diff --git a/CHANGELOG.md b/CHANGELOG.md index 645e5d929f4..64d81e54a07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to Sourcegraph are documented in this file. ### Added - The search sidebar shows a revisions section if all search results are from a single repository. This makes it easier to search in and switch between different revisions. [#23835](https://github.com/sourcegraph/sourcegraph/pull/23835) +- The various alerts overview panels in Grafana can now be clicked to go directly to the relevant panels and dashboards. [#24920](https://github.com/sourcegraph/sourcegraph/pull/24920) - Added a `Documentation` tab to the Site Admin Maintenance panel that links to the official Sourcegraph documentation. [#24917](https://github.com/sourcegraph/sourcegraph/pull/24917) - Code Insights that run over all repositories now generate a moving daily snapshot between time points. [#24804](https://github.com/sourcegraph/sourcegraph/pull/24804) diff --git a/docker-images/grafana/home.json b/docker-images/grafana/home.json index b21c2c4721e..44dd7544520 100644 --- a/docker-images/grafana/home.json +++ b/docker-images/grafana/home.json @@ -19,8 +19,11 @@ "links": [], "panels": [ { - "content": "
\n \n
Overview: High-level insight into the health of Sourcegraph.\n
\n
To learn more, refer to the Sourcegraph metrics and dashboards documentation and alerting documentation.\n
\n", "datasource": null, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, "gridPos": { "h": 4, "w": 24, @@ -28,51 +31,89 @@ "y": 0 }, "id": 9, - "mode": "html", + "options": { + "content": "
\n \n
Overview: High-level insight into the health of Sourcegraph.\n
\n
To learn more, refer to the Sourcegraph metrics and dashboards documentation and alerting documentation.\n
\n", + "mode": "html" + }, + "pluginVersion": "7.5.7", "timeFrom": null, "timeShift": null, - "title": "", "type": "text" }, { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, "datasource": null, - "fill": 1, - "fillGradient": 0, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "open alerts", + "axisPlacement": "hidden", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false + }, + "lineInterpolation": "stepBefore", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true + }, + "decimals": 0, + "links": [ + { + "targetBlank": false, + "title": "Service dashboards", + "url": "/-/debug/grafana/d/${__field.labels.service_name}/${__field.labels.service_name}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, "gridPos": { "h": 5, "w": 24, "x": 0, - "y": 6 + "y": 4 }, - "hiddenSeries": false, - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", + "id": 4, "options": { - "dataLinks": [] + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltipOptions": { + "mode": "single" + } }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, + "pluginVersion": "7.5.7", "targets": [ { "expr": "sum by (service_name)(max by (level,service_name,name,description)(alert_count{name!=\"\",level=\"critical\"}))", @@ -81,87 +122,85 @@ "refId": "A" } ], - "thresholds": [], "timeFrom": null, - "timeRegions": [], "timeShift": null, "title": "Critical alerts by service", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": "open alerts", - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } + "type": "timeseries" }, { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, "datasource": null, - "fill": 1, - "fillGradient": 0, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "open alerts", + "axisPlacement": "hidden", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false + }, + "lineInterpolation": "stepBefore", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true + }, + "decimals": 0, + "links": [ + { + "targetBlank": false, + "title": "Service dashboards", + "url": "/-/debug/grafana/d/${__field.labels.service_name}/${__field.labels.service_name}" + } + ], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, "gridPos": { "h": 5, "w": 24, "x": 0, - "y": 11 + "y": 9 }, - "hiddenSeries": false, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", + "id": 5, "options": { - "dataLinks": [] + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltipOptions": { + "mode": "single" + } }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, + "pluginVersion": "7.5.7", "targets": [ { "expr": "sum by (service_name)(max by (level,service_name,name,description)(alert_count{name!=\"\",level=\"warning\"}))", @@ -170,47 +209,10 @@ "refId": "A" } ], - "thresholds": [], "timeFrom": null, - "timeRegions": [], "timeShift": null, "title": "Warning alerts by service", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": "open alerts", - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } + "type": "timeseries" }, { "cacheTimeout": null, @@ -218,6 +220,10 @@ "colorValue": false, "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"], "datasource": null, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, "format": "none", "gauge": { "maxValue": 100, @@ -227,10 +233,326 @@ "thresholdMarkers": true }, "gridPos": { - "h": 3, + "h": 4, "w": 5, "x": 0, - "y": 16 + "y": 14 + }, + "id": 15, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false, + "ymax": null, + "ymin": null + }, + "tableColumn": "", + "targets": [ + { + "expr": "count(sum(alert_count{name!=\"\"}) by (service_name))", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "", + "timeFrom": null, + "timeShift": null, + "title": "Services being monitored", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "cacheTimeout": null, + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(51, 145, 38)", + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "filterable": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "displayName", + "value": "firing?" + }, + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "custom.align", + "value": "center" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 1 + } + ] + } + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.width", + "value": 80 + }, + { + "id": "mappings", + "value": [ + { + "from": "", + "id": 1, + "text": "false", + "to": "", + "type": 1, + "value": "0" + }, + { + "from": "", + "id": 2, + "text": "true", + "to": "", + "type": 1, + "value": "1" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "service_name" + }, + "properties": [ + { + "id": "custom.width", + "value": 150 + }, + { + "id": "displayName", + "value": "service" + }, + { + "id": "custom.filterable", + "value": true + }, + { + "id": "links", + "value": [ + { + "title": "Service dashboards", + "url": "/-/debug/grafana/d/${__data.fields.service_name}/${__data.fields.service_name}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "level" + }, + "properties": [ + { + "id": "custom.width", + "value": 80 + }, + { + "id": "custom.filterable", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "description" + }, + "properties": [ + { + "id": "custom.filterable", + "value": true + }, + { + "id": "links", + "value": [ + { + "title": "Graph panel", + "url": "/-/debug/grafana/d/${__data.fields.service_name}/${__data.fields.service_name}?viewPanel=${__data.fields.grafana_panel_id}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "grafana_panel_id" + }, + "properties": [ + { + "id": "custom.width", + "value": 0.1 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 19, + "x": 5, + "y": 14 + }, + "id": 11, + "links": [], + "options": { + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "firing?" + } + ] + }, + "pluginVersion": "7.5.7", + "targets": [ + { + "exemplar": true, + "expr": "label_replace(sum by (level,service_name,description,grafana_panel_id)(max by (level,service_name,name,description,grafana_panel_id)(alert_count{name!=\"\"})), \"description\", \"$1\", \"description\", \".*: (.*)\")", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Alerts defined", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Value": false, + "_01_level": false, + "description": false, + "level": false + }, + "indexByName": { + "Time": 0, + "Value": 4, + "description": 3, + "level": 1, + "service_name": 2 + } + } + } + ], + "type": "table" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"], + "datasource": null, + "fieldConfig": { + "defaults": {}, + "overrides": [] + }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 0, + "y": 18 }, "id": 13, "interval": null, @@ -293,191 +615,9 @@ } ], "valueName": "avg" - }, - { - "cacheTimeout": null, - "columns": [], - "datasource": null, - "description": "", - "fontSize": "100%", - "gridPos": { - "h": 6, - "w": 19, - "x": 5, - "y": 16 - }, - "id": 11, - "links": [], - "pageSize": null, - "pluginVersion": "6.4.4", - "showHeader": true, - "sort": { - "col": 4, - "desc": true - }, - "styles": [ - { - "alias": "", - "align": "auto", - "colorMode": null, - "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "mappingType": 1, - "pattern": "Time", - "thresholds": [], - "type": "hidden", - "unit": "short" - }, - { - "alias": "firing?", - "align": "auto", - "colorMode": "row", - "colors": ["rgba(50, 172, 45, 0.97)", "rgba(237, 129, 40, 0.89)", "rgba(245, 54, 54, 0.9)"], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "mappingType": 1, - "pattern": "Value", - "thresholds": ["0.99999", "1"], - "type": "string", - "unit": "short", - "valueMaps": [ - { - "text": "false", - "value": "0" - }, - { - "text": "true", - "value": "1" - } - ] - }, - { - "alias": "", - "align": "auto", - "colorMode": null, - "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "mappingType": 1, - "pattern": "level", - "thresholds": [], - "type": "hidden", - "unit": "short" - }, - { - "alias": "level", - "align": "auto", - "colorMode": null, - "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "mappingType": 1, - "pattern": "_01_level", - "thresholds": [], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "expr": "label_replace(sum by (level,description)(max by (level,service_name,name,description)(alert_count{name!=\"\"})), \"_01_level\", \"$1\", \"level\", \"(.*)\")", - "format": "table", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Alerts defined", - "transform": "table", - "type": "table" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": ["#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a"], - "datasource": null, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 3, - "w": 5, - "x": 0, - "y": 19 - }, - "id": 15, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false, - "ymax": null, - "ymin": null - }, - "tableColumn": "", - "targets": [ - { - "expr": "count(sum(alert_count{name!=\"\"}) by (service_name))", - "instant": true, - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Services being monitored", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" } ], - "schemaVersion": 22, + "schemaVersion": 27, "style": "dark", "tags": [], "templating": { @@ -492,8 +632,6 @@ }, "timezone": "utc", "title": "Overview", - "variables": { - "list": [] - }, + "uid": null, "version": 1 } diff --git a/go.mod b/go.mod index ab2966a4dc7..79dcdf34ad7 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/gorilla/securecookie v1.1.1 github.com/gorilla/sessions v1.2.1 github.com/goware/urlx v0.3.1 - github.com/grafana-tools/sdk v0.0.0-20210709154219-f35c5af8140d + github.com/grafana-tools/sdk v0.0.0-20210831082851-2de27e0f2577 github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29 github.com/graphql-go/graphql v0.7.9 github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 @@ -338,6 +338,8 @@ replace ( replace ( // Pending: https://github.com/ghodss/yaml/pull/65 github.com/ghodss/yaml => github.com/sourcegraph/yaml v1.0.1-0.20200714132230-56936252f152 + // graph-fieldconfig branch - https://github.com/grafana-tools/sdk/pull/170 + github.com/grafana-tools/sdk => github.com/sourcegraph/grafana-sdk v0.0.0-20210914025534-b4255965ba53 github.com/shurcooL/httpgzip => github.com/sourcegraph/httpgzip v0.0.0-20210213125624-48ebf036a6a1 ) diff --git a/go.sum b/go.sum index 8341a0db9b9..f32d0027636 100644 --- a/go.sum +++ b/go.sum @@ -797,8 +797,6 @@ github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.m github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/goware/urlx v0.3.1 h1:BbvKl8oiXtJAzOzMqAQ0GfIhf96fKeNEZfm9ocNSUBI= github.com/goware/urlx v0.3.1/go.mod h1:h8uwbJy68o+tQXCGZNa9D73WN8n0r9OBae5bUnLcgjw= -github.com/grafana-tools/sdk v0.0.0-20210709154219-f35c5af8140d h1:B9Kh4bpYLYe/Fr1UyOWH6QbzpzAB3VMx/UND9TsYHdU= -github.com/grafana-tools/sdk v0.0.0-20210709154219-f35c5af8140d/go.mod h1:MiNTogM+MYQQWjzO7Gg9R6iILfcJ0mJhpaBTwoi8BNI= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29 h1:sezaKhEfPFg8W0Enm61B9Gs911H8iesGY5R8NDPtd1M= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graphql-go/graphql v0.7.9 h1:5Va/Rt4l5g3YjwDnid3vFfn43faaQBq7rMcIZ0VnV34= @@ -1404,6 +1402,8 @@ github.com/sourcegraph/gosaml2 v0.6.1-0.20210128133756-84151d087b10 h1:lLSG41QZ5 github.com/sourcegraph/gosaml2 v0.6.1-0.20210128133756-84151d087b10/go.mod h1:CAOGXqoL6YYtu7kCSx69SZlbNZWbwUchYzOacZatJ3s= github.com/sourcegraph/gosyntect v0.0.0-20210422223331-645353f16ddc h1:iaDqNUpXf8FKUzw1pZrA6NrpILji4OigouwD9OSyamo= github.com/sourcegraph/gosyntect v0.0.0-20210422223331-645353f16ddc/go.mod h1:WiNJKgKTnR3psOIGzVZQjLqZjJZuoL3F8tCh25Uk8dU= +github.com/sourcegraph/grafana-sdk v0.0.0-20210914025534-b4255965ba53 h1:QI7iReP0qGHpZ/rQPhpqsPvTkjQsfO9NPgBK/eBjbsM= +github.com/sourcegraph/grafana-sdk v0.0.0-20210914025534-b4255965ba53/go.mod h1:AHHlOEv1+GGQ3ktHMlhuTUwo3zljV3QJbC0+8o2kn+4= github.com/sourcegraph/httpgzip v0.0.0-20210213125624-48ebf036a6a1 h1:o9U79WCNQjxxK2RYhIvflq7PK6JBbG70O2qG2haR26M= github.com/sourcegraph/httpgzip v0.0.0-20210213125624-48ebf036a6a1/go.mod h1:RqWagzxNGCvucQQC9vX6aps474LCCOgshDpUTTyb+O8= github.com/sourcegraph/jsonx v0.0.0-20200629203448-1a936bd500cf h1:oAdWFqhStsWiiMP/vkkHiMXqFXzl1XfUNOdxKJbd6bI= diff --git a/monitoring/monitoring/internal/grafana/alerts-defined.go b/monitoring/monitoring/internal/grafana/alerts-defined.go new file mode 100644 index 00000000000..2a8b5bd8cfa --- /dev/null +++ b/monitoring/monitoring/internal/grafana/alerts-defined.go @@ -0,0 +1,112 @@ +package grafana + +import "github.com/grafana-tools/sdk" + +func NewContainerAlertsDefinedTable(target sdk.Target) *sdk.Panel { + alertsDefined := sdk.NewCustom("Alerts defined") + alertsDefined.Type = "table" + + var panelTemplateLink = "/-/debug/grafana/d/${__data.fields.service_name}/${__data.fields.service_name}?viewPanel=${__data.fields.grafana_panel_id}" + alertsDefined.CustomPanel = &sdk.CustomPanel{ + "fieldConfig": map[string]interface{}{ + "overrides": []*Override{ + { + Matcher: matcherByName("level"), + Properties: []OverrideProperty{ + propertyWidth(80), + }, + }, + { + Matcher: matcherByName("description"), + Properties: []OverrideProperty{ + {ID: "custom.filterable", Value: true}, + propertyLinks([]*sdk.Link{{ + Title: "Graph panel", + URL: &panelTemplateLink, + }}), + }, + }, + alertsFiringOverride(), + { + Matcher: matcherByName("grafana_panel_id"), + Properties: []OverrideProperty{ + propertyWidth(0.1), + }, + }, + { + Matcher: matcherByName("service_name"), + Properties: []OverrideProperty{ + propertyWidth(0.1), + }, + }, + }, + }, + "options": map[string]interface{}{ + "showHeader": true, + "sortBy": []map[string]interface{}{{ + "desc": true, + "displayName": "firing?", + }}, + }, + "transformations": []map[string]interface{}{{ + "id": "organize", + "options": map[string]map[string]interface{}{ + "excludeByName": { + "Time": true, + }, + "indexByName": { + "Time": 0, + "level": 1, + "description": 2, + "Value": 3, + }, + }, + }}, + "targets": []*sdk.Target{&target}, + } + return alertsDefined +} + +func alertsFiringOverride() *Override { + return &Override{ + Matcher: matcherByName("Value"), + Properties: []OverrideProperty{ + {ID: "displayName", Value: "firing?"}, + {ID: "custom.displayMode", Value: "color-background"}, + {ID: "custom.align", Value: "center"}, + propertyWidth(80), + {ID: "unit", Value: "short"}, + { + ID: "thresholds", + Value: map[string]interface{}{ + "mode": "absolute", + "steps": []map[string]interface{}{{ + "color": "rgba(50, 172, 45, 0.97)", + "value": nil, + }, { + "color": "rgba(245, 54, 54, 0.9)", + "value": 1, + }}, + }, + }, + { + ID: "mappings", + Value: []map[string]interface{}{{ + "from": "", + "id": 1, + "text": "false", + "to": "", + "type": 1, + "value": "0", + }, { + "from": "", + "id": 2, + "text": "true", + "to": "", + "type": 1, + "value": "1", + }}, + }, + }, + } +} diff --git a/monitoring/monitoring/internal/grafana/grafana.go b/monitoring/monitoring/internal/grafana/grafana.go new file mode 100644 index 00000000000..f660cac7fa4 --- /dev/null +++ b/monitoring/monitoring/internal/grafana/grafana.go @@ -0,0 +1,31 @@ +// Package grafana is home to additional internal data types for Grafana to extend the Grafana SDK library +package grafana + +import "github.com/grafana-tools/sdk" + +type OverrideMatcher struct { + ID string `json:"id"` + Options string `json:"options" ` +} + +func matcherByName(name string) OverrideMatcher { + return OverrideMatcher{ID: "byName", Options: name} +} + +type OverrideProperty struct { + ID string `json:"id"` + Value interface{} `json:"value"` +} + +func propertyWidth(width float32) OverrideProperty { + return OverrideProperty{ID: "custom.width", Value: width} +} + +func propertyLinks(links []*sdk.Link) OverrideProperty { + return OverrideProperty{ID: "links", Value: links} +} + +type Override struct { + Matcher OverrideMatcher `json:"matcher"` + Properties []OverrideProperty `json:"properties"` +} diff --git a/monitoring/monitoring/monitoring.go b/monitoring/monitoring/monitoring.go index 757dc8b73a6..03d364df02c 100644 --- a/monitoring/monitoring/monitoring.go +++ b/monitoring/monitoring/monitoring.go @@ -9,6 +9,8 @@ import ( "github.com/cockroachdb/errors" "github.com/grafana-tools/sdk" + + "github.com/sourcegraph/sourcegraph/monitoring/monitoring/internal/grafana" ) // Container describes a Docker container to be observed. @@ -25,9 +27,6 @@ type Container struct { // is responsible for, so that the impact of issues in it is clear. Description string - // List of Annotations to apply to the dashboard. - Annotations []sdk.Annotation - // List of Template Variables to apply to the dashboard Templates []sdk.TemplateVar @@ -73,8 +72,7 @@ func (c *Container) renderDashboard() *sdk.Board { board.SharedCrosshair = true board.Editable = false board.AddTags("builtin") - board.Templating.List = c.Templates - board.Templating.List = append(board.Templating.List, sdk.TemplateVar{ + board.Templating.List = append([]sdk.TemplateVar{{ Label: "Filter alert level", Name: "alert_level", AllValue: ".*", @@ -87,10 +85,8 @@ func (c *Container) renderDashboard() *sdk.Board { }, Query: "critical,warning", Type: "custom", - }, - ) - board.Annotations.List = c.Annotations - board.Annotations.List = append(board.Annotations.List, sdk.Annotation{ + }}, c.Templates...) + board.Annotations.List = []sdk.Annotation{{ Name: "Alert events", Datasource: StringPtr("Prometheus"), // Show alerts matching the selected alert_level (see template variable above) @@ -101,8 +97,7 @@ func (c *Container) renderDashboard() *sdk.Board { IconColor: "rgba(255, 96, 96, 1)", Enable: false, // disable by default for now Type: "tags", - }, - ) + }} // Annotation layers that require a service to export information required by the // Sourcegraph debug server - see the `NoSourcegraphDebugServer` docstring. if !c.NoSourcegraphDebugServer { @@ -129,47 +124,21 @@ func (c *Container) renderDashboard() *sdk.Board { description.TextPanel.Content = fmt.Sprintf(`
-
%s: %s (⧉ architecture diagram) +
%s: %s (⧉ architecture diagram)
`, c.Name, c.Description) board.Panels = append(board.Panels, description) - alertsDefined := sdk.NewTable("Alerts defined") - setPanelSize(alertsDefined, 9, 5) - setPanelPos(alertsDefined, 0, 3) - alertsDefined.TablePanel.Sort = &sdk.Sort{Desc: true, Col: 4} - alertsDefined.TablePanel.Styles = []sdk.ColumnStyle{ - { - Pattern: "Time", - Type: "hidden", - }, - { - Pattern: "level", - Type: "hidden", - }, - { - Pattern: "_01_level", - Alias: StringPtr("level"), - }, - { - Pattern: "Value", - Alias: StringPtr("firing?"), - ColorMode: StringPtr("row"), - Colors: &[]string{"rgba(50, 172, 45, 0.97)", "rgba(237, 129, 40, 0.89)", "rgba(245, 54, 54, 0.9)"}, - Thresholds: &[]string{"0.99999", "1"}, - Type: "string", - MappingType: 1, - ValueMaps: []sdk.ValueMap{ - {TextType: "false", Value: "0"}, - {TextType: "true", Value: "1"}, - }, - }, - } - alertsDefined.AddTarget(&sdk.Target{ - Expr: fmt.Sprintf(`label_replace(sum(max by (level,service_name,name,description)(alert_count{service_name="%s",name!="",level=~"$alert_level"})) by (level,description), "_01_level", "$1", "level", "(.*)")`, c.Name), + alertsDefined := grafana.NewContainerAlertsDefinedTable(sdk.Target{ + Expr: fmt.Sprintf(`label_replace( + sum(max by (level,service_name,name,description,grafana_panel_id)(alert_count{service_name="%s",name!="",level=~"$alert_level"})) by (level,description,service_name,grafana_panel_id), + "description", "$1", "description", ".*: (.*)" + )`, c.Name), Format: "table", Instant: true, }) + setPanelSize(alertsDefined, 9, 5) + setPanelPos(alertsDefined, 0, 3) board.Panels = append(board.Panels, alertsDefined) alertsFiring := sdk.NewGraph("Alerts firing") @@ -191,7 +160,7 @@ func (c *Container) renderDashboard() *sdk.Board { LogBase: 1, Max: sdk.NewFloatString(1), Min: sdk.NewFloatString(0), - Show: true, + Show: false, }, { Format: "short", @@ -200,9 +169,14 @@ func (c *Container) renderDashboard() *sdk.Board { }, } alertsFiring.AddTarget(&sdk.Target{ - Expr: fmt.Sprintf(`sum by (service_name,level,name)(max by (level,service_name,name,description)(alert_count{service_name="%s",name!="",level=~"$alert_level"}) >= 1)`, c.Name), + Expr: fmt.Sprintf(`sum by (service_name,level,name,grafana_panel_id)(max by (level,service_name,name,description,grafana_panel_id)(alert_count{service_name="%s",name!="",level=~"$alert_level"}) >= 1)`, c.Name), LegendFormat: "{{level}}: {{name}}", }) + alertsFiring.GraphPanel.FieldConfig = &sdk.FieldConfig{} + alertsFiring.GraphPanel.FieldConfig.Defaults.Links = []sdk.Link{{ + Title: "Graph panel", + URL: StringPtr("/-/debug/grafana/d/${__field.labels.service_name}/${__field.labels.service_name}?viewPanel=${__field.labels.grafana_panel_id}"), + }} board.Panels = append(board.Panels, alertsFiring) baseY := 8 diff --git a/sg.config.yaml b/sg.config.yaml index 89ece3295a0..097f46ed16f 100644 --- a/sg.config.yaml +++ b/sg.config.yaml @@ -554,14 +554,13 @@ commands: -v "${GRAFANA_DISK}":/var/lib/grafana \ -v "$(pwd)"/dev/grafana/all:/sg_config_grafana/provisioning/datasources \ -v "$(pwd)"/docker-images/grafana/config/provisioning/dashboards:/sg_grafana_additional_dashboards \ - -e DISABLE_SOURCEGRAPH_CONFIG \ - ${IMAGE} >"${GRAFANA_LOG_FILE}" 2>&1 + sourcegraph/grafana:dev >"${GRAFANA_LOG_FILE}" 2>&1 install: | mkdir -p "${GRAFANA_DISK}" mkdir -p "$(dirname ${GRAFANA_LOG_FILE})" docker inspect $CONTAINER >/dev/null 2>&1 && docker rm -f $CONTAINER - CACHE=true ./docker-images/grafana/build.sh + ./docker-images/grafana/build.sh env: GRAFANA_DISK: $HOME/.sourcegraph-dev/data/grafana # Log file location: since we log outside of the Docker container, we should @@ -572,13 +571,12 @@ commands: # We want to capture that output, but because it's fairly noisy, don't want to # display it in the normal case. GRAFANA_LOG_FILE: $HOME/.sourcegraph-dev/logs/grafana/grafana.log - IMAGE: sourcegraph/grafana:dev CONTAINER: grafana PORT: 3370 # docker containers must access things via docker host on non-linux platforms DOCKER_USER: "" ADD_HOST_FLAG: "" - DISABLE_SOURCEGRAPH_CONFIG: false + CACHE: false watch: - monitoring