package utils import ( "context" "log/slog" "net/http" "os" "strings" ) type traceIDContextKey string const traceIDKey traceIDContextKey = "trace_id" func InitSlog() { level := new(slog.LevelVar) switch strings.ToLower(strings.TrimSpace(os.Getenv("SLOG_LEVEL"))) { case "debug": level.Set(slog.LevelDebug) case "warn": level.Set(slog.LevelWarn) case "error": level.Set(slog.LevelError) default: level.Set(slog.LevelInfo) } handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ Level: level, AddSource: false, }) slog.SetDefault(slog.New(handler).With("app", "bssapp-backend")) } func TraceIDFromRequest(r *http.Request) string { if r == nil { return "" } candidates := []string{ strings.TrimSpace(r.Header.Get("X-Trace-ID")), strings.TrimSpace(r.URL.Query().Get("trace_id")), strings.TrimSpace(r.Header.Get("X-Request-ID")), } for _, candidate := range candidates { if candidate != "" { return candidate } } return "" } func ContextWithTraceID(ctx context.Context, traceID string) context.Context { traceID = strings.TrimSpace(traceID) if ctx == nil || traceID == "" { return ctx } return context.WithValue(ctx, traceIDKey, traceID) } func TraceIDFromContext(ctx context.Context) string { if ctx == nil { return "" } value, _ := ctx.Value(traceIDKey).(string) return strings.TrimSpace(value) } func SlogFromContext(ctx context.Context) *slog.Logger { traceID := TraceIDFromContext(ctx) if traceID == "" { return slog.Default() } return slog.Default().With("trace_id", traceID) }