59 lines
1.7 KiB
Go
59 lines
1.7 KiB
Go
// Package flog is a structured logger formatted for GCP Cloud Logging.
|
|
//
|
|
// The API mirrors log/slog: a message string followed by alternating key/value
|
|
// pairs. Each kv pair becomes a JSON field in the emitted record, which Cloud
|
|
// Logging promotes to a queryable jsonPayload field.
|
|
//
|
|
// flog.Info("particle processed", "particleID", id, "elapsed", dt)
|
|
package flog
|
|
|
|
import (
|
|
"os"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Prepares global logger for GCP Cloud Logging's quirks
|
|
var log = func() *logrus.Logger {
|
|
logger := logrus.New()
|
|
logger.SetFormatter(&logrus.JSONFormatter{
|
|
FieldMap: logrus.FieldMap{
|
|
logrus.FieldKeyLevel: "severity",
|
|
logrus.FieldKeyMsg: "message",
|
|
logrus.FieldKeyTime: "timestamp",
|
|
},
|
|
})
|
|
logger.SetOutput(os.Stderr)
|
|
logger.SetLevel(logrus.DebugLevel)
|
|
return logger
|
|
}()
|
|
|
|
// fields converts alternating key/value args into a logrus.Fields map. A
|
|
// trailing odd arg or non-string key is stored under "!BADKEY" to match
|
|
// slog's behavior.
|
|
func fields(args []any) logrus.Fields {
|
|
if len(args) == 0 {
|
|
return nil
|
|
}
|
|
f := make(logrus.Fields, len(args)/2+1)
|
|
for i := 0; i < len(args); i += 2 {
|
|
if i+1 >= len(args) {
|
|
f["!BADKEY"] = args[i]
|
|
break
|
|
}
|
|
key, ok := args[i].(string)
|
|
if !ok {
|
|
f["!BADKEY"] = args[i]
|
|
continue
|
|
}
|
|
f[key] = args[i+1]
|
|
}
|
|
return f
|
|
}
|
|
|
|
func Debug(msg string, args ...any) { log.WithFields(fields(args)).Debug(msg) }
|
|
func Info(msg string, args ...any) { log.WithFields(fields(args)).Info(msg) }
|
|
func Warn(msg string, args ...any) { log.WithFields(fields(args)).Warn(msg) }
|
|
func Error(msg string, args ...any) { log.WithFields(fields(args)).Error(msg) }
|
|
func Fatal(msg string, args ...any) { log.WithFields(fields(args)).Fatal(msg) }
|