From 869753974882dc8c8e276c28f4549f7a28542f1b Mon Sep 17 00:00:00 2001 From: ngosang Date: Sun, 30 Jul 2023 01:02:04 +0200 Subject: [PATCH] Include backup paths in the exported metrics. Resolves #17 --- README.md | 13 +++++++------ restic-exporter.py | 9 ++++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f2344ef..f3158a6 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,8 @@ is `Flase` (only log error, such as network error with Cloud backends). reasons. Default is `False` (perform `restic check`). - `NO_STATS`: (Optional) Do not collect per backup statistics for performance reasons. Default is `False` (collect per backup statistics). -- `NO_LOCKS`: (Optional) Do not collect the number of locks. Default is `False` (collect number of locks). +- `NO_LOCKS`: (Optional) Do not collect the number of locks. Default is `False` (collect the number of locks). +- `INCLUDE_PATHS`: (Optional) Include snapshot paths for each backup. The paths are separated by commas. Default is `False` (not collect the paths). ### Configuration for Rclone @@ -163,17 +164,17 @@ restic_locks_total 1.0 restic_snapshots_total 100.0 # HELP restic_backup_timestamp Timestamp of the last backup # TYPE restic_backup_timestamp gauge -restic_backup_timestamp{client_hostname="product.example.com",client_username="root",snapshot_hash="20795072cba0953bcdbe52e9cf9d75e5726042f5bbf2584bb2999372398ee835",snapshot_tag="mysql"} 1.666273638e+09 +restic_backup_timestamp{client_hostname="product.example.com",client_username="root",snapshot_hash="20795072cba0953bcdbe52e9cf9d75e5726042f5bbf2584bb2999372398ee835",snapshot_tag="mysql",snapshot_paths="/mysql/data,/mysql/config"} 1.666273638e+09 # HELP restic_backup_files_total Number of files in the backup # TYPE restic_backup_files_total counter -restic_backup_files_total{client_hostname="product.example.com",client_username="root",snapshot_hash="20795072cba0953bcdbe52e9cf9d75e5726042f5bbf2584bb2999372398ee835",snapshot_tag="mysql"} 8.0 +restic_backup_files_total{client_hostname="product.example.com",client_username="root",snapshot_hash="20795072cba0953bcdbe52e9cf9d75e5726042f5bbf2584bb2999372398ee835",snapshot_tag="mysql",snapshot_paths="/mysql/data,/mysql/config"} 8.0 # HELP restic_backup_size_total Total size of backup in bytes # TYPE restic_backup_size_total counter -restic_backup_size_total{client_hostname="product.example.com",client_username="root",snapshot_hash="20795072cba0953bcdbe52e9cf9d75e5726042f5bbf2584bb2999372398ee835",snapshot_tag="mysql"} 4.3309562e+07 +restic_backup_size_total{client_hostname="product.example.com",client_username="root",snapshot_hash="20795072cba0953bcdbe52e9cf9d75e5726042f5bbf2584bb2999372398ee835",snapshot_tag="mysql",snapshot_paths="/mysql/data,/mysql/config"} 4.3309562e+07 # HELP restic_backup_snapshots_total Total number of snapshots # TYPE restic_backup_snapshots_total counter -restic_backup_snapshots_total{client_hostname="product.example.com",client_username="root",snapshot_hash="20795072cba0953bcdbe52e9cf9d75e5726042f5bbf2584bb2999372398ee835",snapshot_tag="mysql"} 1.0 -# HELP restic_scrape_duration_seconds Ammount of time each scrape takes +restic_backup_snapshots_total{client_hostname="product.example.com",client_username="root",snapshot_hash="20795072cba0953bcdbe52e9cf9d75e5726042f5bbf2584bb2999372398ee835",snapshot_tag="mysql",snapshot_paths="/mysql/data,/mysql/config"} 1.0 +# HELP restic_scrape_duration_seconds Amount of time each scrape takes # TYPE restic_scrape_duration_seconds gauge restic_scrape_duration_seconds 166.9411084651947 ``` diff --git a/restic-exporter.py b/restic-exporter.py index af097fa..744c073 100644 --- a/restic-exporter.py +++ b/restic-exporter.py @@ -16,7 +16,8 @@ from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily, REGIS class ResticCollector(object): def __init__( - self, repository, password_file, exit_on_error, disable_check, disable_stats, disable_locks + self, repository, password_file, exit_on_error, disable_check, + disable_stats, disable_locks, include_paths ): self.repository = repository self.password_file = password_file @@ -24,6 +25,7 @@ class ResticCollector(object): self.disable_check = disable_check self.disable_stats = disable_stats self.disable_locks = disable_locks + self.include_paths = include_paths # todo: the stats cache increases over time -> remove old ids # todo: cold start -> the stats cache could be saved in a persistent volume # todo: cold start -> the restic cache (/root/.cache/restic) could be @@ -40,6 +42,7 @@ class ResticCollector(object): "client_username", "snapshot_hash", "snapshot_tag", + "snapshot_paths", ] check_success = GaugeMetricFamily( @@ -93,6 +96,7 @@ class ResticCollector(object): client["username"], client["snapshot_hash"], client["snapshot_tag"], + client["snapshot_paths"], ] backup_timestamp.add_metric(common_label_values, client["timestamp"]) @@ -177,6 +181,7 @@ class ResticCollector(object): "username": snap["username"], "snapshot_hash": snap["hash"], "snapshot_tag": snap["tags"][0] if "tags" in snap else "", + "snapshot_paths": ",".join(snap["paths"]) if self.include_paths else "", "timestamp": snap["timestamp"], "size_total": stats["total_size"], "files_total": stats["total_file_count"], @@ -355,6 +360,7 @@ if __name__ == "__main__": exporter_disable_check = bool(os.environ.get("NO_CHECK", False)) exporter_disable_stats = bool(os.environ.get("NO_STATS", False)) exporter_disable_locks = bool(os.environ.get("NO_LOCKS", False)) + exporter_include_paths = bool(os.environ.get("INCLUDE_PATHS", False)) try: collector = ResticCollector( @@ -364,6 +370,7 @@ if __name__ == "__main__": exporter_disable_check, exporter_disable_stats, exporter_disable_locks, + exporter_include_paths, ) REGISTRY.register(collector) start_http_server(exporter_port, exporter_address)