Skip to content
This repository was archived by the owner on Mar 13, 2026. It is now read-only.

Commit 36750c3

Browse files
Send queued time after receiving events (#25)
* Send queued time after receiving events * Add datadog dependency
1 parent afbb9a6 commit 36750c3

5 files changed

Lines changed: 81 additions & 7 deletions

File tree

pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[pytest]
2-
testpaths = tests/tests.py
2+
testpaths = tests/
33
pythonpath = src

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ packages = find:
99
install_requires =
1010
Flask>=2.2,<3
1111
Flask-APScheduler==1.13.1
12+
datadog==0.49.1
1213

1314
[flake8]
1415
max-line-length = 120

src/jobs.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import metrics
2+
13
from datetime import datetime
24
from github import GithubJob
35

@@ -15,6 +17,14 @@ def __init__(self, github_job: GithubJob) -> None:
1517

1618
self.node_id = self.github_job.node_id
1719

20+
@property
21+
def seconds_in_queue(self):
22+
if self.status == "queued":
23+
return (datetime.now() - self.queued_at).total_seconds()
24+
25+
if self.status == "in_progress" or self.status == "completed":
26+
return (self.in_progress_at - self.queued_at).total_seconds()
27+
1828
def _update_attributes(self, github_job: GithubJob):
1929
self.github_job: GithubJob = github_job
2030
self.status = github_job.action
@@ -71,11 +81,17 @@ def _process_in_progress_event(self, event: dict):
7181
job = self._create_job(GithubJob(event))
7282
else:
7383
job.update(GithubJob(event))
84+
metrics.send_queued_job(
85+
seconds_in_queue=job.seconds_in_queue,
86+
job_name=job.github_job.job_name,
87+
repository=job.github_job.repository,
88+
runner=job.github_job.runner_name,
89+
run_id=job.github_job.run_id,
90+
public=job.github_job.runner_public,
91+
)
7492

7593
self.in_progress[job_id] = job
7694

77-
# TODO send final time in queue
78-
7995
def _process_completed_event(self, event: dict):
8096
job_id = self._get_event_job_id(event)
8197
self.in_progress.pop(job_id, None)

src/metrics.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from datadog import initialize, statsd
2+
3+
options = {
4+
"statsd_host": "datadog-agent.datadog.svc.cluster.local",
5+
"statsd_port": 8125,
6+
}
7+
8+
initialize(**options)
9+
10+
11+
def send_queued_job(
12+
seconds_in_queue: int,
13+
job_name: str,
14+
repository: str,
15+
runner: str,
16+
run_id: str,
17+
public: bool,
18+
):
19+
statsd.histogram(
20+
"midokura.github_runners.jobs.seconds_in_queue.histogram",
21+
seconds_in_queue,
22+
tags=[
23+
f"job:{job_name}",
24+
f"repository:{repository}",
25+
f"runner_name:{runner}",
26+
f"run_id:run-{run_id}", # "run-" added to group by run-id in DD
27+
f"public:{public}",
28+
],
29+
)

tests/test_jobs.py

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
22

3-
from unittest.mock import Mock
3+
from unittest.mock import Mock, patch
44

55
from datetime import datetime
66
from github import GithubJob
@@ -14,10 +14,15 @@ def new_job_event():
1414
return {
1515
"workflow_job": {
1616
"id": "workflow_id",
17+
"name": "workflow name",
18+
"run_id": 1234567890,
1719
"started_at": "2024-04-29T12:43:16Z",
1820
"completed_at": None,
1921
"node_id": "CR_kwDOHC6jj88AAAAFqGXrPQ",
22+
"runner_name": "test runner",
23+
"runner_group_name": "Runner Group Test",
2024
},
25+
"repository": {"full_name": "test/repo"},
2126
"action": "queued",
2227
}
2328

@@ -27,10 +32,15 @@ def in_progress_job_event():
2732
return {
2833
"workflow_job": {
2934
"id": "workflow_id",
35+
"name": "workflow name",
36+
"run_id": 1234567890,
3037
"started_at": "2024-04-29T12:43:32Z",
3138
"completed_at": None,
3239
"node_id": "CR_kwDOHC6jj88AAAAFqGXrPQ",
40+
"runner_name": "test runner",
41+
"runner_group_name": "Runner Group Test",
3342
},
43+
"repository": {"full_name": "test/repo"},
3444
"action": "in_progress",
3545
}
3646

@@ -40,10 +50,15 @@ def completed_job_event():
4050
return {
4151
"workflow_job": {
4252
"id": "workflow_id",
53+
"name": "workflow name",
54+
"run_id": 1234567890,
4355
"started_at": "2024-04-29T12:43:32Z",
4456
"completed_at": "2024-04-29T12:45:09Z",
4557
"node_id": "CR_kwDOHC6jj88AAAAFqGXrPQ",
58+
"runner_name": "test runner",
59+
"runner_group_name": "Runner Group Test",
4660
},
61+
"repository": {"full_name": "test/repo"},
4762
"action": "completed",
4863
}
4964

@@ -56,22 +71,35 @@ def test_new_job_event(new_job_event):
5671
assert handler.queued.get("workflow_id")
5772

5873

59-
def test_in_progress_job_event(in_progress_job_event):
74+
@patch("metrics.send_queued_job")
75+
def test_in_progress_job_event(
76+
send_queued_job_mock, new_job_event, in_progress_job_event
77+
):
6078
handler = JobEventsHandler()
61-
job = Mock()
79+
job = Job(GithubJob(new_job_event))
6280
handler.queued["workflow_id"] = job
6381

6482
handler.process_event(in_progress_job_event)
6583

6684
assert not handler.queued.get("workflow_id")
6785
assert handler.in_progress.get("workflow_id") == job
86+
send_queued_job_mock.assert_called_with(
87+
seconds_in_queue=16.0,
88+
job_name="workflow name",
89+
repository="test/repo",
90+
runner="test runner",
91+
run_id=1234567890,
92+
public=False,
93+
)
6894

6995

70-
def test_unprocessed_in_progress_job_event(in_progress_job_event):
96+
@patch("metrics.send_queued_job")
97+
def test_unprocessed_in_progress_job_event(send_queued_job_mock, in_progress_job_event):
7198
handler = JobEventsHandler()
7299
handler.process_event(in_progress_job_event)
73100

74101
assert handler.in_progress.get("workflow_id")
102+
send_queued_job_mock.assert_not_called()
75103

76104

77105
def test_completed_job_event(completed_job_event):

0 commit comments

Comments
 (0)