diff --git a/CHANGELOG.md b/CHANGELOG.md index 0251d8e..e01ea9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- Added workflow Grafana dashboard ## [0.0.10] - 2024-03-19 ### Added diff --git a/helm/grafana-dashboards/workflows.json b/helm/grafana-dashboards/workflows.json new file mode 100644 index 0000000..f6af4bc --- /dev/null +++ b/helm/grafana-dashboards/workflows.json @@ -0,0 +1,684 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 22, + "links": [], + "liveNow": true, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": true, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 1, + "axisSoftMin": 0, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": 86400000, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "area" + } + }, + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "green", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "(sum by(${group:csv}) (gha_workflow_run_count{conclusion=`success`, repo=~`${repo:regex}`, workflow=~`${workflow:regex}`, ref=~`${ref:regex}`, event_type=~`${event:regex}`}) / sum by(${group:csv}) (gha_workflow_run_count{conclusion=~`(success|failure)`, repo=~`${repo:regex}`, workflow=~`${workflow:regex}`, ref=~`${ref:regex}`, event_type=~`${event:regex}` }))", + "format": "time_series", + "instant": false, + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Workflow pass rate", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 5, + "panels": [], + "title": "Workflow time", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "The total run time of all runners for a workflow run", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": true, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "left", + "axisSoftMin": 0, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": 86400000, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": false, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byValue", + "options": { + "op": "gte", + "reducer": "mean", + "value": 999999 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": false, + "viz": false + } + } + ] + }, + { + "matcher": { + "id": "byValue", + "options": { + "op": "eq", + "reducer": "allIsNull", + "value": 0 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": true + } + } + ] + }, + { + "matcher": { + "id": "byValue", + "options": { + "op": "lte", + "reducer": "mean", + "value": 2 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "timezone": [ + "" + ], + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "increase((sum by(${group:csv}) (gha_workflow_runner_seconds{repo=~`${repo:regex}`, workflow=~`${workflow:regex}`, ref=~`${ref:regex}`, event_type=~`${event:regex}`}))[$__interval:]) / (increase((sum by(${group:csv}) (gha_workflow_run_count{conclusion=\"success\", repo=~`${repo:regex}`, workflow=~`${workflow:regex}`, ref=~`${ref:regex}`, event_type=~`${event:regex}`}))[$__interval:]))", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Average workflow runner time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "The total elapsed, \"wall clock\" time of all runners for a workflow run", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": true, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "left", + "axisSoftMin": 0, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": 86400000, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": false, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byValue", + "options": { + "op": "gte", + "reducer": "mean", + "value": 999999 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": false, + "viz": false + } + } + ] + }, + { + "matcher": { + "id": "byValue", + "options": { + "op": "eq", + "reducer": "allIsNull", + "value": 0 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": true + } + } + ] + }, + { + "matcher": { + "id": "byValue", + "options": { + "op": "lte", + "reducer": "mean", + "value": 2 + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "timezone": [ + "" + ], + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "increase((sum by(${group:csv}) (gha_workflow_elapsed_seconds{repo=~`${repo:regex}`, workflow=~`${workflow:regex}`, ref=~`${ref:regex}`, event_type=~`${event:regex}`}))[$__interval:]) / (increase((sum by(${group:csv}) (gha_workflow_run_count{conclusion=\"success\", repo=~`${repo:regex}`, workflow=~`${workflow:regex}`, ref=~`${ref:regex}`, event_type=~`${event:regex}`}))[$__interval:]))", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Average workflow elapsed time", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [ + "github" + ], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": [ + "repo", + "workflow" + ], + "value": [ + "repo", + "workflow" + ] + }, + "description": "Fields to group results by", + "hide": 0, + "includeAll": false, + "label": "Group by", + "multi": true, + "name": "group", + "options": [ + { + "selected": true, + "text": "repo", + "value": "repo" + }, + { + "selected": true, + "text": "workflow", + "value": "workflow" + }, + { + "selected": false, + "text": "ref", + "value": "ref" + }, + { + "selected": false, + "text": "event_type", + "value": "event_type" + } + ], + "query": "repo, workflow, ref, event_type", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "allValue": ".+", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(gha_workflow_run_count,repo)", + "description": "GitHub repo to include", + "hide": 0, + "includeAll": true, + "label": "Repo", + "multi": true, + "name": "repo", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(gha_workflow_run_count,repo)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 7, + "type": "query" + }, + { + "allValue": ".+", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(gha_workflow_run_count{repo=~\"$repo\"},ref)", + "description": "Git reference for the workflow run", + "hide": 0, + "includeAll": true, + "label": "Git ref", + "multi": true, + "name": "ref", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(gha_workflow_run_count{repo=~\"$repo\"},ref)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 7, + "type": "query" + }, + { + "allValue": ".+", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(gha_workflow_run_count{repo=~\"$repo\", ref=~\"$ref\"},workflow)", + "description": "Workflows to include", + "hide": 0, + "includeAll": true, + "label": "Workflow", + "multi": true, + "name": "workflow", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(gha_workflow_run_count{repo=~\"$repo\", ref=~\"$ref\"},workflow)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 7, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(gha_workflow_run_count{repo=~\"$repo\", ref=~\"$ref\", workflow=~\"$workflow\"},event_type)", + "description": "The GitHub event that triggered the workflow", + "hide": 0, + "includeAll": true, + "label": "Event type", + "multi": true, + "name": "event", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(gha_workflow_run_count{repo=~\"$repo\", ref=~\"$ref\", workflow=~\"$workflow\"},event_type)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 7, + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "GitHub Actions workflows", + "uid": "bdg2w9i10h9tsc", + "version": 3, + "weekStart": "" +} \ No newline at end of file diff --git a/helm/templates/dashboards.yaml b/helm/templates/dashboards.yaml new file mode 100644 index 0000000..14669dd --- /dev/null +++ b/helm/templates/dashboards.yaml @@ -0,0 +1,17 @@ +{{- if .Values.dashboards.enabled }} +{{- $files := .Files.Glob "grafana-dashboards/*.json" }} +{{- if $files }} +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: {{ include "gha-exporter.fullname" . }}-grafana-dashboards + labels: + {{- include "gha-exporter.labels" . | nindent 4 }} + {{- with .Values.dashboards.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +data: +{{ $files.AsConfig | indent 2 }} +{{- end }} +{{- end }} diff --git a/helm/values.yaml b/helm/values.yaml index b205c77..2da7ff6 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -27,6 +27,12 @@ exporter: enabled: false # initialWindow: 2h +# Grafana dashboards +dashboards: + enabled: false + additionalLabels: + grafana_dashboard: true # Default label for Grafana Helm chart dashboard sidecar + podAnnotations: {} podLabels: {}