Vibe-guided bskyoauth and custom repo example code in Golang 馃 probably not safe to use in prod
at main 3.9 kB view raw
1package bskyoauth 2 3import ( 4 "context" 5 "io" 6 "log/slog" 7 "os" 8 "strings" 9) 10 11// Logger is the package-level logger instance. 12// By default, logs are discarded. Call SetLogger() to enable logging. 13var Logger *slog.Logger = slog.New(slog.NewJSONHandler(io.Discard, nil)) 14 15// SetLogger sets the package-level logger. 16// This should be called during application initialization to enable logging. 17// 18// Example: 19// 20// // Text logging to stdout (development) 21// handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ 22// Level: slog.LevelInfo, 23// }) 24// bskyoauth.SetLogger(slog.New(handler)) 25// 26// // JSON logging to stdout (production) 27// handler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ 28// Level: slog.LevelError, 29// }) 30// bskyoauth.SetLogger(slog.New(handler)) 31func SetLogger(logger *slog.Logger) { 32 if logger != nil { 33 Logger = logger 34 } 35} 36 37// NewDefaultLogger creates a default logger with JSON output to stdout. 38// Useful for quick setup without manual configuration. 39func NewDefaultLogger(level slog.Level) *slog.Logger { 40 return slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ 41 Level: level, 42 })) 43} 44 45// NewTextLogger creates a text logger for development/debugging. 46func NewTextLogger(level slog.Level) *slog.Logger { 47 return slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ 48 Level: level, 49 })) 50} 51 52// LogLevelFromEnv determines the appropriate log level based on environment. 53// Checks BASE_URL to determine if running locally or in production. 54// Returns Info level for localhost, Error level for production. 55func LogLevelFromEnv(baseURL string) slog.Level { 56 // Parse the base URL 57 if baseURL == "" { 58 return slog.LevelError // Default to production (Error level) 59 } 60 61 // Check if localhost 62 if strings.Contains(baseURL, "localhost") || 63 strings.Contains(baseURL, "127.0.0.1") || 64 strings.Contains(baseURL, "[::1]") { 65 return slog.LevelInfo // Development: Info level 66 } 67 68 return slog.LevelError // Production: Error level 69} 70 71// NewLoggerFromEnv creates a logger with appropriate settings based on environment. 72// Uses BASE_URL to determine if running locally (text, Info) or production (JSON, Error). 73// 74// Example: 75// 76// logger := bskyoauth.NewLoggerFromEnv(os.Getenv("BASE_URL")) 77// bskyoauth.SetLogger(logger) 78func NewLoggerFromEnv(baseURL string) *slog.Logger { 79 level := LogLevelFromEnv(baseURL) 80 81 // Localhost: use text format for readability 82 if strings.Contains(baseURL, "localhost") || 83 strings.Contains(baseURL, "127.0.0.1") || 84 strings.Contains(baseURL, "[::1]") { 85 return NewTextLogger(level) 86 } 87 88 // Production: use JSON format for log aggregation 89 return NewDefaultLogger(level) 90} 91 92// contextKey type for context values 93type contextKey string 94 95// WithRequestID adds a request ID to the context for correlation. 96func WithRequestID(ctx context.Context, requestID string) context.Context { 97 return context.WithValue(ctx, ContextKeyRequestID, requestID) 98} 99 100// WithSessionID adds a session ID to the context for correlation. 101func WithSessionID(ctx context.Context, sessionID string) context.Context { 102 return context.WithValue(ctx, ContextKeySessionID, sessionID) 103} 104 105// LoggerFromContext returns a logger with context values attached. 106// Extracts request_id and session_id from context if present. 107func LoggerFromContext(ctx context.Context) *slog.Logger { 108 logger := Logger 109 110 if requestID, ok := ctx.Value(ContextKeyRequestID).(string); ok && requestID != "" { 111 logger = logger.With("request_id", requestID) 112 } 113 114 if sessionID, ok := ctx.Value(ContextKeySessionID).(string); ok && sessionID != "" { 115 logger = logger.With("session_id", sessionID) 116 } 117 118 return logger 119} 120 121// GenerateRequestID generates a unique request ID for correlation. 122// Uses cryptographic randomness for uniqueness. 123func GenerateRequestID() string { 124 return GenerateSessionID() // Reuse session ID generation (already crypto-random) 125}