diff --git a/borgmatic/config/schema.yaml b/borgmatic/config/schema.yaml index 0b4e2c90..8a9c7224 100644 --- a/borgmatic/config/schema.yaml +++ b/borgmatic/config/schema.yaml @@ -3022,6 +3022,12 @@ properties: project monitor. Used along with the data source name URL to construct a cron URL. example: mymonitor + environment: + type: string + description: | + Sentry monitor environment used in the call to sentry. If + not set, the Sentry default is used. + example: production states: type: array items: diff --git a/borgmatic/hooks/monitoring/sentry.py b/borgmatic/hooks/monitoring/sentry.py index e52d61b1..c6ec5856 100644 --- a/borgmatic/hooks/monitoring/sentry.py +++ b/borgmatic/hooks/monitoring/sentry.py @@ -1,5 +1,6 @@ import logging import re +import urllib import requests @@ -40,6 +41,7 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev dry_run_label = ' (dry run; not actually pinging)' if dry_run else '' data_source_name_url = hook_config.get('data_source_name_url') + environment = hook_config.get('environment') monitor_slug = hook_config.get('monitor_slug') match = DATA_SOURCE_NAME_URL_PATTERN.match(data_source_name_url) @@ -65,10 +67,12 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev if dry_run: return + environment_query = f'&environment={urllib.parse.quote(environment)}' if environment else '' + logging.getLogger('urllib3').setLevel(logging.ERROR) try: response = requests.post( - f'{cron_url}?status={status}', + f'{cron_url}?status={status}{environment_query}', timeout=TIMEOUT_SECONDS, headers={'User-Agent': 'borgmatic'}, ) diff --git a/docs/reference/configuration/monitoring/sentry.md b/docs/reference/configuration/monitoring/sentry.md index 8c59c089..09cde442 100644 --- a/docs/reference/configuration/monitoring/sentry.md +++ b/docs/reference/configuration/monitoring/sentry.md @@ -26,6 +26,9 @@ sentry: The `monitor_slug` value comes from the "Monitor Slug" under "Cron Details" on the same Sentry monitor page. +The `environment` value optionally specifies the environment that is used in +Sentry. + With this configuration, borgmatic pings Sentry whenever borgmatic starts, finishes, or fails, but only when any of the `create`, `prune`, `compact`, or `check` actions are run. You can optionally override the start/finish/fail @@ -36,6 +39,7 @@ Sentry on failure: sentry: data_source_name_url: https://5f80ec@o294220.ingest.us.sentry.io/203069 monitor_slug: mymonitor + environment: myenvironment states: - fail ``` diff --git a/tests/unit/hooks/monitoring/test_sentry.py b/tests/unit/hooks/monitoring/test_sentry.py index 87f62a1a..f85f8f85 100644 --- a/tests/unit/hooks/monitoring/test_sentry.py +++ b/tests/unit/hooks/monitoring/test_sentry.py @@ -6,20 +6,23 @@ from borgmatic.hooks.monitoring import sentry as module @pytest.mark.parametrize( - 'state,configured_states,expected_status', + 'state,configured_states,configured_environment,expected_status', ( - (borgmatic.hooks.monitoring.monitor.State.START, ['start'], 'in_progress'), + (borgmatic.hooks.monitoring.monitor.State.START, ['start'], None, 'in_progress'), ( borgmatic.hooks.monitoring.monitor.State.START, ['start', 'finish', 'fail'], + None, 'in_progress', ), - (borgmatic.hooks.monitoring.monitor.State.START, None, 'in_progress'), - (borgmatic.hooks.monitoring.monitor.State.FINISH, ['finish'], 'ok'), - (borgmatic.hooks.monitoring.monitor.State.FAIL, ['fail'], 'error'), + (borgmatic.hooks.monitoring.monitor.State.START, None, 'production', 'in_progress'), + (borgmatic.hooks.monitoring.monitor.State.FINISH, ['finish'], 'development', 'ok'), + (borgmatic.hooks.monitoring.monitor.State.FAIL, ['fail'], 'another-environment', 'error'), ), ) -def test_ping_monitor_constructs_cron_url_and_pings_it(state, configured_states, expected_status): +def test_ping_monitor_constructs_cron_url_and_pings_it( + state, configured_states, configured_environment, expected_status +): hook_config = { 'data_source_name_url': 'https://5f80ec@o294220.ingest.us.sentry.io/203069', 'monitor_slug': 'test', @@ -28,8 +31,13 @@ def test_ping_monitor_constructs_cron_url_and_pings_it(state, configured_states, if configured_states: hook_config['states'] = configured_states + environment_query = '' + if configured_environment: + hook_config['environment'] = configured_environment + environment_query = f'&environment={configured_environment}' + flexmock(module.requests).should_receive('post').with_args( - f'https://o294220.ingest.us.sentry.io/api/203069/cron/test/5f80ec/?status={expected_status}', + f'https://o294220.ingest.us.sentry.io/api/203069/cron/test/5f80ec/?status={expected_status}{environment_query}', timeout=int, headers={'User-Agent': 'borgmatic'}, ).and_return(flexmock(ok=True)).once()