From e7724789c67b55bbd7641889a85b4a7155ae872e Mon Sep 17 00:00:00 2001 From: "Antonio J. Delgado" Date: Mon, 26 Dec 2022 18:03:05 +0200 Subject: [PATCH] Add logic to skeleton --- restic_exporter/restic_exporter.py | 81 ++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/restic_exporter/restic_exporter.py b/restic_exporter/restic_exporter.py index 25424b9..985a4aa 100644 --- a/restic_exporter/restic_exporter.py +++ b/restic_exporter/restic_exporter.py @@ -8,13 +8,14 @@ import sys import os import logging +import json import click import click_config_file from logging.handlers import SysLogHandler class restic_exporter: - def __init__(self, debug_level, log_file): + def __init__(self, debug_level, log_file, json_file, job_name, extra_labels, metric_name, metric_description): ''' Initial function called when object is created ''' self.config = dict() self.config['debug_level'] = debug_level @@ -23,6 +24,75 @@ class restic_exporter: self.config['log_file'] = log_file self._init_log() + self.metric_name = metric_name.replace(' ', '_') + self.metric_description = metric_description + self.labels= {} + + if extra_labels: + self.labels = { + **self.labels, + **self._read_extra_labels(extra_labels) + } + + self._read_summary_from_json(json_file) + + self._show_metrics() + + def _show_metrics(self): + labels = self._convert_labels(self.labels) + counters = [ + 'files_new', + 'files_changed', + 'files_unmodified', + 'dirs_new', + 'dirs_changed', + 'dirs_unmodified', + 'data_blobs', + 'tree_blobs', + 'data_added', + 'total_files_processed', + 'total_bytes_processed' + ] + print(f"# HELP {self.metric_name} {self.metric_description}.") + print(f"# TYPE {self.metric_name} counter") + for counter in counters: + print(f"{self.metric_name}_{counter}{labels} {float(self.summary[counter])} {self.summary['timestamp']}") + + def _read_summary_from_json(self, json_file): + with open(json_file, 'r') as file_pointer: + content = file_pointer.readlines() + + self.summary = {} + for line in content: + line_data = json.loads(line) + if 'message_type' in line_data and line_data['message_type'] == 'summary': + self.summary = line_data + if 'snapshot_id' in line_data: + self.labels["snapshot_id"] = line_data['snapshot_id'] + file_stats = os.stat(json_file) + self.summary['timestamp'] = round(file_stats.st_mtime) + self._log.debug(f"Summary: {json.dumps(self.summary, indent=2)}") + self._log.debug(f"Labels: {self.labels}") + + def _read_extra_labels(self, extra_labels): + labels_ls = {} + for pair in extra_labels.split(','): + if '=' in pair: + k, v=pair.split('=', 1) + labels_ls[k] = v + self._log.debug(f"Added extra label '{k}'='{v}'") + return labels_ls + + def _convert_labels(self, labels): + labels_ls = [] + for key in labels.keys(): + labels_ls.append(f"{key}=\"{labels[key]}\"") + text_labels = ','.join(labels_ls) + labels_string = "{" + text_labels + "}" + self._log.debug(f"Labels: {labels_string}") + return labels_string + + def _init_log(self): ''' Initialize log object ''' self._log = logging.getLogger("restic_exporter") @@ -62,9 +132,14 @@ class restic_exporter: ), help='Set the debug level for the standard output.') @click.option('--log-file', '-l', help="File to store all debug messages.") #@click.option("--dummy","-n" is_flag=True, help="Don't do anything, just show what would be done.") # Don't forget to add dummy to parameters of main function +@click.option("--json-file", "-j", required=True, help='JSON file containing the output of restic') +@click.option('--job-name', '-n', required=True, help='Restic job name to attach to the exported metrics') +@click.option('--extra-labels', '-a', required=False, default=None, help='Pairs key=value separated by commas with extra labels to add to the summary') +@click.option('--metric-name', '-m', default='restic_summary', help='Metric name. Spaces will be replaced with underscore (_).') +@click.option('--metric-description', '-d', default='Restic summary metrics', help='Metric description.') @click_config_file.configuration_option() -def __main__(debug_level, log_file): - return restic_exporter(debug_level, log_file) +def __main__(debug_level, log_file, json_file, job_name, extra_labels, metric_name, metric_description): + return restic_exporter(debug_level, log_file, json_file, job_name, extra_labels, metric_name, metric_description) if __name__ == "__main__": __main__()