Skip to content

feat: GlitchTip error tracking (sentry, rustls, credential-scrubbing)#12

Merged
ivndev001 merged 7 commits into
mainfrom
feat/glitchtip-sentry
Jul 1, 2026
Merged

feat: GlitchTip error tracking (sentry, rustls, credential-scrubbing)#12
ivndev001 merged 7 commits into
mainfrom
feat/glitchtip-sentry

Conversation

@ivndev001

@ivndev001 ivndev001 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds GlitchTip (Sentry-protocol) error tracking via the sentry crate, error-tracking only (no traces/profiling/spans, send_default_pii=false). Transport is reqwest+rustls — repo stays openssl-free (cargo tree -i openssl-sys / native-tls both empty).
  • src/sentry.rs: runtime init() reading SENTRY_DSN/SENTRY_ENVIRONMENT from env (never hardcoded); unset/malformed DSN → disabled no-op client, app still runs. Mandatory fail-closed before_send scrubber redacts from every event (message, exception, breadcrumbs, extra JSON): URL user:pass@host creds, key=value/key: value secret pairs, and PEM private-key blocks. No unwrap/expect, regex-compile failure → redact whole string.
  • src/main.rs: refactored to sync fn main() binding let _sentry_guard before the tokio runtime, then block_on(run()) — so the transport's own runtime works and the guard flushes on exit.
  • .mcp.json (GlitchTip MCP), .env.example + deploy/mcp-ssh.service + docs/deploy.md document the SENTRY_DSN/SENTRY_ENVIRONMENT runtime injection point.

Tests

  • cargo fmt --check ✓ · cargo clippy --all-targets -D warnings ✓ · cargo test122 passed, 0 failed (incl. 12 scrubber/no-op unit tests).
  • Manual e2e (local relay → real GlitchTip ingest): upstream_status=200 with an accepted event id, and the captured envelope showed MCP_SSH_PASS=***REDACTED*** + token=***REDACTED*** — delivery, flush, guard-before-runtime ordering, and in-flight scrubbing all confirmed. No event lands without the guard held.

Ref: developerz-ai/infrastructure#499 (GlitchTip project id 10).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added optional error tracking support for the app, with safer handling of sensitive information before reports are sent.
    • Added configuration support for environment-specific error reporting settings.
  • Bug Fixes

    • Improved startup behavior so error reporting is initialized more explicitly and can be disabled when no reporting endpoint is configured.
  • Documentation

    • Updated deployment docs with the new environment variables and how they are provided.

ivndev001 and others added 6 commits July 1, 2026 14:19
- default-features=false drops native-tls + debug-images (both default)
- features: reqwest + rustls transport, backtrace/contexts/panic
- verified openssl-free: cargo tree -i openssl-sys / native-tls empty

Co-Authored-By: Claude <noreply@anthropic.com>
…bber

- GlitchTip error tracking: ClientOptions (dsn from SENTRY_DSN env, env from
  SENTRY_ENVIRONMENT, release=CARGO_PKG_VERSION, send_default_pii=false,
  traces_sample_rate=0.0) with a before_send that scrubs every event.
- Fail-closed scrubber: URL user:pass@host creds, secret key=value/key: value
  (password|passwd|pwd|secret|token|dsn|pass), and PEM private-key blocks →
  ***REDACTED***. If any regex fails to compile, paranoid mode redacts whole
  strings. No unwrap/expect outside tests; init never panics (DSN parsed first,
  malformed → disabled no-op client, app still runs).
- scrub_str (pure, testable), scrub_value (recursive JSON), scrub_event
  (message/exception/breadcrumb/extra). 10 unit tests cover all three patterns,
  paranoid mode, DSN parse, JSON recursion, and the no-op path.
- Module wired via `mod sentry;`; init() call lands with the main.rs init-first
  refactor (next task) — guarded with #![allow(dead_code)] until then.

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace `#[tokio::main] async fn main` with a sync `fn main`:
  bind `let _sentry_guard = sentry::init()` FIRST (named binding so it
  outlives block_on, not a bare `let _ =`), then tracing init, then build
  a multi-thread runtime and block_on(run()).
- Move the CLI dispatch body verbatim into `async fn run()`.
- Gate the test-only `scrub_str` helper with `#[cfg(test)]` and drop the
  module-level `#![allow(dead_code)]` now that `init` is wired in.

Sentry now captures for the whole process lifetime; unset/malformed DSN
still yields a disabled no-op client. serve/set_auth/shutdown_signal and
the unix test module are unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace placeholder tests with spec-named cases: password
  assignment, user:pass URL, PEM private-key block, nested JSON
  secret, MCP_SSH_PASS env value, parse_dsn, no-op init.
- Add real no-op test via init()+is_enabled() (disabled client
  when SENTRY_DSN unset), plus array-descent coverage.
- Remove the real ingest key (16a3...) from the parse_dsn test;
  use a throwaway DSN shape so the secret never lands in source.

Co-Authored-By: Claude <noreply@anthropic.com>
- Point MCP clients at the GlitchTip HTTP MCP endpoint
- infra#499

Co-Authored-By: Claude <noreply@anthropic.com>
- .env.example: SENTRY_DSN/SENTRY_ENVIRONMENT after RUST_LOG
- systemd unit: comment at EnvironmentFile noting env-file injection
- docs/deploy.md: config table rows pointing to the env file

Co-Authored-By: Claude <noreply@anthropic.com>
@ivndev001 ivndev001 added the claudetm Created by Claude Task Master label Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 32 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9c2dcd85-0838-4dc5-ae09-b6156f6101e4

📥 Commits

