mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
af77876306
Go version changed to 1.14.4 Golangci-lint changed to 1.26.0 Bazel version changed to 3.0.0 Bazel rules_go version changed to 0.23.3 Bazel gazelle version changed to v0.21.0 Bazel build tools version changed to 0.25.1 Bazel skylib version changed to 1.0.2
116 lines
2.3 KiB
Go
116 lines
2.3 KiB
Go
package log
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/gorilla/mux"
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
// Logger extends zerolog's Logger.
|
|
type Logger struct {
|
|
zerolog.Logger
|
|
}
|
|
|
|
func (l Logger) Println(v ...interface{}) {
|
|
l.Logger.Error().Msg("panic recovered")
|
|
}
|
|
|
|
func NewLogger(level string, output string) Logger {
|
|
zerolog.TimeFieldFormat = time.RFC3339Nano
|
|
lvl, err := zerolog.ParseLevel(level)
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
zerolog.SetGlobalLevel(lvl)
|
|
|
|
var log zerolog.Logger
|
|
|
|
if output == "" {
|
|
log = zerolog.New(os.Stdout)
|
|
} else {
|
|
file, err := os.OpenFile(output, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
log = zerolog.New(file)
|
|
}
|
|
|
|
return Logger{Logger: log.With().Caller().Timestamp().Logger()}
|
|
}
|
|
|
|
type statusWriter struct {
|
|
http.ResponseWriter
|
|
status int
|
|
length int
|
|
}
|
|
|
|
func (w *statusWriter) WriteHeader(status int) {
|
|
w.status = status
|
|
w.ResponseWriter.WriteHeader(status)
|
|
}
|
|
|
|
func (w *statusWriter) Write(b []byte) (int, error) {
|
|
if w.status == 0 {
|
|
w.status = 200
|
|
}
|
|
|
|
n, err := w.ResponseWriter.Write(b)
|
|
w.length += n
|
|
|
|
return n, err
|
|
}
|
|
|
|
func SessionLogger(log Logger) mux.MiddlewareFunc {
|
|
l := log.With().Str("module", "http").Logger()
|
|
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// Start timer
|
|
start := time.Now()
|
|
path := r.URL.Path
|
|
raw := r.URL.RawQuery
|
|
|
|
sw := statusWriter{ResponseWriter: w}
|
|
|
|
// Process request
|
|
next.ServeHTTP(&sw, r)
|
|
|
|
// Stop timer
|
|
end := time.Now()
|
|
latency := end.Sub(start)
|
|
if latency > time.Minute {
|
|
// Truncate in a golang < 1.8 safe way
|
|
latency -= latency % time.Second
|
|
}
|
|
clientIP := r.RemoteAddr
|
|
method := r.Method
|
|
headers := map[string][]string{}
|
|
for key, value := range r.Header {
|
|
if key == "Authorization" { // anonymize from logs
|
|
value = []string{"******"}
|
|
}
|
|
headers[key] = value
|
|
}
|
|
statusCode := sw.status
|
|
bodySize := sw.length
|
|
if raw != "" {
|
|
path = path + "?" + raw
|
|
}
|
|
|
|
l.Info().
|
|
Str("clientIP", clientIP).
|
|
Str("method", method).
|
|
Str("path", path).
|
|
Int("statusCode", statusCode).
|
|
Str("latency", latency.String()).
|
|
Int("bodySize", bodySize).
|
|
Interface("headers", headers).
|
|
Msg("HTTP API")
|
|
})
|
|
}
|
|
}
|