fix(deploy): wire SENTRY_DSN and enable ECS JSON logging for prod (#641) #643
Reference in New Issue
Block a user
Delete Branch "fix/issue-641-sentry-dsn-json-logging"
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?
Closes #641
Summary
docker-compose.prod.yml: AddSENTRY_DSN: ${SENTRY_DSN:-}to backend environment — the variable was already written to.env.stagingbynightly.yml(line 81) but never forwarded into the container, soSentry.captureException()was silently a no-opdocker-compose.prod.yml: AddLOGGING_STRUCTURED_FORMAT_CONSOLE: ecsto backend environment — enables Spring Boot 4.0 ECS JSON structured logging so Loki gets single-entry JSON log lines withlog.levelinstead of 50 separate unlinked stack trace linesloki-logs.json: Update Grafana Loki dashboard query from| logfmtto| jsonto match the new ECS formatAction required before this lands
Set the
SENTRY_DSNsecret in Gitea repository settings → Actions → Secrets with value:https://686ec2daa9bb45dc8e264e1e2727c8a4@glitchtip.archiv.raddatz.cloud/2Test plan
app = backend— confirm logs show as single JSON entries withdetected_levelvisible🏛️ Markus Keller — Software Architect
Verdict: ✅ Approved
Two independent gaps fixed correctly in one PR:
SENTRY_DSNpassthrough (docker-compose.prod.yml)The root cause is clear:
nightly.ymlwrites the secret to.env.staging, but Docker Compose does not auto-inject env-file variables into containers — they must be explicitly declared underenvironment:. The${SENTRY_DSN:-}empty-default pattern is correct: the SDK silently disables itself when the var is empty, so production starts cleanly even before the secret is set.ECS structured logging (
docker-compose.prod.yml+loki-logs.json)LOGGING_STRUCTURED_FORMAT_CONSOLE: ecsis the right lever — it's the Spring Boot 3.4+ property for ECS JSON output. Pairing it with the| jsonparser fix in the Grafana dashboard is necessary and correct;| logfmtwas silently parsing nothing against Spring Boot's plain-text format.No layer boundary concerns. Both fixes are strictly in the infrastructure config layer; no application logic is touched. The change is minimal and precisely scoped to the stated problem.
One note for future PRs: the Grafana dashboard JSON lives in the repo, which is good for reproducibility. If the log schema evolves (new fields added to ECS output), the dashboard queries may need co-updating — worth keeping in mind as the observability setup matures.
👨💻 Felix Brandt — Senior Fullstack Developer
Verdict: ✅ Approved
Pure infra config — no application code changes. The fixes are correct and complete.
docker-compose.prod.ymlSENTRY_DSN: ${SENTRY_DSN:-}properly threads the Gitea secret through compose substitution into the container. Theapplication.yamlbindingsentry.dsn: ${SENTRY_DSN:}then picks it up via Spring's env-var interpolation.LOGGING_STRUCTURED_FORMAT_CONSOLE: ecsis the correct Spring Boot env var. This is a first-class Spring Boot 3.4+ feature, not a workaround — it activates the bundled ECS encoder on the console appender.loki-logs.json| jsonis required for ECS output (which is structured JSON). The old| logfmtparser was a silent no-op against Spring Boot's%d{…} %-5level …text pattern.count_over_timewithout a parser — that's fine; it doesn't need to parse fields.Nothing to block on. Ship it.
🛠️ Tobias Wendt — DevOps / Infrastructure
Verdict: ✅ Approved
This directly touches the production deployment config, so I reviewed it closely.
What's correct:
SENTRY_DSN: ${SENTRY_DSN:-}uses an empty default (:-) — the backend starts cleanly whether or not the secret is set. No compose startup abort. Good defensive default.environment:block. Safe.LOGGING_STRUCTURED_FORMAT_CONSOLE: ecsis additive — it only changes the console log format, not log content or level. No regression risk.| jsonupdate: necessary. Without it, Loki returns zero parsed fields, making the dashboard useless even though logs are being stored correctly.Operational note:
The PR description correctly documents the required follow-up: set the
SENTRY_DSNGitea secret before the next nightly deploy. This is the correct workflow — the compose file just wires the variable; the actual secret value lives in Gitea. The suggested deploy order (merge #643 → nightly → verify Sentry active → merge #644 to validate error disappears) is sound.Minor observation:
MANAGEMENT_TRACING_SAMPLING_PROBABILITYalready has a${…:-0.1}default pattern — theSENTRY_DSNaddition follows the same convention consistently. Good.📋 Elicit — Requirements Engineer
Verdict: ✅ Approved
Checking against issue #641 requirements:
SENTRY_DSN: ${SENTRY_DSN:-}added to backendenvironment:${…:-}substitutionThe fix is minimal and precisely scoped to the stated issues. No out-of-scope changes were introduced.
One open action (outside scope of this PR, documented in PR description): the
SENTRY_DSNGitea repository secret must be set to the GlitchTip project DSN before the next nightly deploy for Sentry capture to activate.🔒 Nora "NullX" Steiner — Security Expert
Verdict: ✅ Approved
Reviewed with focus on secret handling and data exposure risk.
SENTRY_DSN: ${SENTRY_DSN:-}https://<key>@host/<project>). It is injected via environment variable, not hardcoded — correct.:-empty fallback is safe: the Sentry SDK disables itself silently, rather than crashing or leaking.LOGGING_STRUCTURED_FORMAT_CONSOLE: ecsloki-logs.jsonNo security blockers.
🧪 Sara Holt — QA / Tester
Verdict: ✅ Approved
Infrastructure config changes — no unit/integration tests applicable. Validation is deployment-time.
Test plan for after merge + nightly deploy:
Verify SENTRY_DSN reaches the container
Expected:
SENTRY_DSN=https://...@glitchtip.archiv.raddatz.cloud/2Verify ECS JSON logging is active
Expected: lines starting with
{(JSON), not2026-05-20 …(plain text)Verify Loki ingests structured logs
{job="archiv-staging-backend-1"} | json | level="INFO"level,message,@timestampfieldsVerify GlitchTip receives errors (after PR #644 is also merged and the 500 is confirmed fixed — but test the pipeline with a known error first)
https://glitchtip.archiv.raddatz.cloudfor the new eventNote: The
SENTRY_DSNGitea secret must be set before step 1 will pass.🎨 Leonie Voss — UI / UX Expert
Verdict: ✅ Approved
This is a pure infrastructure and observability config change — no frontend code, no UI components, no user-facing behavior is affected. Users will not see any change.
The indirect benefit is that once the Grafana dashboard is functional and GlitchTip receives errors, developers get faster feedback loops when UI-breaking backend errors occur. That's a positive for the overall development experience.
Nothing to flag from a UI perspective. LGTM.