diff --git a/README.md b/README.md index 51949ee..c4a9aab 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Gauge type | node_id | Node ID (github actions) (mandatory ??) | | repo | Repository like \/\ | | run_number | Build id for the repo (incremental id => 1/2/3/4/...) | +| workflow_id | Workflow ID | +| workflow | Workflow Name | | status | Workflow status (completed/in_progress) | ### github_runner_status diff --git a/main.go b/main.go index aeca0f7..dcd2087 100644 --- a/main.go +++ b/main.go @@ -19,7 +19,7 @@ import ( "github-actions-exporter/metrics" ) -var version = "v1.4" +var version = "v1.5" // main init configuration func main() { @@ -34,6 +34,7 @@ func main() { // runWeb start http server func runWeb(ctx *cli.Context) { + go metrics.WorkflowsCache() go metrics.GetRunnersFromGithub() go metrics.GetRunnersOrganizationFromGithub() go metrics.GetJobsFromGithub() diff --git a/metrics/get_billable_from_github.go b/metrics/get_billable_from_github.go index f22a805..bc6db4a 100644 --- a/metrics/get_billable_from_github.go +++ b/metrics/get_billable_from_github.go @@ -22,19 +22,6 @@ var ( ) ) -type workflowsReturn struct { - TotalCount int `json:"total_count"` - Workflows []workflow `json:"workflows"` -} - -type workflow struct { - ID int `json:"id"` - NodeID string `json:"node_id"` - Name string `json:"name"` - Path string `json:"path"` - State string `json:"state"` -} - type UBUNTU struct { TotalMs float64 `json:"total_ms"` } @@ -59,41 +46,25 @@ func GetBillableFromGithub() { client := &http.Client{} for { for _, repo := range config.Github.Repositories { - var p workflowsReturn - req, _ := http.NewRequest("GET", "https://api.github.com/repos/"+repo+"/actions/workflows", nil) - req.Header.Set("Authorization", "token "+config.Github.Token) - resp, err := client.Do(req) - defer resp.Body.Close() - if err != nil { - log.Fatal(err) - } - if resp.StatusCode != 200 { - log.Fatalf("the status code returned by the server is different from 200: %d", resp.StatusCode) - } - err = json.NewDecoder(resp.Body).Decode(&p) - if err != nil { - log.Fatal(err) - } - - for _, w := range p.Workflows { + for k, v := range workflows[repo] { var bill Bill - req, _ := http.NewRequest("GET", "https://api.github.com/repos/"+repo+"/actions/workflows/"+strconv.Itoa(w.ID)+"/timing", nil) + req, _ := http.NewRequest("GET", "https://api.github.com/repos/"+repo+"/actions/workflows/"+strconv.Itoa(k)+"/timing", nil) req.Header.Set("Authorization", "token "+config.Github.Token) - resp2, err := client.Do(req) - defer resp2.Body.Close() + resp, err := client.Do(req) + defer resp.Body.Close() if err != nil { log.Fatal(err) } if resp.StatusCode != 200 { log.Fatalf("the status code returned by the server is different from 200: %d", resp.StatusCode) } - err = json.NewDecoder(resp2.Body).Decode(&bill) + err = json.NewDecoder(resp.Body).Decode(&bill) if err != nil { log.Fatal(err) } - WorkflowBillGauge.WithLabelValues(repo, strconv.Itoa(w.ID), w.NodeID, w.Name, w.State, "MACOS").Set(bill.Billable.MACOS.TotalMs / 1000) - WorkflowBillGauge.WithLabelValues(repo, strconv.Itoa(w.ID), w.NodeID, w.Name, w.State, "WINDOWS").Set(bill.Billable.WINDOWS.TotalMs / 1000) - WorkflowBillGauge.WithLabelValues(repo, strconv.Itoa(w.ID), w.NodeID, w.Name, w.State, "UBUNTU").Set(bill.Billable.UBUNTU.TotalMs / 1000) + WorkflowBillGauge.WithLabelValues(repo, strconv.Itoa(v.ID), v.NodeID, v.Name, v.State, "MACOS").Set(bill.Billable.MACOS.TotalMs / 1000) + WorkflowBillGauge.WithLabelValues(repo, strconv.Itoa(v.ID), v.NodeID, v.Name, v.State, "WINDOWS").Set(bill.Billable.WINDOWS.TotalMs / 1000) + WorkflowBillGauge.WithLabelValues(repo, strconv.Itoa(v.ID), v.NodeID, v.Name, v.State, "UBUNTU").Set(bill.Billable.UBUNTU.TotalMs / 1000) } } diff --git a/metrics/get_jobs_from_github.go b/metrics/get_jobs_from_github.go index 5603038..586794d 100644 --- a/metrics/get_jobs_from_github.go +++ b/metrics/get_jobs_from_github.go @@ -18,7 +18,7 @@ var ( Name: "github_job", Help: "job status", }, - []string{"repo", "id", "node_id", "head_branch", "head_sha", "run_number", "event", "status"}, + []string{"repo", "id", "node_id", "head_branch", "head_sha", "run_number", "workflow_id", "workflow", "event", "status"}, ) ) @@ -37,6 +37,7 @@ type job struct { Status string `json:"status"` Conclusion string `json:"conclusion"` UpdatedAt string `json:"updated_at"` + WorkflowID int `json:"workflow_id"` } func GetJobsFromGithub() { @@ -69,7 +70,7 @@ func GetJobsFromGithub() { } else if r.Status == "queued" { s = 4 } - JobsGauge.WithLabelValues(repo, strconv.Itoa(r.ID), r.NodeID, r.HeadBranch, r.HeadSha, strconv.Itoa(r.RunNumber), r.Event, r.Status).Set(s) + JobsGauge.WithLabelValues(repo, strconv.Itoa(r.ID), r.NodeID, r.HeadBranch, r.HeadSha, strconv.Itoa(r.RunNumber), strconv.Itoa(r.WorkflowID), workflows[repo][r.WorkflowID].Name, r.Event, r.Status).Set(s) } } diff --git a/metrics/worflows_cache.go b/metrics/worflows_cache.go new file mode 100644 index 0000000..67e5d85 --- /dev/null +++ b/metrics/worflows_cache.go @@ -0,0 +1,56 @@ +package metrics + +import ( + "encoding/json" + "github-actions-exporter/config" + "log" + "net/http" + "time" +) + +var workflows = map[string]map[int]workflow{} + +type workflowsReturn struct { + TotalCount int `json:"total_count"` + Workflows []workflow `json:"workflows"` +} + +type workflow struct { + ID int `json:"id"` + NodeID string `json:"node_id"` + Name string `json:"name"` + Path string `json:"path"` + State string `json:"state"` +} + +func WorkflowsCache() { + client := &http.Client{} + + for { + for _, repo := range config.Github.Repositories { + var p workflowsReturn + req, _ := http.NewRequest("GET", "https://api.github.com/repos/"+repo+"/actions/workflows", nil) + req.Header.Set("Authorization", "token "+config.Github.Token) + resp, err := client.Do(req) + defer resp.Body.Close() + if err != nil { + log.Fatal(err) + } + if resp.StatusCode != 200 { + log.Fatalf("the status code returned by the server is different from 200: %d", resp.StatusCode) + } + err = json.NewDecoder(resp.Body).Decode(&p) + if err != nil { + log.Fatal(err) + } + + s := make(map[int]workflow) + for _, w := range p.Workflows { + s[w.ID] = w + } + + workflows[repo] = s + } + time.Sleep(time.Duration(60) * time.Second) + } +}