Backend observability: fx logs bypass slog, Identify() is dead, Sentry/Prometheus config is parsed but unwired #27
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The backend parses configuration for three observability features that do not exist, and part of its own logging escapes the structured logger. Verified on
mainatfbfe1df.1. fx's own logging bypasses slog entirely
backend/cmd/netwatch-server/main.go:29-41callsfx.New(...)with nofx.WithLogger(...). fx therefore falls back to its built-in console logger, writing unstructured plain text to stderr for every provide, invoke, and lifecycle hook, plus all shutdown output.CODE_STYLEGUIDE.md: "For services/servers, log JSON to stdout... Use structured logging whenever possible." Today a production deployment's log stream is a mix of clean JSON frominternal/loggerand unparseable plain text from fx.Side effect:
go.uber.org/zap v1.26.0(go.mod:26) is linked into the binary purely as fx's default logger backend. No application code imports it. Bridging fx to slog removes zap's runtime role.2.
logger.Identify()is dead codeinternal/logger/logger.go:79-85definesIdentify(), which logs appname, version, and buildarch. Grepping the backend finds only the definition — no call site.CODE_STYLEGUIDE_GO.md: "Embed the git commit hash into the binary and include it in startup logs and in health check output." The version does reach the logs by accident viainternal/server/http.go:29-33("http begin listen" carriesversionandbuildarch), butappnamenever does, and the intended identification line never fires.3. Three config values are parsed and never read
internal/config/config.goloadsSENTRY_DSN,METRICS_USERNAME, andMETRICS_PASSWORDinto theConfigstruct. Nothing reads any of them.GO_HTTP_SERVER_CONVENTIONS.mdlists these as mandatory libraries and specifies the wiring:github.com/getsentry/sentry-go— conditional init onSENTRY_DSN,sentryhttpmiddleware withRepanic: true,sentry.Flush(2*time.Second)on shutdown.github.com/prometheus/client_golang+github.com/slok/go-http-metrics+github.com/99designs/basicauth-go—Metrics()middleware and a basic-auth-protectedGET /metrics.None are in
go.mod.internal/middleware/middleware.gohas noMetrics()orMetricsAuth().internal/server/routes.goregisters no/metricsroute. TheServerstruct (server.go:37-47) omits thesentryEnabledfield the conventions doc specifies.backend/README.md:61already lists Prometheus metrics as an open TODO.4. Healthcheck JSON keys violate the snake_case rule
internal/healthcheck/healthcheck.go:39-40emitsuptimeHumananduptimeSeconds.CODE_STYLEGUIDE_GO.md: "Use snake_case for JSON keys."GO_HTTP_SERVER_CONVENTIONS.mdindependently specifiesuptime_secondsanduptime_human. Both authorities agree; the code disagrees with both.Also divergent, same file: the type is
Responserather thanHealthcheckResponse, the method isCheck()rather thanHealthcheck(), andmaintenance_modeis absent (there is noMAINTENANCE_MODEconfig at all).Correct and not to be regressed: the endpoint path
/.well-known/healthcheck,Content-Type: application/json; charset=utf-8,"status":"ok", HTTP 200, and the git hash reaching the output viaVersion.Definition of done
fx.WithLoggerbridges fx's lifecycle logging into the existing slog logger, so the entire process emits one coherent structured stream. Verify by running the binary non-TTY and confirming every startup and shutdown line is valid JSON.logger.Identify()is called at startup (frommain.goor an fxOnStart), or deleted if genuinely unwanted. Do not leave it dead.uptime_seconds,uptime_human. Rename the type and method to match the conventions doc while you are in the file.SENTRY_DSN/METRICS_USERNAME/METRICS_PASSWORDconfig entries so the config surface stops advertising features that do not exist./metricsbehind basic auth is cheap, self-hosted, and immediately useful for a monitoring tool. Sentry adds an external dependency and an outbound network egress to a third party for a service with no users yet — if you want it later it is a small, isolated addition.backend/README.md's config table lists exactly the variables that are actually honoured — no more, no fewer. It currently documents 3 of the 6 defined.cd backend && make checkpasses; rootmake checkpasses.TODO.mdupdated in the same commit.(closes #N).Notes on scope and sequencing
1.0.0milestone. It is real compliance debt, but it does not block a first tag, and #25 may reduce its urgency further. Attach it to the milestone if #25 resolves toward shipping the backend.Recovererpanic-logging fix — that belongs to #23, which is already in that file.Implementation requirements
GO_HTTP_SERVER_CONVENTIONS.mdfor fx wiring, middleware shape, and the metrics route pattern.maketargets only; never rawgoinvocations.