Reviewing files that changed from the base of the PR and between 6dc89cc and c979046.

📒 Files selected for processing (3)
  • docs/deploy.md
  • src/main.rs
  • src/sentry.rs

Walkthrough

Adds Sentry/GlitchTip error tracking to the Rust binary: new sentry/regex dependencies, a src/sentry.rs module performing credential redaction before sending events, restructured main() to initialize Sentry before the Tokio runtime, plus deployment, docs, MCP config, and gitignore updates.

Changes

Sentry error tracking with redaction

Layer / File(s) Summary
Dependency additions
Cargo.toml
Adds regex and sentry (with reqwest+rustls, backtrace, contexts, panic features) dependencies.
Redaction engine and init
src/sentry.rs
Defines Scrubbers regex patterns for credentials/secrets/PEM blocks, recursive JSON redaction, before_send callback, init() reading SENTRY_DSN/SENTRY_ENVIRONMENT with paranoid fail-closed mode, and comprehensive unit tests.
Entrypoint restructuring
src/main.rs
Adds mod sentry; and replaces #[tokio::main] async fn main() with a synchronous main() calling sentry::init(), building the runtime explicitly, and running an extracted async fn run().
Deployment, docs, config
.mcp.json, deploy/mcp-ssh.service, docs/deploy.md, .gitignore
Adds GlitchTip MCP endpoint config, service comments on SENTRY_DSN behavior, documented env vars, and ignores for local task-master artifacts.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant SentryClient
  participant Scrubbers
  participant GlitchTip

  App->>SentryClient: emit Event (message, exception, breadcrumbs, extra)
  SentryClient->>Scrubbers: before_send(event)
  Scrubbers->>Scrubbers: scrub_event (regex + key-match redaction)
  Scrubbers-->>SentryClient: redacted Event
  SentryClient->>GlitchTip: send redacted Event
Loading

Related issues: None referenced in the provided diff.

Related PRs: None referenced in the provided diff.

Suggested labels: enhancement, observability, rust

Suggested reviewers: No reviewer information available from provided context.

Poem:
A rabbit hopped to fetch each crash,
scrubbed the secrets, dodged the stash,
key=value? Gone in a blink,
PEM blocks vanish, no leak, noink,
now errors hop to GlitchTip's den —
redacted clean, again and again. 🐇🔒

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding GlitchTip/Sentry error tracking with rustls transport and credential scrubbing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/glitchtip-sentry

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/deploy.md`:
- Around line 214-215: The documented default for SENTRY_ENVIRONMENT is out of
sync with the actual fallback used in src/sentry.rs. Update the deploy docs
table entry for SENTRY_ENVIRONMENT to match the code’s default behavior, and
verify the wording stays consistent with the environment handling in the sentry
initialization logic.

In `@src/main.rs`:
- Around line 34-37: The `main` function currently returns
`runtime.block_on(run())` directly, so `run()` failures bypass Sentry. Update
`main` to call `run()` through `runtime.block_on`, inspect the returned result,
and when it is an `Err`, capture that error with Sentry before returning it
unchanged. Use the `main` and `run` flow to place the capture logic without
altering the successful path.

In `@src/sentry.rs`:
- Around line 24-28: The scrubber in sentry.rs still misses Authorization and
cookie secrets, so extend both SECRET_KEYS and the free-text secret matcher used
by the sanitization logic to catch structured fields like authorization/cookie
and text forms like Authorization: Bearer ... . Update the relevant masking path
that uses SECRET_KEYS/SECRET_KV so these values are redacted before sending
events or crumbs, and add a regression test covering
event.extra["authorization"], crumb.data["cookie"], and free-text Authorization
headers.
- Around line 252-257: Replace the literal PEM-looking fixture in
scrubs_pem_private_key_block with a value assembled from split string fragments
so the runtime string still matches PEM_BLOCK but the source no longer contains
a scanner-detectable private key block. Keep the test logic unchanged and use
the existing scrubbing test name as the anchor for the fixture update.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 89083cb0-6d1b-4b19-b457-c9c1693b57f4

📥 Commits

Reviewing files that changed from the base of the PR and between 62afbed and 6dc89cc.

⛔ Files ignored due to path filters (2)
  • .env.example is excluded by !.env*
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • .gitignore
  • .mcp.json
  • Cargo.toml
  • deploy/mcp-ssh.service
  • docs/deploy.md
  • src/main.rs
  • src/sentry.rs

Comment thread docs/deploy.md Outdated
Comment thread src/main.rs Outdated
Comment thread src/sentry.rs
Comment thread src/sentry.rs Outdated
- Scrubber now redacts `authorization`/`cookie` keys (structured + free-text,
  incl. full `Authorization: Bearer <tok>`); value capture spans to EOL to avoid
  leaking trailing tokens. Added regression test.
- main captures run() errors to Sentry before propagating (capture_error wrapper
  in the local sentry module — it shadows the SDK crate from main).
- PEM fixture built from split fragments so the source no longer trips secret
  scanners; runtime value unchanged.
- docs: SENTRY_ENVIRONMENT default aligned to code (`development`).

Co-Authored-By: Claude <noreply@anthropic.com>
@ivndev001 ivndev001 merged commit d8b41a0 into main Jul 1, 2026
5 checks passed
@ivndev001 ivndev001 deleted the feat/glitchtip-sentry branch July 1, 2026 15:30
@sebyx07 sebyx07 mentioned this pull request Jul 2, 2026
sebyx07 added a commit that referenced this pull request Jul 2, 2026
Version bump for the v1.3.0 release: GlitchTip error tracking (#12) +
bug-fix PRs #13#16.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claudetm Created by Claude Task Master

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant