import datetime import json import logging metrics_logger = logging.getLogger('metrics') class Metrics: def __init__(self, category: str, context: dict = None): self.context = context or {} self.metrics = {} self.category = category def add_metric(self, key, value): self.metrics[key] = value def send(self): self.send_metrics_to_log() self.send_metrics_to_stdout() def send_metrics_to_stdout(self): print(self.serialize_json()) def send_metrics_to_log(self): data = f'{self.category}: {self.serialize_json()}' metrics_logger.info(data) def serialize_json(self): result = {'metrics_category': self.category, **self.metrics, **self.context} return json.dumps(result) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.send() return False class DurationMetrics(Metrics): def __init__(self, category: str, context: dict = None): super().__init__(category, context) self.started_at = None self.completed_at = None self.duration = None def start(self): self.started_at = datetime.datetime.now() self.add_metric('started', self.started_at.replace(microsecond=0).isoformat()) def finish(self): self.completed_at = datetime.datetime.now() self.add_metric('completed', self.completed_at.replace(microsecond=0).isoformat()) self.duration = self.completed_at - self.started_at self.add_metric('duration_sec', round(self.duration.total_seconds())) def __enter__(self): self.start() return super().__enter__() def __exit__(self, exc_type, exc_val, exc_tb): self.finish() return super().__exit__(exc_type, exc_val, exc_tb)