Add Sentry Logs for the backend and SSR frontend - #1336
Merged
Conversation
Ships Laravel `Log::` calls to Sentry Logs via the sentry_logs Monolog channel, and console output from the SSR server via consoleLoggingIntegration. Both services share one env contract: SENTRY_ENVIRONMENT, SENTRY_RELEASE, SENTRY_ENABLE_LOGS and SENTRY_LOG_LEVEL mean the same thing on each side. Backend: - Add the sentry_logs channel and make the stack channel list env-driven via LOG_STACK, tolerating empty and whitespace-padded values so a misconfigured stack cannot silently fall back to the emergency logger. - Coerce SENTRY_ENABLE_LOGS with filter_var. Sentry's OptionsResolver requires a real bool, so SENTRY_ENABLE_LOGS=1 previously threw InvalidOptionsException during boot. Frontend: - Load dotenv inside instrument.mjs. Because it runs via --import it was evaluated before server.js loaded dotenv, so SENTRY_SSR_DSN in .env was never visible and Sentry silently never initialised. - Gate enableLogs on SENTRY_ENABLE_LOGS and filter by SENTRY_LOG_LEVEL, accepting Monolog level names so both services behave identically. - Warn at boot when SENTRY_ENVIRONMENT is unset instead of silently reporting staging traffic as production. - Replace deprecated sendDefaultPii with dataCollection, disabling every category. The new defaults collect cookies and headers, and the SSR server reads a JWT from req.cookies.token. Also wires SENTRY_RELEASE from github.sha on Vapor deploys and removes .do/app.yaml, a stale app spec describing infrastructure no longer in use.
railway-app
Bot
temporarily deployed
to
Hi.Events / Hi.Events-pr-1336
September 5, 2026 08:15
Destroyed
|
π Deployed to the Hi.Events-pr-1336 environment in Hi.Events
1 service not affected by this PR
|
Contributor
β E2E Β· smoke
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ships application logs to Sentry Logs from both services, behind a single env contract.
The backend already had
sentry/sentry-laravel4.25.1, which includes the Logs feature as a Monolog handler β so every existingLog::call ships with no call-site changes. The SSR side gains the equivalent viaconsoleLoggingIntegration.Nothing is enabled by default.
SENTRY_ENABLE_LOGSdefaults tofalseand self-hosted installs have no Sentry DSN wired at all, so their behaviour is byte-identical to today.Env contract
Same names and values on both sides, so a deployment sets them once:
SENTRY_DSN/SENTRY_SSR_DSNSENTRY_ENVIRONMENTAPP_ENV)SENTRY_RELEASEgithub.sha)SENTRY_ENABLE_LOGSSENTRY_LOG_LEVELSENTRY_TRACES_SAMPLE_RATESENTRY_LOG_LEVELaccepts Monolog level names on both sides (warningβwarn,criticalβfatal), so one value means the same thing in each service.Bugs fixed along the way
SENTRY_ENABLE_LOGS=1crashed the app at boot. Laravel'senv()leaves"1"a string and Sentry'sOptionsResolverrequires a real bool, soClientBuilder::create()threwInvalidOptionsExceptionbefore the app could serve a request. Now coerced withfilter_var.An empty
LOG_STACKsilently killed all logging.explode(',', '')yields[""], andLogManager::get()swallows the resulting exception and falls back to the emergency logger β so logs would vanish fromdocker logsinto a container-layer file with no error. Now sanitised with a fallback tosingle.The SSR instrumentation never initialised from
.env.instrument.mjsruns vianode --import, which is evaluated beforeserver.jsimportsdotenv/configβ soSENTRY_SSR_DSNin.envwas invisible and Sentry silently did nothing locally. Fixed by importing dotenv first.Deprecated
sendDefaultPiireplaced withdataCollection. It's removed in v11, and a naive swap would have been worse than the status quo:dataCollectiondefaults to collecting cookies, headers and request bodies.server.jsreads a JWT fromreq.cookies.token, so every category is now explicitly disabled.Staging would have reported as
production.SENTRY_ENVIRONMENTappeared nowhere in the repo, andyarn starthardcodesNODE_ENV=productionviacross-env, so both DO apps would have landed in the same bucket. It's now required, with a loud boot warning when missing.Also
SENTRY_RELEASEwired fromgithub.shaon Vapor deploys..do/app.yamldeleted β a stale spec describingdemo.hi.eventswith the backend on DigitalOcean and Postgres 12, none of which is current. Nothing referenced it; the README deploy buttons point at the separateHiEventsDev/hi.events-digitaloceanrepo, and the live DO apps are driven by ID through the API.Verification
SENTRY_LOG_LEVELspelling including invalid input, release and traces set, plus the Docker shape (vars injected, no.envon disk).APP_ENVcorrectly drives the backend's Sentry environment, and that an explicitSENTRY_ENVIRONMENToverrides it.--testsuite=Unit: 1127 tests, no failures.pintpasses.tsc --noEmitclean for the touched files.Deploy notes
php artisan optimizeinvapor.yml), so these take effect on the next deploy, not on an env update β and there is no fast kill switch during an incident.SENTRY_SSR_DSNandSENTRY_ENVIRONMENTatRUN_TIMEscope.@sentry/nodepulls in OpenTelemetry (~15 transitive packages, including module-loader patching viaimport-in-the-middle) β worth a look at SSR cold-start before this goes to production.Not included
No browser-side Sentry β this covers the SSR process only, so client-side React errors are still uncaptured. Adding the browser SDK means bundle size, source map upload and PII decisions, so it belongs in its own change. Source maps are likewise not uploaded, which means SSR render stack traces will be minified.