Skip to content

Commit

Permalink
refactor monitoring clients
Browse files Browse the repository at this point in the history
  • Loading branch information
egor-voynov-aiven committed Aug 2, 2024
1 parent af93d79 commit 2a347ac
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 44 deletions.
1 change: 0 additions & 1 deletion pghoard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
Copyright (c) 2016 Ohmu Ltd
See LICENSE for details
"""
from . import mapping, monitoring
2 changes: 1 addition & 1 deletion pghoard/basebackup/delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def _delta_upload_hexdigest(
result_hash = hashlib.blake2s()

def progress_callback(n_bytes: int = 1) -> None:
self.metrics.increase("pghoard.basebackup_bytes_uploaded", inc_value=n_bytes, tags={"delta": True})
self.metrics.increase("pghoard.basebackup_bytes_uploaded", inc_value=n_bytes, tags={"delta": "True"})

with NamedTemporaryFile(dir=temp_dir, prefix=os.path.basename(chunk_path), suffix=".tmp") as raw_output_obj:
raw_output_file = cast(FileLikeWithName, raw_output_obj)
Expand Down
6 changes: 0 additions & 6 deletions pghoard/mapping.py

This file was deleted.

61 changes: 42 additions & 19 deletions pghoard/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,60 @@
Interface for monitoring clients
"""
import pghoard
import logging
from dataclasses import dataclass
from typing import Any, Dict, Optional, Type

from pghoard.monitoring import (PrometheusClient, PushgatewayClient, SentryClient, StatsClient)

class Metrics:
def __init__(self, **configs):
self.clients = self._init_clients(configs)
LOG = logging.getLogger(__name__)


class MetricsClient:
def __init__(self, config: Dict[str, Any]):
self.config = config

def gauge(self, metric: str, value: float, tags: Optional[Dict[str, str]] = None) -> None:
pass

def increase(self, metric: str, inc_value: int = 1, tags: Optional[Dict[str, str]] = None) -> None:
pass

def _init_clients(self, configs):
clients = {}
def unexpected_exception(self, ex: Exception, where: str, tags: Optional[Dict[str, str]] = None) -> None:
pass

if not isinstance(configs, dict):
return clients

map_client = pghoard.mapping.clients
for k, config in configs.items():
if isinstance(config, dict) and k in map_client:
path, classname = map_client[k]
mod = __import__(path, fromlist=[classname])
klass = getattr(mod, classname)
clients[k] = klass(config)
@dataclass()
class AvailableClient:
client_class: Type[MetricsClient]
config_key: str


class Metrics:
available_clients = [
AvailableClient(StatsClient, "statsd"),
AvailableClient(PrometheusClient, "prometheus"),
AvailableClient(PushgatewayClient, "pushgateway"),
AvailableClient(SentryClient, "sentry"),
]

def __init__(self, **configs):
self.clients = {}

return clients
for client_info in self.available_clients:
client_config = configs.get(client_info.config_key)
if isinstance(client_config, dict):
LOG.info("Initializing monitoring client %s", client_info.config_key)
self.clients[client_info.config_key] = client_info.client_class(client_config)

def gauge(self, metric, value, tags=None):
def gauge(self, metric: str, value: float, tags: Optional[Dict[str, str]] = None) -> None:
for client in self.clients.values():
client.gauge(metric, value, tags)

def increase(self, metric, inc_value=1, tags=None):
def increase(self, metric: str, inc_value: int = 1, tags: Optional[Dict[str, str]] = None) -> None:
for client in self.clients.values():
client.increase(metric, inc_value, tags)

def unexpected_exception(self, ex, where, tags=None):
def unexpected_exception(self, ex: Exception, where: str, tags: Optional[Dict[str, str]] = None) -> None:
for client in self.clients.values():
client.unexpected_exception(ex, where, tags)
10 changes: 5 additions & 5 deletions pghoard/monitoring/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pkgutil

__path__ = pkgutil.extend_path(__path__, __name__) # type: ignore
for importer, modname, ispkg in pkgutil.walk_packages(path=__path__, prefix=__name__ + "."):
__import__(modname)
# Copyright (c) 2024 Aiven, Helsinki, Finland. https://aiven.io/
from .prometheus import PrometheusClient
from .pushgateway import PushgatewayClient
from .sentry import SentryClient
from .statsd import StatsClient
5 changes: 4 additions & 1 deletion pghoard/monitoring/prometheus.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@

import time

from pghoard.metrics import MetricsClient

class PrometheusClient:

class PrometheusClient(MetricsClient):
def __init__(self, config):
super().__init__(config)
self._tags = config.get("tags", {})
self.metrics = {}

Expand Down
5 changes: 4 additions & 1 deletion pghoard/monitoring/pushgateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@

import requests

from pghoard.metrics import MetricsClient

class PushgatewayClient:

class PushgatewayClient(MetricsClient):
def __init__(self, config):
super().__init__(config)
self._endpoint = config.get("endpoint", "")
self._job = config.get("job", "pghoard")
self._instance = config.get("instance", "")
Expand Down
17 changes: 8 additions & 9 deletions pghoard/monitoring/sentry.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# Copyright (c) 2024 Aiven, Helsinki, Finland. https://aiven.io/
import logging
from typing import Any, Dict, Optional

from pghoard.metrics import MetricsClient

LOG = logging.getLogger(__name__)


class SentryClient:
def __init__(self, config):
class SentryClient(MetricsClient):
def __init__(self, config: Dict[str, Any]):
super().__init__(config)
self.sentry = None
if config is None:
LOG.info("Sentry configuration not found, skipping setup")
Expand All @@ -29,13 +34,7 @@ def __init__(self, config):
for key, value in tags.items():
sentry_sdk.set_tag(key, value)

def gauge(self, metric, value, tags=None):
pass

def increase(self, metric, inc_value=1, tags=None):
pass

def unexpected_exception(self, ex, where, tags=None):
def unexpected_exception(self, ex: Exception, where: str, tags: Optional[Dict[str, str]] = None) -> None:
if not self.sentry:
return

Expand Down
5 changes: 4 additions & 1 deletion pghoard/monitoring/statsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
"""
import socket

from pghoard.metrics import MetricsClient

class StatsClient:

class StatsClient(MetricsClient):
def __init__(self, config):
super().__init__(config)
self._dest_addr = (config.get("host", "127.0.0.1"), config.get("port", 8125))
self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._tags = config.get("tags", {})
Expand Down

0 comments on commit 2a347ac

Please sign in to comment.