From c3d49956c7c7ba39f2b256326960697bc89d8304 Mon Sep 17 00:00:00 2001 From: Loan Robert Date: Tue, 28 May 2024 18:31:53 +0200 Subject: [PATCH] Intercept exceptions with sentry --- poetry.lock | 56 +++++++++++++++++++++++++++++++++++++--- pyproject.toml | 1 + web/b3desk/__init__.py | 45 +++++++++++++++++++++++--------- web/requirements.app.txt | 1 + 4 files changed, 87 insertions(+), 16 deletions(-) diff --git a/poetry.lock b/poetry.lock index 3cf5801..b9be4f0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiosmtpd" @@ -1303,7 +1303,6 @@ files = [ {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:9e2addd2d1866fe112bc6f80117bcc6bc25191c5ed1bfbcf9f1386a884252ae8"}, {file = "lxml-5.2.1-cp37-cp37m-win32.whl", hash = "sha256:f51969bac61441fd31f028d7b3b45962f3ecebf691a510495e5d2cd8c8092dbd"}, {file = "lxml-5.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b0b58fbfa1bf7367dde8a557994e3b1637294be6cf2169810375caf8571a085c"}, - {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3e183c6e3298a2ed5af9d7a356ea823bccaab4ec2349dc9ed83999fd289d14d5"}, {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:804f74efe22b6a227306dd890eecc4f8c59ff25ca35f1f14e7482bbce96ef10b"}, {file = "lxml-5.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:08802f0c56ed150cc6885ae0788a321b73505d2263ee56dad84d200cab11c07a"}, {file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f8c09ed18ecb4ebf23e02b8e7a22a05d6411911e6fabef3a36e4f371f4f2585"}, @@ -2189,7 +2188,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -2263,6 +2261,56 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "sentry-sdk" +version = "2.3.1" +description = "Python client for Sentry (https://sentry.io)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sentry_sdk-2.3.1-py2.py3-none-any.whl", hash = "sha256:c5aeb095ba226391d337dd42a6f9470d86c9fc236ecc71cfc7cd1942b45010c6"}, + {file = "sentry_sdk-2.3.1.tar.gz", hash = "sha256:139a71a19f5e9eb5d3623942491ce03cf8ebc14ea2e39ba3e6fe79560d8a5b1f"}, +] + +[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)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +huggingface-hub = ["huggingface-hub (>=0.22)"] +langchain = ["langchain (>=0.0.210)"] +loguru = ["loguru (>=0.5)"] +openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] +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 (>=5)"] + [[package]] name = "setuptools" version = "69.5.1" @@ -2946,4 +2994,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0" -content-hash = "36f1c135521baed6284b58f1fd8cfb478eca01c26834f36ff6f47ff042f83b16" +content-hash = "a09c3ed719cf14bc6f49546fdb07e26b4ebe58dfe889d8f2d9c542654f4c5d0c" diff --git a/pyproject.toml b/pyproject.toml index 657051a..f700b5e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ sqlalchemy = "^1.4.31" sqlalchemy-json = "^0.7.0" sqlalchemy-utils = "^0.41.1" webdavclient3 = "3.14.6" +sentry-sdk = "^2.3.1" [tool.poetry.group.dev] optional = true diff --git a/web/b3desk/__init__.py b/web/b3desk/__init__.py index 8487f93..c497b48 100644 --- a/web/b3desk/__init__.py +++ b/web/b3desk/__init__.py @@ -75,6 +75,21 @@ def setup_cache(app): cache.init_app(app, config=config) +def setup_sentry(app): # pragma: no cover + if not app.config.get("SENTRY_DSN"): + return None + + try: + import sentry_sdk + from sentry_sdk.integrations.flask import FlaskIntegration + + except Exception: + return None + + sentry_sdk.init(dsn=app.config["SENTRY_DSN"], integrations=[FlaskIntegration()]) + return sentry_sdk + + def setup_logging(app): if not app.debug and not app.testing: dictConfig( @@ -257,18 +272,24 @@ def setup_oidc(app): def create_app(test_config=None): app = Flask(__name__) - setup_configuration(app, test_config) - setup_celery(app) - setup_cache(app) - setup_logging(app) - setup_i18n(app) - setup_csrf(app) - setup_database(app) - setup_jinja(app) - setup_flask(app) - setup_error_pages(app) - setup_endpoints(app) - setup_oidc(app) + sentry_sdk = setup_sentry(app) + try: + setup_configuration(app, test_config) + setup_celery(app) + setup_cache(app) + setup_logging(app) + setup_i18n(app) + setup_csrf(app) + setup_database(app) + setup_jinja(app) + setup_flask(app) + setup_error_pages(app) + setup_endpoints(app) + setup_oidc(app) + except Exception as exc: # pragma: no cover + if sentry_sdk: + sentry_sdk.capture_exception(exc) + raise # ensure the instance folder exists os.makedirs(app.instance_path, exist_ok=True) diff --git a/web/requirements.app.txt b/web/requirements.app.txt index 220d496..3b0f712 100644 --- a/web/requirements.app.txt +++ b/web/requirements.app.txt @@ -55,6 +55,7 @@ python-slugify==8.0.4 ; python_version >= "3.9" and python_version < "4.0" pytz==2024.1 ; python_version >= "3.9" and python_version < "4.0" redis==5.0.4 ; python_version >= "3.9" and python_version < "4.0" requests==2.31.0 ; python_version >= "3.9" and python_version < "4.0" +sentry-sdk==2.3.1 ; python_version >= "3.9" and python_version < "4.0" six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" sqlalchemy-json==0.7.0 ; python_version >= "3.9" and python_version < "4.0" sqlalchemy-utils==0.41.2 ; python_version >= "3.9" and python_version < "4.0"