refactor: emit structured json logs
This commit is contained in:
51
internal/observability/log.go
Normal file
51
internal/observability/log.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package observability
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LogLevel string
|
||||
|
||||
const (
|
||||
LogLevelInfo LogLevel = "info"
|
||||
LogLevelWarn LogLevel = "warn"
|
||||
LogLevelError LogLevel = "error"
|
||||
)
|
||||
|
||||
type LogEvent struct {
|
||||
TS string `json:"ts"`
|
||||
Level LogLevel `json:"level"`
|
||||
Event string `json:"event"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Fields map[string]any `json:"fields,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Component string `json:"component,omitempty"`
|
||||
}
|
||||
|
||||
func LogJSON(level LogLevel, event string, component string, message string, fields map[string]any, err error) {
|
||||
errorValue := ""
|
||||
if err != nil {
|
||||
errorValue = err.Error()
|
||||
}
|
||||
|
||||
entry := LogEvent{
|
||||
TS: time.Now().UTC().Format(time.RFC3339Nano),
|
||||
Level: level,
|
||||
Event: event,
|
||||
Message: message,
|
||||
Fields: fields,
|
||||
Error: errorValue,
|
||||
Component: component,
|
||||
}
|
||||
|
||||
// Best-effort. If encoding fails, fall back to a minimal line.
|
||||
bytes, marshalErr := json.Marshal(entry)
|
||||
if marshalErr != nil {
|
||||
log.Printf("level=%s event=%s component=%s error=%q", level, event, component, marshalErr.Error())
|
||||
return
|
||||
}
|
||||
|
||||
log.Print(string(bytes))
|
||||
}
|
||||
Reference in New Issue
Block a user