Skip to content

Commit

Permalink
Add branch and event label to metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
tcarmet committed Apr 3, 2024
1 parent 1161089 commit 9fa8e49
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 4 deletions.
2 changes: 1 addition & 1 deletion gh_actions_exporter/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Settings(BaseSettings):
"ubuntu-20.04": 0.008,
}
default_cost: Optional[float] = 0

branches: List[str] = ["main", "master"]
check_runs_enabled: bool = False
github_app_id: Optional[int]
github_app_installation_id: Optional[int]
Expand Down
39 changes: 37 additions & 2 deletions gh_actions_exporter/metrics.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import fnmatch
from typing import Dict, List

from prometheus_client import Counter, Histogram

from gh_actions_exporter.config import Relabel, RelabelType, Settings
from gh_actions_exporter.cost import Cost
from gh_actions_exporter.types import WebHook, WorkflowJob
from gh_actions_exporter.types import WebHook, WorkflowJob, WorkflowRun


class Metrics(object):
Expand All @@ -17,7 +18,10 @@ def __init__(self, settings: Settings):
"workflow_name",
"repository_visibility",
]
self.workflow_labelnames = self.common_labelnames.copy()
self.workflow_labelnames = self.common_labelnames.copy() + [
"branch",
"event",
]
self.job_labelnames = self.common_labelnames.copy() + [
"job_name",
"runner_type",
Expand Down Expand Up @@ -107,11 +111,42 @@ def __init__(self, settings: Settings):
labelnames=self.job_labelnames,
)

def retrieve_branch(self, workflow_run: WorkflowRun) -> str:
"""
Add the branch label to the metrics exposed by the exporter while
also taking into account the cardinality limitations of prometheus:
- For workflows triggered on pull_request event
retrieve the base branch (target branch).
- For other events, retrieve the head branch.
Then check if the branch matches any of the patterns defined in
self.settings.branches like: development/*, main, feature/*, etc.
Return the branch name if it matches any of the patterns,
otherwise return "dev".
"""
ref: str
if workflow_run.event == "pull_request":
assert workflow_run.pull_requests
ref = workflow_run.pull_requests[0].base.ref
else:
ref = workflow_run.head_branch
for branch in self.settings.branches:
if fnmatch.fnmatch(ref, branch):
return ref
return "dev"

def workflow_labels(self, webhook: WebHook) -> dict:
assert webhook.workflow_run
branch = self.retrieve_branch(webhook.workflow_run)
return dict(
workflow_name=webhook.workflow_run.name,
repository=webhook.repository.full_name,
repository_visibility=webhook.repository.visibility,
branch=branch,
event=webhook.workflow_run.event,
)

def runner_type(self, webhook: WebHook) -> str:
Expand Down
10 changes: 10 additions & 0 deletions gh_actions_exporter/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ class WorkflowJob(BaseModel):
steps: Optional[list[Steps]] = None


class BasePullRequest(BaseModel):
ref: str


class PullRequest(BaseModel):
number: int
base: BasePullRequest


class WorkflowRun(BaseModel):
id: int
name: str
Expand All @@ -44,6 +53,7 @@ class WorkflowRun(BaseModel):
workflow_id: int
run_number: int
head_branch: str
pull_requests: Optional[list[PullRequest]] = None
created_at: datetime
updated_at: Optional[datetime] = None
run_attempt: int
Expand Down
25 changes: 25 additions & 0 deletions tests/api/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,31 @@ def workflow_run():
"created_at": "2021-11-16T17:52:47Z",
"run_started_at": "2021-11-16T17:52:47Z",
"updated_at": "2021-11-16T17:53:32Z",
"pull_requests": [
{
"url": "https://api.github.com/repos/org/repo/pulls/555",
"id": 1805247,
"number": 555,
"head": {
"ref": "feature/my-feature",
"sha": "fc98b69edf5ac3f4789c210e758b1ee4b4396b9e",
"repo": {
"id": 395065315,
"url": "https://api.github.com/repos/org/repo",
"name": "repo",
},
},
"base": {
"ref": "master",
"sha": "966917b16d284edde596b0705a49f8c65ecf1c84",
"repo": {
"id": 395065125,
"url": "https://api.github.com/repos/org/repo",
"name": "repo",
},
},
}
],
},
"repository": {
"name": "repo",
Expand Down
4 changes: 3 additions & 1 deletion tests/api/metrics/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ def job_relabel_config():

@lru_cache()
def default_settings():
return Settings()
return Settings(
branches=["main", "master", "development/*"],
)


@lru_cache()
Expand Down
38 changes: 38 additions & 0 deletions tests/api/metrics/test_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,41 @@ def test_rebuild(client, workflow_run, headers):
for line in metrics.text.split("\n"):
if "workflow_rebuild_count_total{" in line:
assert "1.0" in line


def test_branch_label(client, workflow_run, headers):
# Ensure a feature branch is not indexed
upload = client.post("/webhook", json=workflow_run, headers=headers)
assert upload.status_code == 202

metrics = client.get("/metrics")
assert metrics.status_code == 200
assert 'branch="feature"' not in metrics.text
assert 'branch="dev"' in metrics.text

# Index a push event with a branch label
workflow_run["workflow_run"]["head_branch"] = "main"
upload = client.post("/webhook", json=workflow_run, headers=headers)
assert upload.status_code == 202

metrics = client.get("/metrics")
assert metrics.status_code == 200
assert 'branch="main"' in metrics.text

# Index a branch with a fnmatch pattern configured
workflow_run["workflow_run"]["head_branch"] = "development/1.2"
upload = client.post("/webhook", json=workflow_run, headers=headers)
assert upload.status_code == 202

metrics = client.get("/metrics")
assert metrics.status_code == 200
assert 'branch="development/1.2"' in metrics.text

# Index the base branch of a pull request
workflow_run["workflow_run"]["event"] = "pull_request"
upload = client.post("/webhook", json=workflow_run, headers=headers)
assert upload.status_code == 202

metrics = client.get("/metrics")
assert metrics.status_code == 200
assert 'branch="master"' in metrics.text

0 comments on commit 9fa8e49

Please sign in to comment.