infra: add logging wrapping
Resolves issues with gcp cloud logging quirks such as field names
This commit is contained in:
@@ -2,7 +2,8 @@ package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"log/slog"
|
||||
|
||||
"github.com/flowy-live/llink/internal/utils/flog"
|
||||
)
|
||||
|
||||
// EnvVar enumerates the env vars referenced via this package.
|
||||
@@ -15,7 +16,7 @@ func MustGetEnv[T string | EnvVar](key T) string {
|
||||
keyString := string(key)
|
||||
value := os.Getenv(keyString)
|
||||
if value == "" {
|
||||
slog.Errorf("Missing required environment variable %s", key)
|
||||
flog.Error("missing required environment variable", "key", key)
|
||||
panic("Missing required environment variable")
|
||||
}
|
||||
|
||||
@@ -26,7 +27,7 @@ func MustGetEnv[T string | EnvVar](key T) string {
|
||||
func GetEnv(key string) string {
|
||||
value := os.Getenv(key)
|
||||
if value == "" {
|
||||
slog.Warnf("Missing optional environment variable %s", key)
|
||||
flog.Warn("missing optional environment variable", "key", key)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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) }
|
||||
Reference in New Issue
Block a user