From b7d25522f11a20d31eaf4d11d9d18fa625f383f7 Mon Sep 17 00:00:00 2001 From: aradhyacp Date: Tue, 30 Dec 2025 17:35:32 +0530 Subject: [PATCH] Integrate Sentry for error tracking and performance monitoring --- aperisolve/app.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/aperisolve/app.py b/aperisolve/app.py index 75359d2..5b0ad4d 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -8,6 +8,11 @@ from datetime import datetime, timezone from pathlib import Path from typing import Any, Optional +import sentry_sdk +from sentry_sdk.integrations.flask import FlaskIntegration +from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration +from sentry_sdk.integrations.rq import RqIntegration + from flask import Flask, Response, abort, jsonify, render_template, request, send_file from redis import Redis from rq import Queue @@ -16,6 +21,32 @@ from .cleanup import cleanup_old_entries from .config import IMAGE_EXTENSIONS, RESULT_FOLDER, WORKER_FILES from .models import Image, Submission, db, init_db +SENTRY_DSN = os.environ.get("SENTRY_DSN") +ENVIRONMENT = os.environ.get("ENVIRONMENT", "development") + +if SENTRY_DSN: + sentry_sdk.init( + dsn=SENTRY_DSN, + integrations=[ + FlaskIntegration(), + SqlalchemyIntegration(), + RqIntegration(), + ], + # Set traces_sample_rate to 1.0 to capture 100% of transactions for performance monitoring. + # Adjust this value in production (e.g., 0.1 for 10%) + traces_sample_rate=float(os.environ.get("SENTRY_TRACES_SAMPLE_RATE", "0.1")), + # Set profiles_sample_rate to 1.0 to profile 100% of sampled transactions. + profiles_sample_rate=float(os.environ.get("SENTRY_PROFILES_SAMPLE_RATE", "0.1")), + # Environment tag (production, staging, development) + environment=ENVIRONMENT, + # Release version (use git commit hash or version number) + release=os.environ.get("SENTRY_RELEASE", "1.0.0"), + # Send default PII (user IPs, etc.) - set to False for privacy + send_default_pii=False, + # Enable automatic breadcrumb tracking + enable_tracing=True, + ) + app: Flask = Flask(__name__) app.json.sort_keys = False # type: ignore app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("DB_URI") @@ -35,6 +66,11 @@ queue = Queue(connection=redis_conn) @app.errorhandler(413) def too_large(_: Any) -> tuple[Response, int]: """Error Handler for Max File Size.""" + sentry_sdk.set_context("upload", { + "content_length": request.content_length, + "max_allowed": app.config["MAX_CONTENT_LENGTH"], + }) + sentry_sdk.capture_message("Upload failed: 413 Payload Too Large", level="warning") return jsonify({"error": "Image size exceeded"}), 413 @@ -43,6 +79,7 @@ def not_found(_: Any) -> str: """Error Handler for 404 not found.""" return render_template("error.html", message="Resource not found", statuscode=404) +# Sentry automatically captures 500 errors @app.route("/") def index() -> str: