Bladeren bron

Add a Sentry monitoring hook (#855).

Dan Helfman 4 maanden geleden
bovenliggende
commit
914c2b17e9
6 gewijzigde bestanden met toevoegingen van 160 en 3 verwijderingen
  1. 2 0
      NEWS
  2. 1 0
      README.md
  3. 39 1
      borgmatic/config/schema.yaml
  4. 0 1
      borgmatic/hooks/monitoring/ntfy.py
  5. 79 0
      borgmatic/hooks/monitoring/sentry.py
  6. 39 1
      docs/how-to/monitor-your-backups.md

+ 2 - 0
NEWS

@@ -1,4 +1,6 @@
 1.9.7.dev0
+ * #855: Add a Sentry monitoring hook. See the documentation for more information:
+   https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#sentry-hook
  * #968: Fix for a "spot" check error when a filename in the most recent archive contains a newline.
  * #970: Fix for an error when there's a blank line in the configured patterns or excludes.
  * #971: Fix for "exclude_from" files being completely ignored.

+ 1 - 0
README.md

@@ -75,6 +75,7 @@ borgmatic is powered by [Borg Backup](https://www.borgbackup.org/).
 <a href="https://grafana.com/oss/loki/"><img src="docs/static/loki.png" alt="Loki" height="60px" style="margin-bottom:20px; margin-right:20px;"></a>
 <a href="https://github.com/caronc/apprise/wiki"><img src="docs/static/apprise.png" alt="Apprise" height="60px" style="margin-bottom:20px; margin-right:20px;"></a>
 <a href="https://www.zabbix.com/"><img src="docs/static/zabbix.png" alt="Zabbix" height="40px" style="margin-bottom:20px; margin-right:20px;"></a>
+<a href="https://sentry.io/"><img src="docs/static/sentry.png" alt="Sentry" height="40px" style="margin-bottom:20px; margin-right:20px;"></a>
 <a href="https://www.borgbase.com/?utm_source=borgmatic"><img src="docs/static/borgbase.png" alt="BorgBase" height="60px" style="margin-bottom:20px; margin-right:20px;"></a>
 
 

+ 39 - 1
borgmatic/config/schema.yaml

@@ -2259,7 +2259,45 @@ properties:
             can send the logs to a self-hosted instance or create an account at
             https://grafana.com/auth/sign-up/create-user. See borgmatic
             monitoring documentation for details.
-
+    sentry:
+        type: object
+        required: ['data_source_name_url', 'monitor_slug']
+        additionalProperties: false
+        properties:
+            data_source_name_url:
+                type: string
+                description: |
+                    Sentry Data Source Name (DSN) URL, associated with a
+                    particular Sentry project. Used to construct a cron URL,
+                    notified when a backup begins, ends, or errors.
+                example: https://5f80ec@o294220.ingest.us.sentry.io/203069
+            monitor_slug:
+                type: string
+                description: |
+                    Sentry monitor slug, associated with a particular Sentry
+                    project monitor. Used along with the data source name URL to
+                    construct a cron URL.
+                example: mymonitor
+            states:
+                type: array
+                items:
+                    type: string
+                    enum:
+                        - start
+                        - finish
+                        - fail
+                    uniqueItems: true
+                description: |
+                    List of one or more monitoring states to ping for: "start",
+                    "finish", and/or "fail". Defaults to pinging for all states.
+                example:
+                    - start
+                    - finish
+        description: |
+            Configuration for a monitoring integration with Sentry. You can use
+            a self-hosted instance via https://develop.sentry.dev/self-hosted/
+            or create a cloud-hosted account at https://sentry.io. See borgmatic
+            monitoring documentation for details.
     zfs:
         type: ["object", "null"]
         additionalProperties: false

+ 0 - 1
borgmatic/hooks/monitoring/ntfy.py

@@ -19,7 +19,6 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
     Ping the configured Ntfy topic. Use the given configuration filename in any log entries.
     If this is a dry run, then don't actually ping anything.
     '''
-
     run_states = hook_config.get('states', ['fail'])
 
     if state.name.lower() in run_states:

+ 79 - 0
borgmatic/hooks/monitoring/sentry.py

@@ -0,0 +1,79 @@
+import logging
+import re
+
+import requests
+
+logger = logging.getLogger(__name__)
+
+
+def initialize_monitor(
+    ping_url, config, config_filename, monitoring_log_level, dry_run
+):  # pragma: no cover
+    '''
+    No initialization is necessary for this monitor.
+    '''
+    pass
+
+
+DATA_SOURCE_NAME_URL_PATTERN = re.compile(
+    '^(?P<protocol>.*)://(?P<username>.*)@(?P<hostname>.*)/(?P<project_id>.*)$'
+)
+
+
+def ping_monitor(hook_config, config, config_filename, state, monitoring_log_level, dry_run):
+    '''
+    Construct and ping a Sentry cron URL, based on the configured DSN URL and monitor slug. Use the
+    given configuration filename in any log entries. If this is a dry run, then don't actually ping
+    anything.
+    '''
+    run_states = hook_config.get('states', ['start', 'finish', 'fail'])
+
+    if not state.name.lower() in run_states:
+        return
+
+    dry_run_label = ' (dry run; not actually pinging)' if dry_run else ''
+
+    data_source_name_url = hook_config.get('data_source_name_url')
+    monitor_slug = hook_config.get('monitor_slug')
+    match = DATA_SOURCE_NAME_URL_PATTERN.match(data_source_name_url)
+
+    if not match:
+        logger.warning(
+            'f{config_filename}: Invalid Sentry data source name URL: {data_source_name_url}'
+        )
+        return
+
+    cron_url = f'{match.group("protocol")}://{match.group("hostname")}/api/{match.group("project_id")}/cron/{monitor_slug}/{match.group("username")}/'
+
+    logger.info(f'{config_filename}: Pinging Sentry {state.name.lower()}{dry_run_label}')
+    logger.debug(f'{config_filename}: Using Sentry cron URL {cron_url}')
+
+    status = {
+        'start': 'in_progress',
+        'finish': 'ok',
+        'fail': 'error',
+    }.get(state.name.lower())
+
+    if not status:
+        logger.warning('f{config_filename}: Invalid Sentry state')
+        return
+
+    if dry_run:
+        return
+
+    logging.getLogger('urllib3').setLevel(logging.ERROR)
+    try:
+        response = requests.post(f'{cron_url}?status={status}')
+        if not response.ok:
+            response.raise_for_status()
+    except requests.exceptions.RequestException as error:
+        logger.warning(f'{config_filename}: Sentry error: {error}')
+
+
+def destroy_monitor(
+    ping_url_or_uuid, config, config_filename, monitoring_log_level, dry_run
+):  # pragma: no cover
+    '''
+    No destruction is necessary for this monitor.
+    '''
+    pass

+ 39 - 1
docs/how-to/monitor-your-backups.md

@@ -47,6 +47,7 @@ them as backups happen:
  * [ntfy](https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#ntfy-hook)
  * [PagerDuty](https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#pagerduty-hook)
  * [Pushover](https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#pushover-hook)
+ * [Sentry](https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#sentry-hook)
  * [Uptime Kuma](https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#uptime-kuma-hook)
  * [Zabbix](https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#zabbix-hook)
 
@@ -361,10 +362,47 @@ pushover:
 ```
 
 
+## Sentry hook
+
+<span class="minilink minilink-addedin">New in version 1.9.7</span>
+[Sentry](https://sentry.io/) is an application monitoring service that
+includes cron-style monitoring (either cloud-hosted or
+[self-hosted](https://develop.sentry.dev/self-hosted/)).
+
+To get started, create a [Sentry cron
+monitor](https://docs.sentry.io/product/crons/) in the Sentry UI. Under
+"Instrument your monitor," select "Sentry CLI" and copy the URL value for the
+displayed `SENTRY_DSN` environment variable into borgmatic's Sentry
+`data_source_name_url` configuration option. For example:
+
+```
+sentry:
+    data_source_name_url: https://5f80ec@o294220.ingest.us.sentry.io/203069
+    monitor_slug: mymonitor
+```
+
+The `monitor_slug` value comes from the "Monitor Slug" under "Cron Details" on
+the same Sentry monitor page.
+
+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
+behavior with the `states` configuration option. For instance, to only ping
+Sentry on failure:
+
+```
+sentry:
+    data_source_name_url: https://5f80ec@o294220.ingest.us.sentry.io/203069
+    monitor_slug: mymonitor
+    states:
+      - fail
+```
+
+
 ## ntfy hook
 
 <span class="minilink minilink-addedin">New in version 1.6.3</span>
-[ntfy](https://ntfy.sh) is a free, simple, service (either hosted or
+[ntfy](https://ntfy.sh) is a free, simple, service (either cloud-hosted or
 self-hosted) which offers simple pub/sub push notifications to multiple
 platforms including [web](https://ntfy.sh/stats),
 [Android](https://play.google.com/store/apps/details?id=io.heckel.ntfy) and