From 7dc7eea34d0adfc53239a78634a114334a101b9e Mon Sep 17 00:00:00 2001 From: Michael Manganiello Date: Fri, 27 Dec 2024 10:48:43 -0300 Subject: [PATCH] feat: Initial Sentry support This change initializes the Sentry SDK, which enables error tracking when the `SENTRY_DSN` environment variable is set. Drop-in alternatives to Sentry are also supported, like GlitchTip. --- backend/config/__init__.py | 3 ++ backend/main.py | 7 +++++ backend/scheduler.py | 8 ++++++ backend/utils/__init__.py | 2 +- backend/watcher.py | 8 ++++++ backend/worker.py | 9 ++++++ poetry.lock | 56 +++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 8 files changed, 92 insertions(+), 2 deletions(-) diff --git a/backend/config/__init__.py b/backend/config/__init__.py index 0ef19fab8..7a5860b2d 100644 --- a/backend/config/__init__.py +++ b/backend/config/__init__.py @@ -119,5 +119,8 @@ LOGLEVEL: Final = os.environ.get("LOGLEVEL", "INFO") FORCE_COLOR: Final = str_to_bool(os.environ.get("FORCE_COLOR", "false")) NO_COLOR: Final = str_to_bool(os.environ.get("NO_COLOR", "false")) +# SENTRY +SENTRY_DSN: Final = os.environ.get("SENTRY_DSN", None) + # TESTING IS_PYTEST_RUN: Final = bool(os.environ.get("PYTEST_VERSION", False)) diff --git a/backend/main.py b/backend/main.py index ffc3c6407..06cf9f19a 100644 --- a/backend/main.py +++ b/backend/main.py @@ -4,6 +4,7 @@ from contextlib import asynccontextmanager import alembic.config import endpoints.sockets.scan # noqa +import sentry_sdk import uvicorn from config import ( DEV_HOST, @@ -11,6 +12,7 @@ from config import ( DISABLE_CSRF_PROTECTION, IS_PYTEST_RUN, ROMM_AUTH_SECRET_KEY, + SENTRY_DSN, ) from endpoints import ( auth, @@ -48,6 +50,11 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: yield +sentry_sdk.init( + dsn=SENTRY_DSN, + release="romm@" + get_version(), +) + app = FastAPI( title="RomM API", version=get_version(), diff --git a/backend/scheduler.py b/backend/scheduler.py index 485cc822c..2105c65ac 100644 --- a/backend/scheduler.py +++ b/backend/scheduler.py @@ -1,7 +1,15 @@ +import sentry_sdk +from config import SENTRY_DSN from logger.logger import log from tasks.scan_library import scan_library_task from tasks.tasks import tasks_scheduler from tasks.update_switch_titledb import update_switch_titledb_task +from utils import get_version + +sentry_sdk.init( + dsn=SENTRY_DSN, + release="romm@" + get_version(), +) if __name__ == "__main__": # Initialize the tasks diff --git a/backend/utils/__init__.py b/backend/utils/__init__.py index 4d3c83144..a0861fc26 100644 --- a/backend/utils/__init__.py +++ b/backend/utils/__init__.py @@ -3,7 +3,7 @@ from __version__ import __version__ def get_version() -> str: """Returns current version tag""" - if not __version__ == "": + if __version__ != "": return __version__ return "development" diff --git a/backend/watcher.py b/backend/watcher.py index 37a3ca448..3e3cb15db 100644 --- a/backend/watcher.py +++ b/backend/watcher.py @@ -1,10 +1,12 @@ import os from datetime import timedelta +import sentry_sdk from config import ( ENABLE_RESCAN_ON_FILESYSTEM_CHANGE, LIBRARY_BASE_PATH, RESCAN_ON_FILESYSTEM_CHANGE_DELAY, + SENTRY_DSN, ) from config.config_manager import config_manager as cm from endpoints.sockets.scan import scan_platforms @@ -12,9 +14,15 @@ from handler.database import db_platform_handler from handler.scan_handler import ScanType from logger.logger import log from tasks.tasks import tasks_scheduler +from utils import get_version from watchdog.events import FileSystemEventHandler from watchdog.observers import Observer +sentry_sdk.init( + dsn=SENTRY_DSN, + release="romm@" + get_version(), +) + path = ( cm.get_config().HIGH_PRIO_STRUCTURE_PATH if os.path.exists(cm.get_config().HIGH_PRIO_STRUCTURE_PATH) diff --git a/backend/worker.py b/backend/worker.py index a67e2cb68..cda32afd2 100644 --- a/backend/worker.py +++ b/backend/worker.py @@ -1,8 +1,17 @@ +import sentry_sdk +from config import SENTRY_DSN from handler.redis_handler import redis_client from rq import Connection, Queue, Worker +from utils import get_version listen = ["high", "default", "low"] +sentry_sdk.init( + dsn=SENTRY_DSN, + release="romm@" + get_version(), +) + + if __name__ == "__main__": # Start the worker with Connection(redis_client): diff --git a/poetry.lock b/poetry.lock index ff22dadf9..d4e7d2dbf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2646,6 +2646,60 @@ freezegun = "*" python-dateutil = "*" rq = ">=0.13" +[[package]] +name = "sentry-sdk" +version = "2.19.2" +description = "Python client for Sentry (https://sentry.io)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sentry_sdk-2.19.2-py2.py3-none-any.whl", hash = "sha256:ebdc08228b4d131128e568d696c210d846e5b9d70aa0327dec6b1272d9d40b84"}, + {file = "sentry_sdk-2.19.2.tar.gz", hash = "sha256:467df6e126ba242d39952375dd816fbee0f217d119bf454a8ce74cf1e7909e8d"}, +] + +[package.dependencies] +certifi = "*" +urllib3 = ">=1.26.11" + +[package.extras] +aiohttp = ["aiohttp (>=3.5)"] +anthropic = ["anthropic (>=0.16)"] +arq = ["arq (>=0.23)"] +asyncpg = ["asyncpg (>=0.23)"] +beam = ["apache-beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +celery-redbeat = ["celery-redbeat (>=2)"] +chalice = ["chalice (>=1.16.0)"] +clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] +django = ["django (>=1.8)"] +falcon = ["falcon (>=1.4)"] +fastapi = ["fastapi (>=0.79.0)"] +flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] +grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"] +http2 = ["httpcore[http2] (==1.*)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +huggingface-hub = ["huggingface_hub (>=0.22)"] +langchain = ["langchain (>=0.0.210)"] +launchdarkly = ["launchdarkly-server-sdk (>=9.8.0)"] +litestar = ["litestar (>=2.0.0)"] +loguru = ["loguru (>=0.5)"] +openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] +openfeature = ["openfeature-sdk (>=0.7.1)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-distro"] +pure-eval = ["asttokens", "executing", "pure_eval"] +pymongo = ["pymongo (>=3.1)"] +pyspark = ["pyspark (>=2.4.4)"] +quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] +rq = ["rq (>=0.6)"] +sanic = ["sanic (>=0.8)"] +sqlalchemy = ["sqlalchemy (>=1.2)"] +starlette = ["starlette (>=0.19.1)"] +starlite = ["starlite (>=1.48)"] +tornado = ["tornado (>=6)"] + [[package]] name = "simple-websocket" version = "1.1.0" @@ -3512,4 +3566,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "0f6f275d52781259c3780482aab4270849bba5f4e09bcd1c90bea8ead769dc72" +content-hash = "e9380cae3aa9cbc412125bb79ed8c4107749117d16d219974480e70b9f34579d" diff --git a/pyproject.toml b/pyproject.toml index e94071fb0..e58cdaa9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,6 +44,7 @@ python-magic = "^0.4.27" # TODO: Move back to `py7zr` official releases, once the following PR is merged and released: # https://github.com/miurahr/py7zr/pull/620 py7zr = { git = "https://github.com/adamantike/py7zr.git", rev = "54b68426" } +sentry-sdk = "^2.19" streaming-form-data = "^1.16.0" zipfile-deflate64 = "^0.2.0" colorama = "^0.4.6"