package logging import ( "context" "go.uber.org/zap" ) type requestIDContextKey struct{} type adminIDContextKey struct{} // WithRequestID 把请求 ID 写入标准 context,供非 HTTP 层日志关联请求链路。 func WithRequestID(ctx context.Context, requestID string) context.Context { if ctx == nil || requestID == "" { return ctx } return context.WithValue(ctx, requestIDContextKey{}, requestID) } // RequestIDFromContext 从标准 context 读取请求 ID。 func RequestIDFromContext(ctx context.Context) string { if ctx == nil { return "" } value, ok := ctx.Value(requestIDContextKey{}).(string) if !ok { return "" } return value } // WithAdminID 把已完成鉴权的管理员 ID 写入标准 context,供仓储审计和日志关联。 func WithAdminID(ctx context.Context, adminID uint64) context.Context { if ctx == nil || adminID == 0 { return ctx } return context.WithValue(ctx, adminIDContextKey{}, adminID) } // AdminIDFromContext 从标准 context 读取已完成鉴权的管理员 ID。 func AdminIDFromContext(ctx context.Context) uint64 { if ctx == nil { return 0 } adminID, _ := ctx.Value(adminIDContextKey{}).(uint64) return adminID } // FromContext 返回自动携带请求和管理员上下文的日志器。 func FromContext(ctx context.Context) *zap.Logger { logger := zap.L() fields := make([]zap.Field, 0, 2) if requestID := RequestIDFromContext(ctx); requestID != "" { fields = append(fields, zap.String("request_id", requestID)) } if adminID := AdminIDFromContext(ctx); adminID != 0 { fields = append(fields, zap.Uint64("admin_id", adminID)) } if len(fields) == 0 { return logger } return logger.With(fields...) }