Example #1
0
class DogStatsdMonitoring(AbstractMonitoring):
    def __init__(self, config):
        super().__init__(config)
        self.client = DogStatsd()

    def send(self, tags, value):
        if len(tags) != 3:
            raise AssertionError(
                "Datadog monitoring implementation needs 3 tags: 'name', 'what' and 'backup_name'"
            )

        name, what, backup_name = tags
        metric = '{name}.{what}'.format(name=name, what=what)
        backup_name_tag = 'backup_name:{}'.format(backup_name)

        # The backup_name  would be a rather high cardinality metrics series if backups are at all frequent.
        # This could be a expensive metric so backup_name is droppped from the tags sent by default
        if medusa.utils.evaluate_boolean(self.config.send_backup_name_tag):
            self.client.gauge(metric, value, tags=[backup_name_tag])
        else:
            self.client.gauge(metric, value)
Example #2
0
class DatadogStatsClient:
    """Statsd compliant datadog client."""
    def __init__(self,
                 host: str = 'localhost',
                 port: int = 8125,
                 prefix: str = 'faust-app',
                 rate: float = 1.0,
                 **kwargs: Any) -> None:
        self.client = DogStatsd(host=host,
                                port=port,
                                namespace=prefix,
                                **kwargs)
        self.rate = rate
        self.sanitize_re = re.compile(r'[^0-9a-zA-Z_]')
        self.re_substitution = '_'

    def gauge(self, metric: str, value: float, labels: Dict = None) -> None:
        self.client.gauge(
            metric,
            value=value,
            tags=self._encode_labels(labels),
            sample_rate=self.rate,
        )

    def increment(self,
                  metric: str,
                  value: float = 1.0,
                  labels: Dict = None) -> None:
        self.client.increment(
            metric,
            value=value,
            tags=self._encode_labels(labels),
            sample_rate=self.rate,
        )

    def incr(self, metric: str, count: int = 1) -> None:
        """Statsd compatibility."""
        self.increment(metric, value=count)

    def decrement(self,
                  metric: str,
                  value: float = 1.0,
                  labels: Dict = None) -> float:
        return self.client.decrement(
            metric,
            value=value,
            tags=self._encode_labels(labels),
            sample_rate=self.rate,
        )

    def decr(self, metric: str, count: float = 1.0) -> None:
        """Statsd compatibility."""
        self.decrement(metric, value=count)

    def timing(self, metric: str, value: float, labels: Dict = None) -> None:
        self.client.timing(
            metric,
            value=value,
            tags=self._encode_labels(labels),
            sample_rate=self.rate,
        )

    def timed(self,
              metric: str = None,
              labels: Dict = None,
              use_ms: bool = None) -> float:
        return self.client.timed(
            metric=metric,
            tags=self._encode_labels(labels),
            sample_rate=self.rate,
            use_ms=use_ms,
        )

    def histogram(self,
                  metric: str,
                  value: float,
                  labels: Dict = None) -> None:
        self.client.histogram(
            metric,
            value=value,
            tags=self._encode_labels(labels),
            sample_rate=self.rate,
        )

    def _encode_labels(self, labels: Optional[Dict]) -> Optional[List[str]]:
        def sanitize(s: str) -> str:
            return self.sanitize_re.sub(self.re_substitution, str(s))

        return [f'{sanitize(k)}:{sanitize(v)}'
                for k, v in labels.items()] if labels else None
class DogStatsdAdapter(object):
    """
    A wrapper around DogStatsd that supports the full statsd.StatsClient interface
    Note that `tags` is available on all these methods, but this is not supported by statsd.StatsClient. It has been
    added, but should only be used when you are CERTAIN that you will be using this class (or something similar)
    """
    def __init__(self,
                 host='localhost',
                 port=8125,
                 prefix=None,
                 maxudpsize=512,
                 ipv6=False):
        if ipv6:
            _log.warning("DogStatsdAdapter() was 'ipv6'. This is ignored")

        self._dd_client = DogStatsd(host=host,
                                    port=port,
                                    namespace=prefix,
                                    max_buffer_size=maxudpsize)

    def timer(self, stat, rate=1, tags=None):
        self._dd_client.timed(metric=stat,
                              sample_rate=rate,
                              use_ms=True,
                              tags=tags)

    def timing(self, stat, delta, rate=1, tags=None):
        """Send new timing information. `delta` is in milliseconds."""
        self._dd_client.timing(metric=stat,
                               value=delta,
                               sample_rate=rate,
                               tags=tags)

    def incr(self, stat, count=1, rate=1, tags=None):
        """Increment a stat by `count`."""
        self._dd_client.increment(metric=stat,
                                  value=count,
                                  sample_rate=rate,
                                  tags=tags)

    def decr(self, stat, count=1, rate=1, tags=None):
        """Decrement a stat by `count`."""
        self._dd_client.decrement(metric=stat,
                                  value=count,
                                  sample_rate=rate,
                                  tags=tags)

    def gauge(self, stat, value, rate=1, delta=False, tags=None):
        """Set a gauge value."""
        self._dd_client.gauge(metric=stat,
                              value=value,
                              sample_rate=rate,
                              tags=tags)
        if delta:
            _log.warning(
                "DogStatsdAdapter was passed a gauge with 'delta' set. This is ignored in datadog"
            )

    def set(self, stat, value, rate=1, tags=None):
        """Set a set value."""
        self._dd_client.set(metric=stat,
                            value=value,
                            sample_rate=rate,
                            tags=tags)

    def histogram(self, stat, value, rate=1, tags=None):
        """
        Sample a histogram value, optionally setting tags and a sample rate.
        This is not supported by statsd.StatsClient. Use with caution!
        """
        self._dd_client.set(metric=stat,
                            value=value,
                            sample_rate=rate,
                            tags=tags)
Example #4
0
class DogStatsdMetrics(Metrics):
    def __init__(self,
                 id,
                 prefix=None,
                 tags=None,
                 host="127.0.0.1",
                 port=8125):
        self.id = id
        self.prefix = prefix
        self.tags = tags or {}
        self.host = host
        self.port = port
        self.tags["instance"] = id

    def setup(self):
        from datadog.dogstatsd import DogStatsd

        self.client = DogStatsd(host=self.host, port=self.port)

    def gauge(self, metric, value, tags=None, sample_rate=1):
        self.client.gauge(
            self._get_key(metric),
            value,
            sample_rate=sample_rate,
            tags=self._get_tags(tags),
        )

    def increment(self, metric, value=1, tags=None, sample_rate=1):
        self.client.increment(
            self._get_key(metric),
            value,
            sample_rate=sample_rate,
            tags=self._get_tags(tags),
        )

    def decrement(self, metric, value=1, tags=None, sample_rate=1):
        self.client.decrement(
            self._get_key(metric),
            value,
            sample_rate=sample_rate,
            tags=self._get_tags(tags),
        )

    def histogram(self, metric, value, tags=None, sample_rate=1):
        self.client.histogram(
            self._get_key(metric),
            value,
            sample_rate=sample_rate,
            tags=self._get_tags(tags),
        )

    def timing(self, metric, value, tags=None, sample_rate=1):
        self.client.timing(
            self._get_key(metric),
            value,
            sample_rate=sample_rate,
            tags=self._get_tags(tags),
        )

    def timed(self, metric, tags=None, sample_rate=1, use_ms=None):
        self.client.timed(
            self._get_key(metric),
            sample_rate=sample_rate,
            tags=self._get_tags(tags),
            use_ms=use_ms,
        )