From 3bbe8a6901197e06a7430649b990b096245742cc Mon Sep 17 00:00:00 2001 From: Joel Robotham Date: Mon, 30 Mar 2026 14:12:55 +1100 Subject: [PATCH] fix: use structured logging for startup errors after logger init Startup errors after the slog logger is initialized (config loading, metrics, server creation) were using kong's FatalIfErrorf, which writes plain unstructured text to stderr. Log aggregation systems cannot extract a log level from these messages, making them difficult to find and alert on. Switch post-logger-init fatal errors to use slog.ErrorContext so they are emitted as structured logs with a proper ERROR level. Pre-logger errors (HCL parsing, global config) remain on kong since the logger isn't available yet. Amp-Thread-ID: https://ampcode.com/threads/T-019d3c97-9bcd-753d-bea7-bb117983acd6 Co-authored-by: Amp --- cmd/cachewd/main.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/cmd/cachewd/main.go b/cmd/cachewd/main.go index ab45f36..3001f37 100644 --- a/cmd/cachewd/main.go +++ b/cmd/cachewd/main.go @@ -91,27 +91,27 @@ func main() { } mux, err := newMux(ctx, cr, sr, providersConfigHCL, envars) - kctx.FatalIfErrorf(err) + fatalIfError(ctx, logger, err, "Failed to load config") metricsClient, err := metrics.New(ctx, globalConfig.MetricsConfig) - kctx.FatalIfErrorf(err, "failed to create metrics client") + fatalIfError(ctx, logger, err, "Failed to create metrics client") defer func() { if err := metricsClient.Close(); err != nil { - logger.ErrorContext(ctx, "failed to close metrics client", "error", err) + logger.ErrorContext(ctx, "Failed to close metrics client", "error", err) } }() if err := metricsClient.ServeMetrics(ctx); err != nil { - kctx.FatalIfErrorf(err, "failed to start metrics server") + fatalIfError(ctx, logger, err, "Failed to start metrics server") } logger.InfoContext(ctx, "Starting cachewd", "bind", globalConfig.Bind) server, err := newServer(ctx, mux, globalConfig.Bind, globalConfig.MetricsConfig, globalConfig.OPAConfig) - kctx.FatalIfErrorf(err) + fatalIfError(ctx, logger, err, "Failed to create server") err = server.ListenAndServe() - kctx.FatalIfErrorf(err) + fatalIfError(ctx, logger, err, "Server stopped") } func newRegistries(scheduler jobscheduler.Provider, cloneManagerProvider gitclone.ManagerProvider, tokenManagerProvider githubapp.TokenManagerProvider, s3ClientProvider s3client.ClientProvider) (*cache.Registry, *strategy.Registry) { @@ -187,6 +187,14 @@ func newMux(ctx context.Context, cr *cache.Registry, sr *strategy.Registry, prov return handler, nil } +func fatalIfError(ctx context.Context, logger *slog.Logger, err error, msg string) { + if err == nil { + return + } + logger.ErrorContext(ctx, msg, "error", err) + os.Exit(1) +} + // extractPathPrefix extracts the strategy name, path prefix from a request path. // Examples: /git/... -> "git", /gomod/... -> "gomod", /api/v1/... -> "api". func extractPathPrefix(path string) string {