package middleware import ( "context" "net/http" "server/internal/db" "server/internal/db/sqlc" "server/internal/pkg/safego" "time" ) type AccessLogMiddleware struct { store *db.Store } func NewAccessLogMiddleware(store *db.Store) *AccessLogMiddleware { return &AccessLogMiddleware{ store: store, } } func (m *AccessLogMiddleware) Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { reqCtx := GetRequestContext(r.Context()) userCtx := GetUserContext(r.Context()) rw := NewResponseRecorder(w) next.ServeHTTP(rw, r) // 写入数据库时是null userID := &userCtx.UserID if userCtx.UserID == 0 { userID = nil } durationMs := int32(time.Since(reqCtx.StartTime).Milliseconds()) statusCode := int32(rw.statusCode) // 异步写入 safego.Go(func() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() _ = m.store.Queries.CreateAccessLog(ctx, sqlc.CreateAccessLogParams{ RequestID: &reqCtx.RequestID, UserID: userID, Ip: &reqCtx.ClientIp, UserAgent: &reqCtx.UserAgent, RequestMethod: reqCtx.Method, RequestPath: reqCtx.Path, Message: &rw.errorMsg, Referer: &reqCtx.Referer, StatusCode: &statusCode, ResponseTimeMs: &durationMs, StartedAt: reqCtx.StartTime, }) }) }) }