mirror of
https://github.com/ipfs/kubo.git
synced 2025-08-23 09:52:08 +08:00

* chore: update to go-log/v2 go-log v2 has been out for quite a while now and it is time to deprecate v1. Replace all use of go-log with go-log/v2 Makes /api/v0/log/tail useful over HTTP Updates dependencies that have moved to go-lov/v2 Removes support for ContextWithLoggable as this is not needed for tracing-like functionality - Replaces: PR #8765 - Closes issue #8753 - Closes issue #9245 - Closes issue #10809 Other fixes: * update go-ipfs-cmds * update http logs test * fix test * Read/send one line of log data at a time * Update -log-level docs
70 lines
1.7 KiB
Go
70 lines
1.7 KiB
Go
package corehttp
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
|
|
logging "github.com/ipfs/go-log/v2"
|
|
core "github.com/ipfs/kubo/core"
|
|
)
|
|
|
|
func LogOption() ServeOption {
|
|
return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
|
|
mux.HandleFunc("/logs", func(w http.ResponseWriter, r *http.Request) {
|
|
// The log data comes from an io.Reader, and we need to constantly
|
|
// read from it and then write to the HTTP response.
|
|
pipeReader := logging.NewPipeReader()
|
|
done := make(chan struct{})
|
|
|
|
// Close the pipe reader if the request context is canceled. This
|
|
// is necessary to avoiding blocking on reading from the pipe
|
|
// reader when the client terminates the request.
|
|
go func() {
|
|
select {
|
|
case <-r.Context().Done(): // Client canceled request
|
|
case <-n.Context().Done(): // Node shutdown
|
|
case <-done: // log reader goroutine exitex
|
|
}
|
|
pipeReader.Close()
|
|
}()
|
|
|
|
errs := make(chan error, 1)
|
|
|
|
go func() {
|
|
defer close(errs)
|
|
defer close(done)
|
|
|
|
rdr := bufio.NewReader(pipeReader)
|
|
for {
|
|
// Read a line of log data and send it to the client.
|
|
line, err := rdr.ReadString('\n')
|
|
if err != nil {
|
|
errs <- fmt.Errorf("error reading log message: %s", err)
|
|
return
|
|
}
|
|
_, err = w.Write([]byte(line))
|
|
if err != nil {
|
|
// Failed to write to client, probably disconnected.
|
|
return
|
|
}
|
|
if f, ok := w.(http.Flusher); ok {
|
|
f.Flush()
|
|
}
|
|
if r.Context().Err() != nil {
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
log.Info("log API client connected")
|
|
err := <-errs
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
})
|
|
return mux, nil
|
|
}
|
|
}
|