WIP: Add Sentry #469
No reviewers
Labels
No labels
Compat/Breaking
Component/Enclave-Builder
Component/Infrastructure
Deploy/BYOC
Deploy/Full-managed
Deploy/Self-hosted
Interface/API
Interface/CLI
Interface/Git
Interface/Web
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority/Critical
Priority/High
Priority/Low
Priority/Medium
Reviewed/Confirmed
Reviewed/Duplicate
Reviewed/Invalid
Reviewed/Won't Fix
Status/Abandoned
Status/Blocked
Status/Need More Info
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
public/platform!469
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "ryansquared/add-sentry"
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?
Sentry review: 6 issues to fix before merge. I've left out the smaller ones; I'm happy to share them separately.
src/sentry-middleware/src/lib.rs:247: an empty or invalidSENTRY_DSNpanics at startup.ClientOptions::dsncallsexpect(sentry-coreclientoptions.rs:311), so a blankSENTRY_DSN=in an env file takes down api, gateway and metering. The doc comment says it returnsNonein that case. Fix: usedsn.parse::<Dsn>().ok()and treat empty or invalid as disabled.lib.rs:393: breadcrumbs leak across requests and users.Arc::new(Hub::current())returns the worker thread's long-lived hub, not a new one.add_breadcrumbadds to it permanently, so a later 5xx on the same thread includes earlier requests' breadcrumbs, such as other users' emails and IDs. Fix:Hub::new_from_top(Hub::current()).src/api/src/main.rs:790: removingerrfrom all 343#[tracing::instrument]attributes drops root causes. The only replacement is oneerror = %errorline inSentryLayer. It logs only the top-level error message, without the underlying cause, and only for 5xx. It also logs under thesentry_middlewaretarget, which the default filters hide.SENTRY_DSNisn't set anywhere, so errors such as sqlx failures are now logged nowhere. Fix: restoreerr, or log the full error chain in the middleware.api/src/main.rs:3115: deploy failures are invisible.deploy_logicruns in atokio::spawnbehind a 200 streaming response, and itsErrbranch only streamsclient_response()to the client. There's no Sentry event and no ERROR log, and the spawned task doesn't inheritREQUEST_ID. Fix: add an explicit log andcapture_errorin that branch.lib.rs:132: PII is sent to Sentry through breadcrumbs. Every INFO/WARN message and its fields go out without scrubbing, which bypassessend_default_pii=false. That includes emails (onboarding.rs:305,webhooks.rs:1173), client IPs (rate_limit.rs:115), and backend URLs inside reqwest errors (proxy.rs:299). Fix: a field allowlist orbefore_breadcrumbscrubbing.lib.rs:366: the globalBREADCRUMBSmap leaks memory. Cleanup runs only afterinner.callfinishes. A client disconnect, cancellation or panic leaves up to 100 breadcrumbs per request in the map forever. Fix: a drop guard, or keep the buffer in the task-local instead.Suggestion: Sentry already ships most of this middleware:
sentry::integrations::tower::{NewSentryLayer, SentryHttpLayer}plussentry::integrations::tracing::layer(). They give each request its own hub, add request context and capture ERROR events. That fixes 2 and 6, and also removes the global lock and the ERROR events that currently go missing. It may be simpler than patching the custom middleware.errremovedPosting here in addition to elsewhere: Sentry's integrations are not enough, as they aren't Tokio task aware. In Sentry, breadcrumbs are tracked thread_local, but tasks are Send + Sync, which means that, at any point after a
.await, you might accidentally gain, lose, or whatever else a bunch of breadcrumbs. That's the reason I went with a custom middleware. I don't think we care about leaking BREADCRUMBS at this point in time, and if we hit memory issues, we can add a cleaner in the future.We don't have automata for Sentry events yet so I'm not sure how concerned we should be about PII. If we don't have that, we could lose critical information about what's happened. Requesting feedback on what's acceptable there.
The rebase includes a fix for deploy failures.
We can add
#[tracing::instrument(err(Debug))]on handlers to print logs of all errors in a function. Debug repr prints out sources, so we get a full stack. However, sending the error through Sentry should capture the entire chain.Fixed.
Expected. What if it's not set properly? We're not gonna notice it in Sentry.
Thanks, the rest LGTM. A few notes:
Tokio / thread-local hubs (not a blocker): I don't think that's right.
sentry-towerattaches the per-request hub to the request future (Hub::run+fut.bind_hub(hub), sentry-tower 0.49.3lib.rs:277-280).SentryFuture::pollswaps that hub into the thread-local on every poll (sentry-corefutures.rs:34-41).sentry-tracingbreadcrumbs go to the current hub (layer/mod.rs:277), so they follow the task across.awaits and threads. Fine to keep the custom middleware for now. Two real caveats:tokio::spawnneeds an explicit.bind_hub(), same as yourREQUEST_IDre-scope in deploy.new_from_top()copies the worker thread's hub, so breadcrumbs from unbound background work can leak in. A closure provider returning a hub with an emptyScope::default()avoids that.PII: let's scrub emails/IPs and keep only UUIDs.
onboarding.rs:305,rate_limit.rs:115), so it needs a regex over the message and field values, replacing them with[email]/[ip].before_breadcrumbininit_from_envis enough.Hub::add_breadcrumbruns it (sentry-corehub.rs:255), so it only costs anything when an error is reported, andregexis already a workspace dep.before_sendcovers exception messages too.Deploy failures: the
Errbranch (api/src/main.rs:3131) reports to Sentry but doesn't log anything. With noSENTRY_DSN, which is the default everywhere, a failed deploy still leaves no trace. Addtracing::error!(error = ?error, "deploy failed").DSN: failing fast on an invalid DSN is fine. Two small fixes:
sentry-middleware/src/lib.rs:243) still says it returnsNonewhen the DSN is invalid.init_from_envthan to panic inside sentry with "invalid value for DSN".d17307e281to391ba5502a391ba5502ato84d75c7c77