Skip to content

Commit cedf9ab

Browse files
committed
refactoring
- rename workflowUrl to workflowDefinitonUrl - add workflow list page as workflowUrl - do not produce run metrics for disabled workflows Signed-off-by: Markus Blaschke <mail@markus-blaschke.de>
1 parent 98bc7bd commit cedf9ab

2 files changed

Lines changed: 127 additions & 44 deletions

File tree

‎metrics_github_workflows.go‎

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package main
22

33
import (
44
"context"
5-
"errors"
65
"fmt"
76
"log/slog"
87
"strings"
@@ -84,6 +83,7 @@ func (m *MetricsCollectorGithubWorkflows) Setup(collector *collector.Collector)
8483
"workflowID",
8584
"workflow",
8685
"workflowUrl",
86+
"workflowDefinitionUrl",
8787
"state",
8888
"path",
8989
},
@@ -107,6 +107,7 @@ func (m *MetricsCollectorGithubWorkflows) Setup(collector *collector.Collector)
107107
"workflowRunNumber",
108108
"workflow",
109109
"workflowUrl",
110+
"workflowDefinitionUrl",
110111
"workflowRun",
111112
"workflowRunUrl",
112113
"event",
@@ -147,6 +148,7 @@ func (m *MetricsCollectorGithubWorkflows) Setup(collector *collector.Collector)
147148
"workflowRunNumber",
148149
"workflow",
149150
"workflowUrl",
151+
"workflowDefinitionUrl",
150152
"workflowRun",
151153
"workflowRunUrl",
152154
"event",
@@ -201,6 +203,7 @@ func (m *MetricsCollectorGithubWorkflows) Setup(collector *collector.Collector)
201203
"workflowRunNumber",
202204
"workflow",
203205
"workflowUrl",
206+
"workflowDefinitionUrl",
204207
"workflowRun",
205208
"workflowRunUrl",
206209
"branch",
@@ -223,6 +226,7 @@ func (m *MetricsCollectorGithubWorkflows) Setup(collector *collector.Collector)
223226
"workflowRunNumber",
224227
"workflow",
225228
"workflowUrl",
229+
"workflowDefinitionUrl",
226230
"workflowRun",
227231
"workflowRunUrl",
228232
"branch",
@@ -265,12 +269,7 @@ func (m *MetricsCollectorGithubWorkflows) getRepoList(ctx context.Context, org s
265269
var repoCustomProperties []*github.CustomPropertyValue
266270
for {
267271
repoCustomProperties, _, err = githubClient.Repositories.GetAllCustomPropertyValues(ctx, org, repository.GetName())
268-
var ghRateLimitError *github.RateLimitError
269-
if ok := errors.As(err, &ghRateLimitError); ok {
270-
m.Logger().Debug("request GetAllCustomPropertyValues rate limited", slog.Time("waitingUntil", ghRateLimitError.Rate.Reset.Time))
271-
time.Sleep(time.Until(ghRateLimitError.Rate.Reset.Time))
272-
continue
273-
} else if err != nil {
272+
if err != nil {
274273
panic(err)
275274
}
276275
break
@@ -286,22 +285,20 @@ func (m *MetricsCollectorGithubWorkflows) getRepoList(ctx context.Context, org s
286285
return repositories, nil
287286
}
288287

289-
func (m *MetricsCollectorGithubWorkflows) getRepoWorkflows(ctx context.Context, org, repo string) (map[int64]*github.Workflow, error) {
290-
workflows := map[int64]*github.Workflow{}
288+
func (m *MetricsCollectorGithubWorkflows) getRepoWorkflows(ctx context.Context, org string, repo *github.Repository) (*GithubWorkflowList, error) {
289+
workflows := NewGithubWorkflowList(org, repo)
291290

292291
opts := github.ListOptions{PerPage: 100, Page: 1}
293292

294293
for {
295-
m.Logger().Debug(`fetching workflows list for repository`, slog.String("repository", repo), slog.Int("page", opts.Page))
294+
m.Logger().Debug(`fetching workflows list for repository`, slog.String("repository", repo.GetName()), slog.Int("page", opts.Page))
296295

297-
result, response, err := githubClient.Actions.ListWorkflows(ctx, org, repo, &opts)
296+
result, response, err := githubClient.Actions.ListWorkflows(ctx, org, repo.GetName(), &opts)
298297
if err != nil {
299298
return workflows, err
300299
}
301300

302-
for _, row := range result.Workflows {
303-
workflows[row.GetID()] = row
304-
}
301+
workflows.Add(result.Workflows...)
305302

306303
// calc next page
307304
if response.NextPage == 0 {
@@ -394,29 +391,28 @@ func (m *MetricsCollectorGithubWorkflows) Collect(callback chan<- func()) {
394391
repositoryMetric.AddInfo(labels)
395392

396393
// get workflows
397-
workflows, err := m.getRepoWorkflows(ctx, org, repo.GetName())
394+
workflows, err := m.getRepoWorkflows(ctx, org, repo)
398395
if err != nil {
399396
panic(err)
400397
}
401398

402399
// workflow info metrics
403-
for _, workflow := range workflows {
400+
for _, workflow := range workflows.List() {
404401
labels := prometheus.Labels{
405-
"org": org,
406-
"repo": repo.GetName(),
407-
"workflowID": fmt.Sprintf("%v", workflow.GetID()),
408-
"workflow": workflow.GetName(),
409-
"state": workflow.GetState(),
410-
"path": workflow.GetPath(),
411-
"workflowUrl": workflow.GetHTMLURL(),
402+
"org": org,
403+
"repo": repo.GetName(),
404+
"workflowID": fmt.Sprintf("%v", workflow.GetID()),
405+
"state": workflow.GetState(),
406+
"path": workflow.GetPath(),
412407
}
408+
workflow.AddDefaultLabels(labels)
413409
for labelName, labelValue := range propLabels {
414410
labels[labelName] = labelValue
415411
}
416412
workflowMetric.AddInfo(labels)
417413
}
418414

419-
if len(workflows) >= 1 {
415+
if workflows.Count() >= 1 {
420416
workflowRuns, err := m.getRepoWorkflowRuns(ctx, repo)
421417
if err != nil {
422418
panic(err)
@@ -432,7 +428,7 @@ func (m *MetricsCollectorGithubWorkflows) Collect(callback chan<- func()) {
432428
}
433429
}
434430

435-
func (m *MetricsCollectorGithubWorkflows) collectRunningRuns(org string, repo *github.Repository, workflows map[int64]*github.Workflow, workflowRun []*github.WorkflowRun, callback chan<- func()) {
431+
func (m *MetricsCollectorGithubWorkflows) collectRunningRuns(org string, repo *github.Repository, workflows *GithubWorkflowList, workflowRun []*github.WorkflowRun, callback chan<- func()) {
436432
runMetric := m.Collector.GetMetricList("workflowRunRunning")
437433
runStartTimeMetric := m.Collector.GetMetricList("workflowRunRunningStartTime")
438434

@@ -466,10 +462,7 @@ func (m *MetricsCollectorGithubWorkflows) collectRunningRuns(org string, repo *g
466462
}
467463

468464
// add workflow labels
469-
if workflow, ok := workflows[workflowRun.GetWorkflowID()]; ok {
470-
infoLabels["workflow"] = workflow.GetName()
471-
infoLabels["workflowUrl"] = workflow.GetHTMLURL()
472-
}
465+
workflows.GetById(workflowRun.GetWorkflowID()).AddDefaultLabels(infoLabels)
473466

474467
statLabels := prometheus.Labels{
475468
"org": org,
@@ -483,7 +476,7 @@ func (m *MetricsCollectorGithubWorkflows) collectRunningRuns(org string, repo *g
483476
}
484477
}
485478

486-
func (m *MetricsCollectorGithubWorkflows) collectLatestRun(org string, repo *github.Repository, workflows map[int64]*github.Workflow, workflowRun []*github.WorkflowRun, callback chan<- func()) {
479+
func (m *MetricsCollectorGithubWorkflows) collectLatestRun(org string, repo *github.Repository, workflows *GithubWorkflowList, workflowRun []*github.WorkflowRun, callback chan<- func()) {
487480
runMetric := m.Collector.GetMetricList("workflowLatestRun")
488481
runTimestampMetric := m.Collector.GetMetricList("workflowLatestRunStartTime")
489482
runDurationMetric := m.Collector.GetMetricList("workflowLatestRunDuration")
@@ -493,6 +486,11 @@ func (m *MetricsCollectorGithubWorkflows) collectLatestRun(org string, repo *git
493486
workflowRun := row
494487
workflowId := workflowRun.GetWorkflowID()
495488

489+
workflow := workflows.GetById(workflowRun.GetWorkflowID())
490+
if !workflow.IsActive() {
491+
continue
492+
}
493+
496494
// skip forks
497495
if workflowRun.GetHeadRepository().Fork != nil && *workflowRun.GetHeadRepository().Fork {
498496
continue
@@ -533,10 +531,7 @@ func (m *MetricsCollectorGithubWorkflows) collectLatestRun(org string, repo *git
533531
}
534532

535533
// add workflow labels
536-
if workflow, ok := workflows[workflowRun.GetWorkflowID()]; ok {
537-
infoLabels["workflow"] = workflow.GetName()
538-
infoLabels["workflowUrl"] = workflow.GetHTMLURL()
539-
}
534+
workflows.GetById(workflowRun.GetWorkflowID()).AddDefaultLabels(infoLabels)
540535

541536
statLabels := prometheus.Labels{
542537
"org": org,
@@ -551,7 +546,7 @@ func (m *MetricsCollectorGithubWorkflows) collectLatestRun(org string, repo *git
551546
}
552547
}
553548

554-
func (m *MetricsCollectorGithubWorkflows) collectConsecutiveFailures(org string, repo *github.Repository, workflows map[int64]*github.Workflow, workflowRun []*github.WorkflowRun, callback chan<- func()) {
549+
func (m *MetricsCollectorGithubWorkflows) collectConsecutiveFailures(org string, repo *github.Repository, workflows *GithubWorkflowList, workflowRun []*github.WorkflowRun, callback chan<- func()) {
555550
consecutiveFailuresMetric := m.Collector.GetMetricList("workflowConsecutiveFailures")
556551

557552
consecutiveFailMap := map[int64]*struct {
@@ -564,6 +559,11 @@ func (m *MetricsCollectorGithubWorkflows) collectConsecutiveFailures(org string,
564559
workflowRun := row
565560
workflowId := workflowRun.GetWorkflowID()
566561

562+
workflow := workflows.GetById(workflowRun.GetWorkflowID())
563+
if !workflow.IsActive() {
564+
continue
565+
}
566+
567567
// ignore running/not finished workflow runs
568568
switch workflowRun.GetStatus() {
569569
case "in_progress":
@@ -592,10 +592,7 @@ func (m *MetricsCollectorGithubWorkflows) collectConsecutiveFailures(org string,
592592
}
593593

594594
// add workflow labels
595-
if workflow, ok := workflows[workflowRun.GetWorkflowID()]; ok {
596-
infoLabels["workflow"] = workflow.GetName()
597-
infoLabels["workflowUrl"] = workflow.GetHTMLURL()
598-
}
595+
workflow.AddDefaultLabels(infoLabels)
599596

600597
consecutiveFailMap[workflowId] = &struct {
601598
count int64
@@ -628,7 +625,7 @@ func (m *MetricsCollectorGithubWorkflows) collectConsecutiveFailures(org string,
628625
}
629626
}
630627

631-
func (m *MetricsCollectorGithubWorkflows) collectConsecutiveRuns(org string, repo *github.Repository, workflows map[int64]*github.Workflow, workflowRun []*github.WorkflowRun, callback chan<- func()) {
628+
func (m *MetricsCollectorGithubWorkflows) collectConsecutiveRuns(org string, repo *github.Repository, workflows *GithubWorkflowList, workflowRun []*github.WorkflowRun, callback chan<- func()) {
632629
consecutiveRunsMetric := m.Collector.GetMetricList("workflowConsecutiveRuns")
633630

634631
consecutiveRunMap := map[int64]*struct {
@@ -642,6 +639,11 @@ func (m *MetricsCollectorGithubWorkflows) collectConsecutiveRuns(org string, rep
642639
workflowRun := row
643640
workflowId := workflowRun.GetWorkflowID()
644641

642+
workflow := workflows.GetById(workflowRun.GetWorkflowID())
643+
if !workflow.IsActive() {
644+
continue
645+
}
646+
645647
if _, exists := consecutiveRunMap[workflowId]; !exists {
646648
infoLabels := prometheus.Labels{
647649
"org": org,
@@ -657,10 +659,7 @@ func (m *MetricsCollectorGithubWorkflows) collectConsecutiveRuns(org string, rep
657659
}
658660

659661
// add workflow labels
660-
if workflow, ok := workflows[workflowRun.GetWorkflowID()]; ok {
661-
infoLabels["workflow"] = workflow.GetName()
662-
infoLabels["workflowUrl"] = workflow.GetHTMLURL()
663-
}
662+
workflow.AddDefaultLabels(infoLabels)
664663

665664
consecutiveRunMap[workflowId] = &struct {
666665
count int64

‎workflow.go‎

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/google/go-github/v92/github"
8+
"github.com/prometheus/client_golang/prometheus"
9+
)
10+
11+
type (
12+
GithubWorkflowList struct {
13+
org string
14+
repo *github.Repository
15+
list map[int64]*GitHubWorkflow
16+
}
17+
18+
GitHubWorkflow struct {
19+
*github.Workflow
20+
ref *GithubWorkflowList
21+
}
22+
)
23+
24+
func NewGithubWorkflowList(org string, repo *github.Repository) *GithubWorkflowList {
25+
return &GithubWorkflowList{
26+
org: org,
27+
repo: repo,
28+
list: map[int64]*GitHubWorkflow{},
29+
}
30+
}
31+
32+
func (list *GithubWorkflowList) Add(workflow ...*github.Workflow) {
33+
for _, item := range workflow {
34+
list.list[*item.ID] = new(GitHubWorkflow{Workflow: item, ref: list})
35+
}
36+
}
37+
38+
func (list *GithubWorkflowList) GetById(id int64) *GitHubWorkflow {
39+
if workflow, ok := list.list[id]; ok {
40+
return workflow
41+
}
42+
return nil
43+
}
44+
45+
func (list *GithubWorkflowList) Count() int {
46+
return len(list.list)
47+
}
48+
49+
func (list *GithubWorkflowList) List() map[int64]*GitHubWorkflow {
50+
return list.list
51+
}
52+
53+
func (workflow *GitHubWorkflow) IsActive() bool {
54+
if workflow != nil {
55+
return strings.EqualFold(workflow.GetState(), "active")
56+
}
57+
return false
58+
}
59+
60+
func (workflow *GitHubWorkflow) AddDefaultLabels(labels prometheus.Labels) {
61+
// reset
62+
labels["workflow"] = ""
63+
labels["workflowUrl"] = ""
64+
labels["workflowDefinitionUrl"] = ""
65+
66+
if workflow != nil {
67+
// for whatever reason we only get the definition url, not the real "workflow" overview page
68+
69+
orgName := workflow.ref.repo.Organization.GetName()
70+
repoName := workflow.ref.repo.GetName()
71+
defaultBranch := workflow.ref.repo.GetDefaultBranch()
72+
73+
workflowOverviewUrl := strings.Replace(
74+
workflow.GetHTMLURL(),
75+
fmt.Sprintf("%s/%s/blob/%s/.github/workflows/", orgName, repoName, defaultBranch),
76+
fmt.Sprintf("%s/%s/actions/workflows/", orgName, repoName),
77+
1,
78+
)
79+
80+
labels["workflow"] = workflow.GetName()
81+
labels["workflowUrl"] = workflowOverviewUrl
82+
labels["workflowDefinitionUrl"] = workflow.GetHTMLURL()
83+
}
84+
}

0 commit comments

Comments
 (0)