Add environment option to Sentry monitoring hook (#1172).

Reviewed-on: https://projects.torsion.org/borgmatic-collective/borgmatic/pulls/1172
Reviewed-by: Dan Helfman <witten@torsion.org>
This commit is contained in:
Dan Helfman
2025-10-30 22:37:53 +00:00
4 changed files with 30 additions and 8 deletions
+6
View File
@@ -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:
+5 -1
View File
@@ -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'},
)
@@ -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
```
+15 -7
View File
@@ -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()