mirror of
https://github.com/weaveworks/scope.git
synced 2026-05-09 18:57:29 +00:00
Changes: - Default diff-printer to hide details (#103) - da4c3ff - Improve logging of http errors (#115) - f5a1710 - Update httpgrpc to match weaveworks/cortex#910 (#117) - 80ff076 - Expose the HTTP server from the server struct. (#118) - 1a7a6b3 - Add HTTP tracing middleware (#119) - d442d08
71 lines
2.2 KiB
Go
71 lines
2.2 KiB
Go
package middleware
|
|
|
|
import (
|
|
"bytes"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/weaveworks/common/logging"
|
|
"github.com/weaveworks/common/user"
|
|
)
|
|
|
|
// Log middleware logs http requests
|
|
type Log struct {
|
|
Log logging.Interface
|
|
LogRequestHeaders bool // LogRequestHeaders true -> dump http headers at debug log level
|
|
}
|
|
|
|
// logWithRequest information from the request and context as fields.
|
|
func (l Log) logWithRequest(r *http.Request) logging.Interface {
|
|
return user.LogWith(r.Context(), l.Log)
|
|
}
|
|
|
|
// Wrap implements Middleware
|
|
func (l Log) Wrap(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
begin := time.Now()
|
|
uri := r.RequestURI // capture the URI before running next, as it may get rewritten
|
|
// Log headers before running 'next' in case other interceptors change the data.
|
|
headers, err := dumpRequest(r)
|
|
if err != nil {
|
|
headers = nil
|
|
l.logWithRequest(r).Errorf("Could not dump request headers: %v", err)
|
|
}
|
|
var buf bytes.Buffer
|
|
wrapped := newBadResponseLoggingWriter(w, &buf)
|
|
next.ServeHTTP(wrapped, r)
|
|
statusCode := wrapped.statusCode
|
|
if 100 <= statusCode && statusCode < 500 || statusCode == http.StatusBadGateway || statusCode == http.StatusServiceUnavailable {
|
|
l.logWithRequest(r).Debugf("%s %s (%d) %s", r.Method, uri, statusCode, time.Since(begin))
|
|
if l.LogRequestHeaders && headers != nil {
|
|
l.logWithRequest(r).Debugf("ws: %v; %s", IsWSHandshakeRequest(r), string(headers))
|
|
}
|
|
} else {
|
|
l.logWithRequest(r).Warnf("%s %s (%d) %s Response: %q ws: %v; %s",
|
|
r.Method, uri, statusCode, time.Since(begin), buf.Bytes(), IsWSHandshakeRequest(r), headers)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Logging middleware logs each HTTP request method, path, response code and
|
|
// duration for all HTTP requests.
|
|
var Logging = Log{
|
|
Log: logging.Global(),
|
|
}
|
|
|
|
func dumpRequest(req *http.Request) ([]byte, error) {
|
|
var b bytes.Buffer
|
|
|
|
// Exclude some headers for security, or just that we don't need them when debugging
|
|
err := req.Header.WriteSubset(&b, map[string]bool{
|
|
"Cookie": true,
|
|
"X-Csrf-Token": true,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ret := bytes.Replace(b.Bytes(), []byte("\r\n"), []byte("; "), -1)
|
|
return ret, nil
|
|
}
|