Major changes: - Add internal/logging package with field constants, context propagation, sensitive data auto-redaction, and per-component log levels - Add worker timeout constants (TimeoutQuickOp, TimeoutHealthCheck, etc.) - Extend SDLC with callback handlers, generate endpoints, and executor - Add new cookbook trees for aeries and slackpath progression - Add skeleton templates for queue, realtime, and microservices - Add worker component template with async job processing - Refactor services and handlers to use new logging infrastructure - Split component.go into component_infra.go and component_listing.go Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
91 lines
2.4 KiB
Go
91 lines
2.4 KiB
Go
package logging
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/orchard9/rdev/internal/envutil"
|
|
)
|
|
|
|
// Config holds logging configuration.
|
|
type Config struct {
|
|
// Level is the default log level.
|
|
Level Level
|
|
|
|
// Format is the output format (json or text).
|
|
Format Format
|
|
|
|
// ComponentLevels overrides log levels per component.
|
|
// Example: {"handlers": LevelDebug, "worker": LevelWarn}
|
|
ComponentLevels map[string]Level
|
|
|
|
// RedactEnabled enables automatic redaction of sensitive data.
|
|
RedactEnabled bool
|
|
|
|
// AddSource adds source file/line to log entries (performance impact).
|
|
AddSource bool
|
|
}
|
|
|
|
// DefaultConfig returns sensible defaults for production.
|
|
func DefaultConfig() Config {
|
|
return Config{
|
|
Level: LevelInfo,
|
|
Format: FormatJSON,
|
|
ComponentLevels: make(map[string]Level),
|
|
RedactEnabled: true,
|
|
AddSource: false,
|
|
}
|
|
}
|
|
|
|
// ConfigFromEnv creates a Config from environment variables.
|
|
//
|
|
// Environment variables:
|
|
// - LOG_LEVEL: default level (debug, info, warn, error)
|
|
// - LOG_FORMAT: output format (json, text)
|
|
// - LOG_LEVELS: per-component levels (handlers:debug,worker:warn)
|
|
// - LOG_REDACT: enable/disable sensitive data redaction (true/false)
|
|
// - LOG_SOURCE: add source file/line to logs (true/false)
|
|
func ConfigFromEnv() Config {
|
|
cfg := DefaultConfig()
|
|
|
|
cfg.Level = ParseLevel(envutil.GetEnv("LOG_LEVEL", "info"))
|
|
cfg.Format = ParseFormat(envutil.GetEnv("LOG_FORMAT", "json"))
|
|
cfg.RedactEnabled = envutil.GetEnvBool("LOG_REDACT", true)
|
|
cfg.AddSource = envutil.GetEnvBool("LOG_SOURCE", false)
|
|
|
|
// Parse per-component log levels: "handlers:debug,worker:warn"
|
|
if levels := envutil.GetEnv("LOG_LEVELS", ""); levels != "" {
|
|
cfg.ComponentLevels = parseComponentLevels(levels)
|
|
}
|
|
|
|
return cfg
|
|
}
|
|
|
|
// parseComponentLevels parses a comma-separated list of component:level pairs.
|
|
func parseComponentLevels(s string) map[string]Level {
|
|
result := make(map[string]Level)
|
|
for pair := range strings.SplitSeq(s, ",") {
|
|
pair = strings.TrimSpace(pair)
|
|
if pair == "" {
|
|
continue
|
|
}
|
|
parts := strings.SplitN(pair, ":", 2)
|
|
if len(parts) != 2 {
|
|
continue
|
|
}
|
|
component := strings.TrimSpace(parts[0])
|
|
level := ParseLevel(parts[1])
|
|
if component != "" {
|
|
result[component] = level
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// LevelFor returns the log level for a component, falling back to the default.
|
|
func (c Config) LevelFor(component string) Level {
|
|
if level, ok := c.ComponentLevels[component]; ok {
|
|
return level
|
|
}
|
|
return c.Level
|
|
}
|