refactor(log): unified schema — mandatory type/class/method, request_id removed
Every log record now carries type ('http' for the request middleware
line, 'wrapper' for garmin execute() calls and forwarded wrapper.py
stderr, 'app' for everything else), class (Go type with package, or the
package/module for free functions), and method (the emitting Go/Python
function -- wrapper.py stamps it automatically, so its msg prefixes are
gone). msg is optional and omitted when empty; the redundant messages
('HTTP request', 'wrapper call', 'garmin wrapper stderr') are dropped,
the HTTP verb moves to http_method, source=garmin-wrapper is replaced by
type=wrapper, and the request_id middleware plumbing (applog
WithLogger/FromContext) is removed. applog.App(class, method) is the
tagging helper for app records.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,6 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"geniusrun/backend/internal/auth"
|
||||
@@ -162,19 +161,12 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
var requestIDCounter atomic.Int64
|
||||
|
||||
// loggingMiddleware logs one JSON line per HTTP request (method,
|
||||
// path, status, duration) and attaches a per-request logger (tagged with a
|
||||
// request_id) to the request context, so any downstream call this request
|
||||
// triggers -- e.g. a Garmin wrapper round-trip -- logs with the same
|
||||
// correlating id (see internal/applog, internal/garmin's roundTrip).
|
||||
// loggingMiddleware logs one type=http JSON line per HTTP request. The
|
||||
// record's meaning is fully carried by its fields (http_method, path,
|
||||
// status, duration_ms), so it has no msg; "method" stays reserved for the
|
||||
// emitting function per the log schema, hence http_method for the verb.
|
||||
func loggingMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
id := fmt.Sprintf("req-%d", requestIDCounter.Add(1))
|
||||
logger := applog.FromContext(r.Context()).With("request_id", id)
|
||||
r = r.WithContext(applog.WithLogger(r.Context(), logger))
|
||||
|
||||
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
|
||||
start := time.Now()
|
||||
next.ServeHTTP(ww, r)
|
||||
@@ -183,8 +175,11 @@ func loggingMiddleware(next http.Handler) http.Handler {
|
||||
if ww.Status() >= 500 {
|
||||
level = slog.LevelWarn
|
||||
}
|
||||
logger.LogAttrs(r.Context(), level, "HTTP request",
|
||||
slog.String("method", r.Method),
|
||||
slog.Default().LogAttrs(r.Context(), level, "",
|
||||
slog.String("type", "http"),
|
||||
slog.String("class", "api"),
|
||||
slog.String("method", "loggingMiddleware"),
|
||||
slog.String("http_method", r.Method),
|
||||
slog.String("path", r.URL.Path),
|
||||
slog.Int("status", ww.Status()),
|
||||
slog.Int64("duration_ms", time.Since(start).Milliseconds()),
|
||||
@@ -261,7 +256,7 @@ func (s *Server) removeUserClient(userID int64) {
|
||||
|
||||
if ok {
|
||||
if err := client.Close(); err != nil {
|
||||
slog.Error("close garmin client for deleted user", "user_id", userID, "error", err)
|
||||
applog.App("api.Server", "removeUserClient").Error("close garmin client for deleted user", "user_id", userID, "error", err)
|
||||
}
|
||||
}
|
||||
if s.ClientConfig.TokenStorePath == "" {
|
||||
@@ -269,7 +264,7 @@ func (s *Server) removeUserClient(userID int64) {
|
||||
}
|
||||
tokenStoreDir := filepath.Join(s.ClientConfig.TokenStorePath, strconv.FormatInt(userID, 10))
|
||||
if err := os.RemoveAll(tokenStoreDir); err != nil {
|
||||
slog.Error("remove token store dir for deleted user", "user_id", userID, "error", err)
|
||||
applog.App("api.Server", "removeUserClient").Error("remove token store dir for deleted user", "user_id", userID, "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,7 +311,7 @@ func (s *Server) backgroundSync(userID int64, fn func(ctx context.Context) error
|
||||
s.mu.Unlock()
|
||||
}()
|
||||
if err := fn(context.Background()); err != nil {
|
||||
slog.Error("background sync failed", "user_id", userID, "error", err)
|
||||
applog.App("api.Server", "backgroundSync").Error("background sync failed", "user_id", userID, "error", err)
|
||||
}
|
||||
}()
|
||||
return true
|
||||
@@ -336,7 +331,7 @@ func writeJSON(w http.ResponseWriter, status int, v any) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
if err := json.NewEncoder(w).Encode(v); err != nil {
|
||||
slog.Error("encode response", "error", err)
|
||||
applog.App("api", "writeJSON").Error("encode response", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user