Skip to content

Commit 48c7f2c

Browse files
committed
Add metrics tracking for ogr API calls per namespace and service type
1 parent 2b66f57 commit 48c7f2c

File tree

4 files changed

+94
-2
lines changed

4 files changed

+94
-2
lines changed

packit_service/celery_config.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
"schedule": 10800.0,
5555
"options": {"queue": "long-running", "time_limit": 3600},
5656
},
57+
"push-ogr-namespace-metrics": {
58+
"task": "packit_service.worker.tasks.push_ogr_namespace_metrics",
59+
"schedule": 300.0,
60+
"options": {"queue": "short-running"},
61+
},
5762
}
5863

5964
# http://mher.github.io/flower/prometheus-integration.html#set-up-your-celery-application

packit_service/worker/monitoring.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import logging
55
import os
66

7-
from prometheus_client import CollectorRegistry, Counter, Histogram, push_to_gateway
7+
from prometheus_client import CollectorRegistry, Counter, Gauge, Histogram, push_to_gateway
88

99
logger = logging.getLogger(__name__)
1010

@@ -265,6 +265,13 @@ def __init__(self):
265265
buckets=(5, 15, 20, 25, 30, 40, 60, float("inf")),
266266
)
267267

268+
self.ogr_namespace_requests = Gauge(
269+
"ogr_namespace_requests_total",
270+
"Total number of ogr API requests per instance URL and namespace in the last 5 minutes",
271+
["instance_url", "namespace"],
272+
registry=self.registry,
273+
)
274+
268275
def push(self):
269276
if not (self.pushgateway_address and self.worker_name):
270277
logger.debug("Pushgateway address or worker name not defined.")

packit_service/worker/tasks.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from copr.v3 import CoprException
1414
from ogr import __version__ as ogr_version
1515
from ogr.exceptions import OgrException
16+
from ogr.metrics import get_metrics_tracker
1617
from packit import __version__ as packit_version
1718
from packit.exceptions import PackitException
1819
from sqlalchemy import __version__ as sqlal_version
@@ -101,6 +102,7 @@
101102
update_vm_image_build,
102103
)
103104
from packit_service.worker.jobs import SteveJobs
105+
from packit_service.worker.monitoring import Pushgateway
104106
from packit_service.worker.result import TaskResults
105107

106108
logger = logging.getLogger(__name__)
@@ -970,3 +972,37 @@ def get_usage_statistics() -> None:
970972
logger.debug(f"Getting usage data from datetime_from {day}.")
971973
get_usage_data(datetime_from=day)
972974
logger.debug("Got usage data.")
975+
976+
977+
@celery_app.task
978+
def push_ogr_namespace_metrics() -> None:
979+
"""
980+
Collect ogr namespace request metrics and push them to pushgateway.
981+
982+
This task queries the ogr metrics tracker for request counts per instance URL
983+
and namespace, then updates the Prometheus metrics and pushes them.
984+
After pushing, the counters are reset for the next collection period.
985+
"""
986+
logger.debug("Collecting ogr namespace request metrics.")
987+
988+
try:
989+
metrics_tracker = get_metrics_tracker()
990+
counts = metrics_tracker.get_all_counts()
991+
992+
pushgateway = Pushgateway()
993+
994+
for (instance_url, namespace), count in counts.items():
995+
pushgateway.ogr_namespace_requests.labels(
996+
instance_url=instance_url,
997+
namespace=namespace,
998+
).set(count)
999+
1000+
pushgateway.push()
1001+
1002+
metrics_tracker.reset()
1003+
1004+
logger.info(
1005+
f"Pushed ogr namespace metrics: {len(counts)} instance/namespace combinations",
1006+
)
1007+
except Exception as e:
1008+
logger.error(f"Failed to push ogr namespace metrics: {e}", exc_info=True)

tests/unit/test_tasks.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from packit.exceptions import PackitException
99

1010
from packit_service.worker.handlers import CoprBuildHandler
11-
from packit_service.worker.tasks import run_copr_build_handler
11+
from packit_service.worker.tasks import push_ogr_namespace_metrics, run_copr_build_handler
1212

1313

1414
def test_autoretry():
@@ -21,3 +21,47 @@ def test_autoretry():
2121
flexmock(Task).should_receive("retry").and_raise(PackitException).once()
2222
with pytest.raises(PackitException):
2323
run_copr_build_handler({}, {}, {})
24+
25+
26+
def test_push_metrics_handles_exception():
27+
"""Test that exceptions are handled gracefully."""
28+
from packit_service.worker import tasks
29+
30+
mock_tracker = flexmock()
31+
mock_tracker.should_receive("get_all_counts").and_raise(Exception("Test error")).once()
32+
33+
flexmock(tasks).should_receive("get_metrics_tracker").and_return(mock_tracker).once()
34+
35+
push_ogr_namespace_metrics()
36+
37+
38+
def test_push_metrics_resets_after_push():
39+
"""Test that reset is called after pushing metrics."""
40+
from packit_service.worker import tasks
41+
42+
mock_tracker = flexmock()
43+
mock_tracker.should_receive("get_all_counts").and_return(
44+
{("https://github.com", "packit"): 1}
45+
).once()
46+
# Verify reset is called after push
47+
mock_tracker.should_receive("reset").once()
48+
49+
flexmock(tasks).should_receive("get_metrics_tracker").and_return(mock_tracker).once()
50+
51+
# Mock Pushgateway
52+
mock_gauge = flexmock()
53+
mock_gauge.should_receive("set").with_args(1).once()
54+
55+
mock_pushgateway = flexmock()
56+
mock_pushgateway.ogr_namespace_requests = flexmock()
57+
mock_pushgateway.ogr_namespace_requests.should_receive("labels").with_args(
58+
instance_url="https://github.com", namespace="packit"
59+
).and_return(mock_gauge).once()
60+
mock_pushgateway.should_receive("push").once()
61+
62+
from packit_service.worker.monitoring import Pushgateway
63+
64+
flexmock(Pushgateway).should_receive("__init__").and_return(None)
65+
flexmock(Pushgateway).new_instances(mock_pushgateway)
66+
67+
push_ogr_namespace_metrics()

0 commit comments

Comments
 (0)