diff --git a/swh/core/sentry.py b/swh/core/sentry.py --- a/swh/core/sentry.py +++ b/swh/core/sentry.py @@ -4,6 +4,7 @@ # See top-level LICENSE file for more information import os +from typing import Dict, List, Optional import pkg_resources @@ -17,15 +18,54 @@ return None -def init_sentry(sentry_dsn, *, debug=None, integrations=[], extra_kwargs={}): - if debug is None: - debug = bool(os.environ.get("SWH_SENTRY_DEBUG")) - sentry_dsn = sentry_dsn or os.environ.get("SWH_SENTRY_DSN") +def envvar_is_positive(envvar: str) -> bool: + """Check whether a given environment variable looks like a positive boolean value""" + return os.environ.get(envvar, "false").lower() in ("t", "true", "y", "yes", "1") + + +def init_sentry( + sentry_dsn: str, + *, + debug: Optional[bool] = None, + disable_logging_events: Optional[bool] = None, + integrations: Optional[List] = None, + extra_kwargs: Optional[Dict] = None, +): + """Configure the sentry integration + + Args: + sentry_dsn: sentry DSN; where sentry report will be sent (if empty, pulled from + :envvar:`SWH_SENTRY_DSN`) + debug: turn on sentry SDK debug mode (if ``None``, pulled from + :envvar:`SWH_SENTRY_DEBUG`) + disable_logging_events: if set, disable the automatic reporting of error/exception + log entries as sentry events (if ``None``, pulled from + :envvar:`SWH_SENTRY_DISABLE_LOGGING_EVENTS`) + integrations: list of dedicated sentry integrations objects + extra_kwargs: dict of additional parameters passed to :func:`sentry_sdk.init` + + """ + if integrations is None: + integrations = [] + if extra_kwargs is None: + extra_kwargs = {} + + sentry_dsn = sentry_dsn or os.environ.get("SWH_SENTRY_DSN", "") environment = os.environ.get("SWH_SENTRY_ENVIRONMENT") + if debug is None: + debug = envvar_is_positive("SWH_SENTRY_DEBUG") + if disable_logging_events is None: + disable_logging_events = envvar_is_positive("SWH_SENTRY_DISABLE_LOGGING_EVENTS") + if sentry_dsn: import sentry_sdk + if disable_logging_events: + from sentry_sdk.integrations.logging import LoggingIntegration + + integrations.append(LoggingIntegration(event_level=None)) + sentry_sdk.init( release=get_sentry_release(), environment=environment, diff --git a/swh/core/tests/test_sentry.py b/swh/core/tests/test_sentry.py new file mode 100644 --- /dev/null +++ b/swh/core/tests/test_sentry.py @@ -0,0 +1,68 @@ +# Copyright (C) 2022 The Software Heritage developers +# See the AUTHORS file at the top-level directory of this distribution +# License: GNU General Public License version 3, or any later version +# See top-level LICENSE file for more information + +import logging + +from sentry_sdk import capture_message + +from swh.core.sentry import init_sentry + + +def test_sentry(): + reports = [] + init_sentry("http://example.org", extra_kwargs={"transport": reports.append}) + + capture_message("Something went wrong") + logging.error("Stupid error") + + assert len(reports) == 2 + assert reports[0]["message"] == "Something went wrong" + assert reports[1]["logentry"]["message"] == "Stupid error" + + +def test_sentry_no_logging(): + reports = [] + init_sentry( + "http://example.org", + disable_logging_events=True, + extra_kwargs={"transport": reports.append}, + ) + + capture_message("Something went wrong") + logging.error("Stupid error") + + assert len(reports) == 1 + assert reports[0]["message"] == "Something went wrong" + + +def test_sentry_no_logging_from_venv(monkeypatch): + monkeypatch.setenv("SWH_SENTRY_DISABLE_LOGGING_EVENTS", "True") + + reports = [] + init_sentry( + "http://example.org", + extra_kwargs={"transport": reports.append}, + ) + + capture_message("Something went wrong") + logging.error("Stupid error") + + assert len(reports) == 1 + assert reports[0]["message"] == "Something went wrong" + + +def test_sentry_logging_from_venv(monkeypatch): + monkeypatch.setenv("SWH_SENTRY_DISABLE_LOGGING_EVENTS", "false") + + reports = [] + init_sentry( + "http://example.org", + extra_kwargs={"transport": reports.append}, + ) + + capture_message("Something went wrong") + logging.error("Stupid error") + + assert len(reports) == 2