7b6624ecc3
redesigned the project sharing popup to be a multi select dropdown that populates the options by using the input as a fuzzy search filter on the current users & invited users. users can now also be directly invited by email from the project share window. if invited this way, then the user will receive an email that sends them to a registration page, then a confirmation page. the initial registration was always redone so that it uses a similar system to the above in that it now will accept the first registered user if there are no other accounts (besides 'system').
90 lines
2.6 KiB
Go
90 lines
2.6 KiB
Go
package logger
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/go-chi/chi/middleware"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// NewStructuredLogger creates a new logger for chi router
|
|
func NewStructuredLogger(logger *logrus.Logger) func(next http.Handler) http.Handler {
|
|
return middleware.RequestLogger(&StructuredLogger{logger})
|
|
}
|
|
|
|
// StructuredLogger is a logger for chi router
|
|
type StructuredLogger struct {
|
|
Logger *logrus.Logger
|
|
}
|
|
|
|
// NewLogEntry creates a new log entry for the given HTTP request
|
|
func (l *StructuredLogger) NewLogEntry(r *http.Request) middleware.LogEntry {
|
|
entry := &StructuredLoggerEntry{Logger: logrus.NewEntry(l.Logger)}
|
|
logFields := logrus.Fields{}
|
|
|
|
if reqID := middleware.GetReqID(r.Context()); reqID != "" {
|
|
logFields["req_id"] = reqID
|
|
}
|
|
|
|
scheme := "http"
|
|
if r.TLS != nil {
|
|
scheme = "https"
|
|
}
|
|
logFields["http_scheme"] = scheme
|
|
logFields["http_proto"] = r.Proto
|
|
logFields["http_method"] = r.Method
|
|
|
|
logFields["remote_addr"] = r.RemoteAddr
|
|
logFields["user_agent"] = r.UserAgent()
|
|
|
|
logFields["uri"] = fmt.Sprintf("%s://%s%s", scheme, r.Host, r.RequestURI)
|
|
|
|
entry.Logger = entry.Logger.WithFields(logFields)
|
|
|
|
return entry
|
|
}
|
|
|
|
// StructuredLoggerEntry is a log entry will all relevant information about a specific http request
|
|
type StructuredLoggerEntry struct {
|
|
Logger logrus.FieldLogger
|
|
}
|
|
|
|
// Write logs information about http request response body
|
|
func (l *StructuredLoggerEntry) Write(status, bytes int, elapsed time.Duration) {
|
|
l.Logger = l.Logger.WithFields(logrus.Fields{
|
|
"resp_status": status, "resp_bytes_length": bytes,
|
|
"resp_elapsed_ms": float64(elapsed.Nanoseconds()) / 1000000.0,
|
|
})
|
|
l.Logger.Debugln("request complete")
|
|
}
|
|
|
|
// Panic logs if the request panics
|
|
func (l *StructuredLoggerEntry) Panic(v interface{}, stack []byte) {
|
|
l.Logger = l.Logger.WithFields(logrus.Fields{
|
|
"stack": string(stack),
|
|
"panic": fmt.Sprintf("%+v", v),
|
|
})
|
|
}
|
|
|
|
// GetLogEntry helper function for getting log entry for request
|
|
func GetLogEntry(r *http.Request) logrus.FieldLogger {
|
|
entry := middleware.GetLogEntry(r).(*StructuredLoggerEntry)
|
|
return entry.Logger
|
|
}
|
|
|
|
// LogEntrySetField sets a key's value
|
|
func LogEntrySetField(r *http.Request, key string, value interface{}) {
|
|
if entry, ok := r.Context().Value(middleware.LogEntryCtxKey).(*StructuredLoggerEntry); ok {
|
|
entry.Logger = entry.Logger.WithField(key, value)
|
|
}
|
|
}
|
|
|
|
// LogEntrySetFields sets the log entry's fields
|
|
func LogEntrySetFields(r *http.Request, fields map[string]interface{}) {
|
|
if entry, ok := r.Context().Value(middleware.LogEntryCtxKey).(*StructuredLoggerEntry); ok {
|
|
entry.Logger = entry.Logger.WithFields(fields)
|
|
}
|
|
}
|