Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog and versioning

## Unreleased

### New Features ✨

- Add `distribution` method to the metrics backend interface for recording distribution metrics

## 2.40.3

### New Features ✨
Expand Down
14 changes: 14 additions & 0 deletions arroyo/utils/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ def timing(
"""
raise NotImplementedError

@abstractmethod
def distribution(
self, name: MetricName, value: Union[int, float], tags: Optional[Tags] = None
) -> None:
"""
Records a distribution metric.
"""
raise NotImplementedError


class DummyMetricsBackend(Metrics):
"""
Expand All @@ -68,6 +77,11 @@ def timing(
) -> None:
pass

def distribution(
self, name: MetricName, value: Union[int, float], tags: Optional[Tags] = None
) -> None:
pass


class Gauge:
def __init__(
Expand Down
6 changes: 6 additions & 0 deletions docs/source/metrics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ This can be done like so:
# Emit a timing metric with the given value.
record_timing(name, value, tags)

def distribution(
self, name: MetricName, value: Union[int, float], tags: Optional[Tags] = None
) -> None:
# Emit a distribution metric with the given value.
record_distribution(name, value, tags)

metrics_backend = MyMetrics()

configure_metrics(metrics_backend)
Expand Down
15 changes: 13 additions & 2 deletions tests/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ class Timing(NamedTuple):
tags: Optional[Tags]


MetricCall = Union[Increment, Gauge, Timing]
class Distribution(NamedTuple):
name: MetricName
value: Union[int, float]
tags: Optional[Tags]


MetricCall = Union[Increment, Gauge, Timing, Distribution]


class _TestingMetricsBackend(Metrics):
Expand All @@ -32,7 +38,7 @@ class _TestingMetricsBackend(Metrics):
"""

def __init__(self) -> None:
self.calls: MutableSequence[Union[Increment, Gauge, Timing]] = []
self.calls: MutableSequence[Union[Increment, Gauge, Timing, Distribution]] = []

def increment(
self,
Expand All @@ -52,5 +58,10 @@ def timing(
) -> None:
self.calls.append(Timing(name, value, tags))

def distribution(
self, name: MetricName, value: Union[int, float], tags: Optional[Tags] = None
) -> None:
self.calls.append(Distribution(name, value, tags))


TestingMetricsBackend = _TestingMetricsBackend()
16 changes: 16 additions & 0 deletions tests/utils/test_metrics.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest

from arroyo.utils.metrics import Gauge, MetricName, configure_metrics, get_metrics
from tests.metrics import Distribution as DistributionCall
from tests.metrics import Gauge as GaugeCall
from tests.metrics import TestingMetricsBackend, _TestingMetricsBackend

Expand All @@ -22,6 +23,21 @@ def test_gauge_simple() -> None:
]


def test_distribution_simple() -> None:
backend = _TestingMetricsBackend()

name: MetricName = "name" # type: ignore
tags = {"tag": "value"}

backend.distribution(name, 1.0, tags)
backend.distribution(name, 2.0, tags)

assert backend.calls == [
DistributionCall(name, 1.0, tags),
DistributionCall(name, 2.0, tags),
]


def test_configure_metrics() -> None:
assert get_metrics() == TestingMetricsBackend

Expand Down
Loading