diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index ba5d657466699974f475dcf482862bc87e257892..61c5617a1ea9c69e99791842654783ac52accbe8 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -285,6 +285,7 @@ func serveHTTPApi(req cmds.Request) (error, <-chan error) { corehttp.VersionOption(), defaultMux("/debug/vars"), defaultMux("/debug/pprof/"), + corehttp.LogOption(), } if len(cfg.Gateway.RootRedirect) > 0 { diff --git a/core/corehttp/logs.go b/core/corehttp/logs.go new file mode 100644 index 0000000000000000000000000000000000000000..4cdf529ad099e982205148560c4af6cb449d7ac4 --- /dev/null +++ b/core/corehttp/logs.go @@ -0,0 +1,42 @@ +package corehttp + +import ( + "io" + "net/http" + + core "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/thirdparty/eventlog" +) + +type writeErrNotifier struct { + w io.Writer + errs chan error +} + +func newWriteErrNotifier(w io.Writer) (io.Writer, <-chan error) { + ch := make(chan error, 1) + return &writeErrNotifier{ + w: w, + errs: ch, + }, ch +} + +func (w *writeErrNotifier) Write(b []byte) (int, error) { + n, err := w.w.Write(b) + if err != nil { + w.errs <- err + } + return n, err +} + +func LogOption() ServeOption { + return func(n *core.IpfsNode, mux *http.ServeMux) (*http.ServeMux, error) { + mux.HandleFunc("/logs", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + wnf, errs := newWriteErrNotifier(w) + eventlog.WriterGroup.AddWriter(wnf) + <-errs + }) + return mux, nil + } +} diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index d35a3525c5ccd1bba27cf64e8e7bb18cdb7faeaa..4c4735396221c34e8ea236cffe3a74a2a9de476b 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -368,13 +368,7 @@ func (r *FSRepo) openDatastore() error { func configureEventLoggerAtRepoPath(c *config.Config, repoPath string) { eventlog.Configure(eventlog.LevelInfo) eventlog.Configure(eventlog.LdJSONFormatter) - rotateConf := eventlog.LogRotatorConfig{ - Filename: path.Join(repoPath, "logs", "events.log"), - MaxSizeMB: c.Log.MaxSizeMB, - MaxBackups: c.Log.MaxBackups, - MaxAgeDays: c.Log.MaxAgeDays, - } - eventlog.Configure(eventlog.OutputRotatingLogFile(rotateConf)) + eventlog.Configure(eventlog.Output(eventlog.WriterGroup)) } // Close closes the FSRepo, releasing held resources. diff --git a/thirdparty/eventlog/option.go b/thirdparty/eventlog/option.go index 6d297bb3bd953eff6820f31d687e875b13a4d432..bf5219d60e5ee97848f23db9aeee029240b3e884 100644 --- a/thirdparty/eventlog/option.go +++ b/thirdparty/eventlog/option.go @@ -18,6 +18,8 @@ func init() { Configure(LevelError) } +var WriterGroup = new(MirrorWriter) + type Option func() // Configure applies the provided options sequentially from left to right diff --git a/thirdparty/eventlog/writer.go b/thirdparty/eventlog/writer.go new file mode 100644 index 0000000000000000000000000000000000000000..5397fc6853262f8f57e80a5fde07f29e45c998ff --- /dev/null +++ b/thirdparty/eventlog/writer.go @@ -0,0 +1,31 @@ +package eventlog + +import ( + "io" + "sync" +) + +type MirrorWriter struct { + writers []io.Writer + lk sync.Mutex +} + +func (mw *MirrorWriter) Write(b []byte) (int, error) { + mw.lk.Lock() + var filter []io.Writer + for _, w := range mw.writers { + _, err := w.Write(b) + if err == nil { + filter = append(filter, w) + } + } + mw.writers = filter + mw.lk.Unlock() + return len(b), nil +} + +func (mw *MirrorWriter) AddWriter(w io.Writer) { + mw.lk.Lock() + mw.writers = append(mw.writers, w) + mw.lk.Unlock() +}