Skip to content

Commit

Permalink
Report request size
Browse files Browse the repository at this point in the history
  • Loading branch information
leplatrem committed Oct 29, 2024
1 parent 7c7ea92 commit 367dfa3
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 0 deletions.
7 changes: 7 additions & 0 deletions kinto/core/initialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,13 @@ def on_new_response(event):
],
)

# Observe response size.
metrics_service.observe(
"request_size",
len(request.response.body or b""),
labels=[("endpoint", utils.strip_uri_prefix(request.path))],
)

# Count authentication verifications.
if hasattr(request, "authn_type"):
metrics_service.count(f"authn_type.{request.authn_type}")
Expand Down
5 changes: 5 additions & 0 deletions kinto/core/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ def timer(key):
Watch execution time.
"""

def observe(self, key, value, labels=[]):
"""
Observe a give `value` for the specified `key`.
"""

def count(key, count=1, unique=None):
"""
Count occurrences. If `unique` is set, overwrites the counter value
Expand Down
22 changes: 22 additions & 0 deletions kinto/plugins/prometheus.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,28 @@ def timer(self, key):

return Timer(_METRICS[key])

def observe(self, key, value, labels=[]):
global _METRICS

if key not in _METRICS:
_METRICS[key] = prometheus_module.Summary(
_fix_metric_name(key),
f"Summary of {key}",
labelnames=[label_name for label_name, _ in labels],
registry=get_registry(),
)

if not isinstance(_METRICS[key], prometheus_module.Summary):
raise RuntimeError(
f"Metric {key} already exists with different type ({_METRICS[key]})"
)

m = _METRICS[key]
if labels:
m = m.labels(*(label_value for _, label_value in labels))

m.observe(value)

def count(self, key, count=1, unique=None):
global _METRICS

Expand Down
3 changes: 3 additions & 0 deletions kinto/plugins/statsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ def __init__(self, host, port, prefix):
def timer(self, key):
return self._client.timer(key)

def observe(self, key, value, labels=[]):
return self._client.gauge(key, value)

def count(self, key, count=1, unique=None):
if unique is None:
return self._client.incr(key, count=count)
Expand Down
10 changes: 10 additions & 0 deletions tests/core/test_initialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,16 @@ def test_statsd_counts_endpoints(self):
unique=[("method", "get"), ("endpoint", "/__heartbeat__"), ("status", "200")],
)

def test_statsd_observe_request_size(self):
kinto.core.initialize(self.config, "0.0.1", "settings_prefix")
app = webtest.TestApp(self.config.make_wsgi_app())
app.get("/v0/__heartbeat__")
self.mocked().observe.assert_any_call(
"request_size",
len("{}"),
labels=[("endpoint", "/__heartbeat__")],
)

def test_statsd_counts_views_and_methods(self):
kinto.core.initialize(self.config, "0.0.1", "settings_prefix")
app = webtest.TestApp(self.config.make_wsgi_app())
Expand Down
16 changes: 16 additions & 0 deletions tests/plugins/test_prometheus.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ def test_timer_can_be_used_as_decorator_on_partial_function(self):
resp = self.app.get("/__metrics__")
self.assertIn("TYPE func_latency_partial summary", resp.text)

def test_observe_a_single_value(self):
self.app.app.registry.metrics.observe("price", 111)

resp = self.app.get("/__metrics__")
self.assertIn("price_sum 111", resp.text)

def test_observe_a_single_value_with_labels(self):
self.app.app.registry.metrics.observe("size", 3.14, labels=[("endpoint", "/buckets")])

resp = self.app.get("/__metrics__")
self.assertIn('size_sum{endpoint="/buckets"} 3.14', resp.text)

def test_count_by_key(self):
self.app.app.registry.metrics.count("key")

Expand Down Expand Up @@ -107,6 +119,10 @@ def test_metrics_cant_be_mixed(self):
with self.assertRaises(RuntimeError):
self.app.app.registry.metrics.count("timer")

self.app.app.registry.metrics.count("observer")
with self.assertRaises(RuntimeError):
self.app.app.registry.metrics.observe("observer", 42)

def test_metrics_names_and_labels_are_transformed(self):
self.app.app.registry.metrics.count("http.home.status", unique=[("code.get", "200")])

Expand Down
5 changes: 5 additions & 0 deletions tests/plugins/test_statsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ def setUp(self):
self.mocked_client = patch.start()
self.addCleanup(patch.stop)

def test_observe_a_single_value(self):
with mock.patch.object(self.client, "_client") as mocked_client:
self.client.observe("size", 3.14)
mocked_client.gauge.assert_called_with("size", 3.14)

def test_count_increments_the_counter_for_key(self):
with mock.patch.object(self.client, "_client") as mocked_client:
self.client.count("click")
Expand Down

0 comments on commit 367dfa3

Please sign in to comment.