feat: Add Sentry error tracking integration (Issue #698)#735
Conversation
Implements GitHub Issue #700 This CODEOWNERS file defines code ownership and review requirements for the ModPorter-AI project: - Frontend: /frontend/ directory ownership - Backend: /backend/ directory ownership - AI-Engine: /ai-engine/ directory ownership - Infrastructure: Docker and docker-compose files - Security: Security-related scripts and configs - Documentation: docs/ and markdown files - Configuration: Project-wide configs and CI/CD workflows Readiness Pillar: Security Co-authored-by: openhands <openhands@all-hands.dev>
- Add sentry-sdk to backend with FastAPI and SQLAlchemy integrations - Add @sentry/react to frontend with browser tracing and replay - Integrate Sentry with existing ErrorBoundary component - Add Sentry configuration to .env.example files - Configure environment variables for DSN and sampling rates - Add performance monitoring and error capturing This implements the Readiness Pillar for Debugging & Observability by providing comprehensive error tracking for production issue detection. Co-authored-by: openhands <openhands@all-hands.dev>
There was a problem hiding this comment.
Pull request overview
Adds Sentry-based error tracking/observability across the FastAPI backend and React frontend to address Issue #698, including environment configuration examples and ownership rules.
Changes:
- Initialize Sentry in the frontend entrypoint and report React errors via the existing ErrorBoundary.
- Initialize Sentry in the backend app startup with FastAPI + SQLAlchemy integrations and configurable trace sampling.
- Add example environment variables and introduce a CODEOWNERS file.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
frontend/src/main.tsx |
Adds Sentry initialization (dsn/env/release, tracing, replay, filtering). |
frontend/src/components/ErrorBoundary/ErrorBoundary.tsx |
Reports caught React errors to Sentry. |
frontend/package.json |
Adds @sentry/react dependency. |
frontend/.env.example |
Documents frontend Sentry env vars. |
backend/requirements.txt |
Adds sentry-sdk[fastapi] (and structlog). |
backend/main.py |
Adds Sentry SDK initialization for backend error/perf capture. |
.env.example |
Documents backend Sentry env vars. |
.github/CODEOWNERS |
Introduces code ownership rules for review requirements. |
Comments suppressed due to low confidence (1)
backend/main.py:52
- Sentry is initialized before
load_dotenv()is called. IfSENTRY_DSN/SENTRY_TRACES_SAMPLE_RATE/ENVIRONMENT/VERSIONare provided via a local.env, they won’t be loaded yet and Sentry won’t initialize as expected. Moveload_dotenv()above the Sentryos.getenv(...)reads (or rely solely on process env and removeload_dotenv()usage here).
# Sentry error tracking initialization
import sentry_sdk
from sentry_sdk.integrations.fastapi import FastApiIntegration
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
SENTRY_DSN = os.getenv("SENTRY_DSN")
if SENTRY_DSN:
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[
FastApiIntegration(),
SqlalchemyIntegration(),
],
# Set traces_sample_rate to 1.0 to capture 100% of transactions for tracing
traces_sample_rate=float(os.getenv("SENTRY_TRACES_SAMPLE_RATE", "0.1")),
# Include environment and release info
environment=os.getenv("ENVIRONMENT", "development"),
release=os.getenv("VERSION", "1.0.0"),
# Attach serverless context
send_default_pii=False,
# Filter out common non-critical events
before_send=lambda event, hint: None if 'ignore' in hint else event,
)
print(f"Sentry error tracking initialized for environment: {os.getenv('ENVIRONMENT', 'development')}")
# AI Engine settings
load_dotenv()
| Sentry.browserTracingIntegration(), | ||
| Sentry.replayIntegration({ | ||
| maskAllText: false, | ||
| blockAllMedia: false, | ||
| }), |
There was a problem hiding this comment.
Session replay is configured with maskAllText: false and blockAllMedia: false, which risks capturing sensitive user content (PII) in replays by default. Consider enabling masking/blocking by default (or gating replay behind an explicit env var) and only relaxing these settings for vetted, non-sensitive views.
| # Set traces_sample_rate to 1.0 to capture 100% of transactions for tracing | ||
| traces_sample_rate=float(os.getenv("SENTRY_TRACES_SAMPLE_RATE", "0.1")), | ||
| # Include environment and release info | ||
| environment=os.getenv("ENVIRONMENT", "development"), | ||
| release=os.getenv("VERSION", "1.0.0"), |
There was a problem hiding this comment.
float(os.getenv("SENTRY_TRACES_SAMPLE_RATE", "0.1")) will raise a ValueError if the env var is set but not a valid float, preventing the app from starting. Consider parsing defensively (try/except) and clamping to [0.0, 1.0] with a fallback default.
| } | ||
|
|
||
| Sentry.addCaptureConsoleIntegration(); |
There was a problem hiding this comment.
Sentry.addCaptureConsoleIntegration() is called unconditionally and appears to be a non-existent/incorrect Sentry v8 API for adding the console-capture integration. This will likely fail at runtime/compile time, and it also runs even when VITE_SENTRY_DSN is unset. Use the supported integration (e.g., the capture-console integration factory) and add it via the integrations array inside Sentry.init, gated behind the DSN/config flag.
| beforeSend(event) { | ||
| // Don't send events in development unless explicitly enabled | ||
| if (import.meta.env.MODE === 'development' && !import.meta.env.VITE_SENTRY_ENABLE_DEV) { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
VITE_SENTRY_ENABLE_DEV is treated as a boolean, but Vite env vars are strings. If it’s set to "false", it’s still truthy and will unintentionally enable event sending in development. Compare explicitly to "true" (or parse the value) before deciding whether to drop events.
| // Performance monitoring | ||
| tracesSampleRate: parseFloat(import.meta.env.VITE_SENTRY_TRACES_SAMPLE_RATE || '0.1'), | ||
| // Session replay |
There was a problem hiding this comment.
tracesSampleRate is derived via parseFloat(...) without validation/clamping. If the env var is missing/invalid (e.g., "" or "abc"), this becomes NaN and may break Sentry init. Validate the parsed value (0.0–1.0) and fall back to a safe default when invalid.
| # Attach serverless context | ||
| send_default_pii=False, | ||
| # Filter out common non-critical events | ||
| before_send=lambda event, hint: None if 'ignore' in hint else event, | ||
| ) |
There was a problem hiding this comment.
before_send=lambda event, hint: None if 'ignore' in hint else event can raise at runtime if hint is None (it’s typed as optional in the Sentry SDK), and the current predicate doesn’t correspond to a meaningful filter (nothing sets an ignore key by default). Replace this with a named before_send(event, hint) that handles hint is None safely and filters based on explicit conditions (exception types/messages, endpoint paths, etc.).
| # Monitoring | ||
| prometheus_client>=0.17.0 | ||
| sentry-sdk[fastapi]>=2.0.0 | ||
| structlog>=24.0.0 |
There was a problem hiding this comment.
structlog is added to requirements but doesn’t appear to be used anywhere in the backend codebase. Unused dependencies increase image size and supply-chain surface area; either remove it or add the intended structured-logging initialization in this PR.
| structlog>=24.0.0 |
| # Documentation changes can be reviewed by any maintainer | ||
| /docs/ @alex | ||
| *.md @alex | ||
| !/.github/*.md |
There was a problem hiding this comment.
!/.github/*.md looks like an attempt to use .gitignore-style negation, but CODEOWNERS patterns don’t support ! negation. As written, .github/*.md will still be matched by the preceding *.md rule. Use an explicit positive pattern for .github/*.md (placed after *.md) with the desired owners, or restructure the rules to avoid needing negation.
| !/.github/*.md | |
| /.github/*.md @alex |
Summary
This PR implements GitHub Issue #698 by adding comprehensive error tracking integration using Sentry.
Changes Made:
Backend (Python/FastAPI):
Frontend (React/TypeScript):
Environment Configuration:
Features:
Readiness Pillar: Debugging & Observability
This implementation supports the Debugging & Observability pillar by providing:
How to Use:
Co-authored-by: openhands openhands@all-hands.dev