diff --git a/conf/config.example.toml b/conf/config.example.toml index dd7a12a..39db773 100644 --- a/conf/config.example.toml +++ b/conf/config.example.toml @@ -1,7 +1,7 @@ # Unless otherwise noted, every value in this file is the same # as the intrinsic default value. -log-format = "datetime+message" +log-format = "text" [server] # Use "-" to disable the handler. diff --git a/go.mod b/go.mod index c21a21d..25929a9 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 github.com/creasty/defaults v1.8.0 github.com/getsentry/sentry-go v0.35.3 + github.com/getsentry/sentry-go/slog v0.35.3 github.com/go-git/go-billy/v6 v6.0.0-20250627091229-31e2a16eef30 github.com/go-git/go-git/v6 v6.0.0-20250910120214-3a68d0404116 github.com/honeybadger-io/honeybadger-go v0.8.0 @@ -15,6 +16,7 @@ require ( github.com/minio/minio-go/v7 v7.0.95 github.com/pelletier/go-toml/v2 v2.2.4 github.com/prometheus/client_golang v1.23.2 + github.com/samber/slog-multi v1.5.0 github.com/tj/go-redirects v0.0.0-20200911105812-fd1ba1020b37 github.com/valyala/fasttemplate v1.2.2 google.golang.org/protobuf v1.36.9 @@ -50,6 +52,8 @@ require ( github.com/prometheus/common v0.66.1 // indirect github.com/prometheus/procfs v0.16.1 // indirect github.com/rs/xid v1.6.0 // indirect + github.com/samber/lo v1.51.0 // indirect + github.com/samber/slog-common v0.19.0 // indirect github.com/sergi/go-diff v1.4.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/tinylib/msgp v1.3.0 // indirect diff --git a/go.sum b/go.sum index dbc26f2..0ba8181 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/getsentry/sentry-go v0.35.3 h1:u5IJaEqZyPdWqe/hKlBKBBnMTSxB/HenCqF3QLabeds= github.com/getsentry/sentry-go v0.35.3/go.mod h1:mdL49ixwT2yi57k5eh7mpnDyPybixPzlzEJFu0Z76QA= +github.com/getsentry/sentry-go/slog v0.35.3 h1:4MQEfo3U25jxKhrRYMS6wPXpW3WXSrjSRmDQZroalaw= +github.com/getsentry/sentry-go/slog v0.35.3/go.mod h1:BhcfZ6LB5VpHAl6kOKf0Bsy2AXJbTl9Nit9Zq4KApus= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -71,8 +73,9 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/maypok86/otter/v2 v2.2.1 h1:hnGssisMFkdisYcvQ8L019zpYQcdtPse+g0ps2i7cfI= @@ -113,6 +116,12 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI= +github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= +github.com/samber/slog-common v0.19.0 h1:fNcZb8B2uOLooeYwFpAlKjkQTUafdjfqKcwcC89G9YI= +github.com/samber/slog-common v0.19.0/go.mod h1:dTz+YOU76aH007YUU0DffsXNsGFQRQllPQh9XyNoA3M= +github.com/samber/slog-multi v1.5.0 h1:UDRJdsdb0R5vFQFy3l26rpX3rL3FEPJTJ2yKVjoiT1I= +github.com/samber/slog-multi v1.5.0/go.mod h1:im2Zi3mH/ivSY5XDj6LFcKToRIWPw1OcjSVSdXt+2d0= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= diff --git a/src/config.go b/src/config.go index 0b0e1a0..d2caf58 100644 --- a/src/config.go +++ b/src/config.go @@ -37,7 +37,7 @@ func (t *Duration) MarshalText() ([]byte, error) { type Config struct { Insecure bool `toml:"-" env:"insecure"` Features []string `toml:"features"` - LogFormat string `toml:"log-format" default:"datetime+message"` + LogFormat string `toml:"log-format" default:"text"` Server ServerConfig `toml:"server"` Wildcard []WildcardConfig `toml:"wildcard"` Storage StorageConfig `toml:"storage"` diff --git a/src/main.go b/src/main.go index c83d5dc..ec8092a 100644 --- a/src/main.go +++ b/src/main.go @@ -71,9 +71,6 @@ func serve(listener net.Listener, handler http.Handler) { } func main() { - InitObservability() - defer FiniObservability() - printConfigEnvVars := flag.Bool("print-config-env-vars", false, "print every recognized configuration environment variable and exit") printConfig := flag.Bool("print-config", false, @@ -107,12 +104,8 @@ func main() { return } - switch config.LogFormat { - case "message": - log.SetFlags(0) - case "datetime+message": - log.SetFlags(log.Ldate | log.Ltime | log.LUTC) - } + InitObservability() + defer FiniObservability() if len(config.Features) > 0 { log.Println("features:", strings.Join(config.Features, ", ")) diff --git a/src/observe.go b/src/observe.go index 3e778ab..67ffb88 100644 --- a/src/observe.go +++ b/src/observe.go @@ -1,16 +1,22 @@ package main import ( + "context" "log" + "log/slog" "net/http" "os" "runtime/debug" + "strconv" "time" "github.com/honeybadger-io/honeybadger-go" "github.com/getsentry/sentry-go" sentryhttp "github.com/getsentry/sentry-go/http" + sentryslog "github.com/getsentry/sentry-go/slog" + + slogmulti "github.com/samber/slog-multi" ) func hasHoneybadger() bool { @@ -27,6 +33,21 @@ func InitObservability() { environment = value } + logHandlers := []slog.Handler{} + + switch config.LogFormat { + case "none": + // nothing to do + case "text": + logHandlers = append(logHandlers, + slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{})) + case "json": + logHandlers = append(logHandlers, + slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{})) + default: + log.Println("unknown log format", config.LogFormat) + } + if hasHoneybadger() { honeybadger.Configure(honeybadger.Configuration{ Env: environment, @@ -35,13 +56,27 @@ func InitObservability() { } if hasSentry() { + enableLogs := false + if value, err := strconv.ParseBool(os.Getenv("SENTRY_LOGS")); err == nil { + enableLogs = value + } + options := sentry.ClientOptions{} - options.Environment = environment options.Dsn = os.Getenv("SENTRY_DSN") + options.Environment = environment + options.EnableLogs = enableLogs if err := sentry.Init(options); err != nil { log.Fatalf("sentry: %s\n", err) } + + if enableLogs { + logHandlers = append(logHandlers, sentryslog.Option{ + AddSource: true, + }.NewSentryHandler(context.Background())) + } } + + slog.SetDefault(slog.New(slogmulti.Fanout(logHandlers...))) } func FiniObservability() {