Skip to content

Commit c1b2dfb

Browse files
Implement metrics for Fedora CI (#3007)
Implement metrics for Fedora CI Fixes #2975 Assisted-by: Cursor(Claude) Reviewed-by: gemini-code-assist[bot] Reviewed-by: Nikola Forró Reviewed-by: Laura Barcziová
2 parents 983c59f + 36b0247 commit c1b2dfb

File tree

8 files changed

+136
-7
lines changed

8 files changed

+136
-7
lines changed

packit_service/worker/handlers/distgit.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,7 @@ def _run(self) -> TaskResults:
921921
description="RPM build was submitted ...",
922922
url=url,
923923
)
924+
self.pushgateway.fedora_ci_koji_builds_queued.inc()
924925
except Exception as ex:
925926
sentry_integration.send_to_sentry(ex)
926927
self.report(

packit_service/worker/handlers/koji.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import logging
99
from abc import ABC, abstractmethod
10-
from datetime import datetime
10+
from datetime import datetime, timezone
1111
from os import getenv
1212
from typing import Optional
1313

@@ -42,6 +42,7 @@
4242
from packit_service.utils import (
4343
dump_job_config,
4444
dump_package_config,
45+
elapsed_seconds,
4546
)
4647
from packit_service.worker.checker.abstract import Checker
4748
from packit_service.worker.checker.koji import (
@@ -162,6 +163,9 @@ def notify_about_failure_if_configured(
162163
def trigger_log_detective_if_configured(self):
163164
pass
164165

166+
@abstractmethod
167+
def push_metrics(self) -> None: ...
168+
165169
@property
166170
def build(self) -> Optional[KojiBuildTargetModel]:
167171
if not self._build:
@@ -242,6 +246,7 @@ def _run(self) -> TaskResults:
242246
)
243247

244248
else:
249+
self.push_metrics()
245250
self.build.set_status(new_commit_status.value)
246251
self.report(description, new_commit_status, dashboard_url, koji_web_url)
247252
koji_build_logs = self.koji_task_event.get_koji_build_rpm_tasks_logs_urls(
@@ -319,6 +324,9 @@ def notify_about_failure_if_configured(
319324
def trigger_log_detective_if_configured(self):
320325
pass
321326

327+
def push_metrics(self) -> None:
328+
pass
329+
322330

323331
@reacts_to_as_fedora_ci(event=koji.result.Task)
324332
class KojiTaskReportDownstreamHandler(AbstractKojiTaskReportHandler, FedoraCIJobHandler):
@@ -376,6 +384,21 @@ def trigger_log_detective_if_configured(self):
376384
if not trigger_success:
377385
logger.error("Log Detective was not properly triggered for a failed Koji build")
378386

387+
def push_metrics(self) -> None:
388+
"""Track Fedora CI Koji build metrics."""
389+
state = self.koji_task_event.state
390+
391+
if state == KojiTaskState.open:
392+
self.pushgateway.fedora_ci_koji_builds_started.inc()
393+
elif state in (KojiTaskState.closed, KojiTaskState.canceled, KojiTaskState.failed):
394+
self.pushgateway.fedora_ci_koji_builds_finished.inc()
395+
if self.build.submitted_time:
396+
koji_build_time = elapsed_seconds(
397+
begin=self.build.submitted_time,
398+
end=datetime.now(timezone.utc),
399+
)
400+
self.pushgateway.fedora_ci_koji_build_finished_time.observe(koji_build_time)
401+
379402

380403
@configured_as(job_type=JobType.koji_build)
381404
@configured_as(job_type=JobType.bodhi_update)

packit_service/worker/handlers/testing_farm.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ def run_for_fedora_ci_test(
458458
failed: dict,
459459
):
460460
if self.celery_task.retries == 0:
461-
self.pushgateway.test_runs_queued.inc()
461+
self.pushgateway.fedora_ci_test_runs_queued.inc()
462462
result = self.downstream_testing_farm_job_helper.run_testing_farm(test_run)
463463
if not result["success"]:
464464
failed[test_run.data["fedora_ci_test"]] = result.get("details")
@@ -697,14 +697,14 @@ def _run(self) -> TaskResults:
697697
summary = self.summary or "Error ..."
698698

699699
if self.result == TestingFarmResult.running:
700-
self.pushgateway.test_runs_started.inc()
700+
self.pushgateway.fedora_ci_test_runs_started.inc()
701701
else:
702-
self.pushgateway.test_runs_finished.inc()
702+
self.pushgateway.fedora_ci_test_runs_finished.inc()
703703
test_run_time = elapsed_seconds(
704704
begin=test_run_model.submitted_time,
705705
end=datetime.now(timezone.utc),
706706
)
707-
self.pushgateway.test_run_finished_time.observe(test_run_time)
707+
self.pushgateway.fedora_ci_test_run_finished_time.observe(test_run_time)
708708

709709
test_run_model.set_web_url(self.log_url)
710710
# For Fedora CI, try to link directly to Testing Farm results instead of dashboard

packit_service/worker/jobs.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ def report_task_accepted_for_fedora_ci(self, handler_kls: type[FedoraCIJobHandle
507507
target_branch=self.event.pull_request_object.target_branch,
508508
)
509509

510+
first_status_reported = False
510511
for check_name in handler_kls.get_check_names(
511512
self.service_config, self.event.project, metadata
512513
):
@@ -516,6 +517,18 @@ def report_task_accepted_for_fedora_ci(self, handler_kls: type[FedoraCIJobHandle
516517
url="",
517518
check_name=check_name,
518519
)
520+
# Track the time for the first status report
521+
if not first_status_reported:
522+
first_status_reported = True
523+
response_time = elapsed_seconds(
524+
begin=self.event.created_at,
525+
end=datetime.now(),
526+
)
527+
logger.debug(
528+
"Reporting Fedora CI first initial status "
529+
f"check time: {response_time} seconds.",
530+
)
531+
self.pushgateway.fedora_ci_first_initial_status_time.observe(response_time)
519532

520533
def search_distgit_config_in_issue(self) -> Optional[tuple[str, PackageConfig]]:
521534
"""Get a tuple (dist-git repo url, package config loaded from dist-git yaml file).

packit_service/worker/monitoring.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,80 @@ def __init__(self):
191191
registry=self.registry,
192192
)
193193

194+
# Fedora CI metrics
195+
self.fedora_ci_koji_builds_queued = Counter(
196+
"fedora_ci_koji_builds_queued",
197+
"Number of Fedora CI Koji scratch builds queued",
198+
registry=self.registry,
199+
)
200+
201+
self.fedora_ci_koji_builds_started = Counter(
202+
"fedora_ci_koji_builds_started",
203+
"Number of Fedora CI Koji scratch builds started",
204+
registry=self.registry,
205+
)
206+
207+
self.fedora_ci_koji_builds_finished = Counter(
208+
"fedora_ci_koji_builds_finished",
209+
"Number of Fedora CI Koji scratch builds finished",
210+
registry=self.registry,
211+
)
212+
213+
self.fedora_ci_koji_build_finished_time = Histogram(
214+
"fedora_ci_koji_build_finished_time",
215+
"Time it takes from submitting Fedora CI Koji scratch build to finished",
216+
registry=self.registry,
217+
buckets=(
218+
1800,
219+
3600,
220+
3 * 3600,
221+
6 * 3600,
222+
12 * 3600,
223+
24 * 3600,
224+
float("inf"),
225+
),
226+
)
227+
228+
self.fedora_ci_test_runs_queued = Counter(
229+
"fedora_ci_test_runs_queued",
230+
"Number of Fedora CI test runs queued",
231+
registry=self.registry,
232+
)
233+
234+
self.fedora_ci_test_runs_started = Counter(
235+
"fedora_ci_test_runs_started",
236+
"Number of Fedora CI test runs started",
237+
registry=self.registry,
238+
)
239+
240+
self.fedora_ci_test_runs_finished = Counter(
241+
"fedora_ci_test_runs_finished",
242+
"Number of Fedora CI test runs finished",
243+
registry=self.registry,
244+
)
245+
246+
self.fedora_ci_test_run_finished_time = Histogram(
247+
"fedora_ci_test_run_finished_time",
248+
"Time it takes from submitting Fedora CI test run to finished",
249+
registry=self.registry,
250+
buckets=(
251+
1800,
252+
3600,
253+
3 * 3600,
254+
6 * 3600,
255+
12 * 3600,
256+
24 * 3600,
257+
float("inf"),
258+
),
259+
)
260+
261+
self.fedora_ci_first_initial_status_time = Histogram(
262+
"fedora_ci_first_initial_status_time",
263+
"Time it takes to set the initial status for the first Fedora CI check",
264+
registry=self.registry,
265+
buckets=(5, 15, 20, 25, 30, 40, 60, float("inf")),
266+
)
267+
194268
def push(self):
195269
if not (self.pushgateway_address and self.worker_name):
196270
logger.debug("Pushgateway address or worker name not defined.")

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ def koji_build_pr_downstream():
360360
status="some-status",
361361
group_of_targets=koji_group,
362362
runs=runs,
363+
submitted_time=None,
363364
)
364365
koji_build_model._srpm_build_for_mocking = srpm_build
365366
koji_build_model.get_project_event_object = lambda: pr_model

tests/integration/test_logdetective_koji.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,14 @@ def test_logdetective_koji_build_scratch_downstream(
9191
)
9292
flexmock(LogDetectiveRunModel).should_receive("create").times(ld_calls)
9393

94-
pushgateway = flexmock(log_detective_runs_started=flexmock())
94+
pushgateway = flexmock(
95+
log_detective_runs_started=flexmock(),
96+
fedora_ci_koji_builds_started=flexmock(),
97+
fedora_ci_koji_builds_finished=flexmock(),
98+
fedora_ci_koji_build_finished_time=flexmock(),
99+
)
95100
pushgateway.log_detective_runs_started.should_receive("inc").times(ld_calls).and_return()
101+
pushgateway.fedora_ci_koji_builds_finished.should_receive("inc").once().and_return()
96102
pushgateway.should_receive("push").and_return()
97103
flexmock(Pushgateway).new_instances(pushgateway)
98104

tests_openshift/service/conftest.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,25 @@ def mock_metrics_counters():
9090
# Specific metrics for Log Detective
9191
mock_pushgateway.log_detective_runs_finished = mock_counter
9292
mock_pushgateway.log_detective_run_finished = mock_histogram
93-
mock_pushgateway.log_detective_runs_started = mock_counter # Use mock_counter for this too
93+
mock_pushgateway.log_detective_runs_started = mock_counter
9494

9595
# General metrics used by SteveJobs
9696
mock_pushgateway.events_processed = mock_counter
9797
mock_pushgateway.events_not_handled = mock_counter
9898
mock_pushgateway.events_pre_check_failed = mock_counter
9999
mock_pushgateway.rate_limited_tasks_enqueued = mock_counter
100100

101+
# Fedora CI metrics
102+
mock_pushgateway.fedora_ci_koji_builds_queued = mock_counter
103+
mock_pushgateway.fedora_ci_koji_builds_started = mock_counter
104+
mock_pushgateway.fedora_ci_koji_builds_finished = mock_counter
105+
mock_pushgateway.fedora_ci_koji_build_finished_time = mock_histogram
106+
mock_pushgateway.fedora_ci_test_runs_queued = mock_counter
107+
mock_pushgateway.fedora_ci_test_runs_started = mock_counter
108+
mock_pushgateway.fedora_ci_test_runs_finished = mock_counter
109+
mock_pushgateway.fedora_ci_test_run_finished_time = mock_histogram
110+
mock_pushgateway.fedora_ci_first_initial_status_time = mock_histogram
111+
101112
# Inject the mock instance
102113
flexmock(Pushgateway).new_instances(mock_pushgateway)
103114

0 commit comments

Comments
 (0)