diff --git a/.betterer.results b/.betterer.results index 3a94de50eb6..4db1152f170 100644 --- a/.betterer.results +++ b/.betterer.results @@ -200,9 +200,6 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "6"], [0, 0, 0, "Unexpected any. Specify a different type.", "7"] ], - "packages/grafana-data/src/field/templateProxies.ts:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"] - ], "packages/grafana-data/src/geo/layer.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], @@ -2523,8 +2520,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Unexpected any. Specify a different type.", "4"], [0, 0, 0, "Unexpected any. Specify a different type.", "5"], - [0, 0, 0, "Unexpected any. Specify a different type.", "6"], - [0, 0, 0, "Unexpected any. Specify a different type.", "7"] + [0, 0, 0, "Unexpected any. Specify a different type.", "6"] ], "public/app/features/dashboard/state/DashboardModel.test.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] @@ -3353,6 +3349,9 @@ exports[`better eslint`] = { "public/app/features/teams/state/selectors.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], + "public/app/features/templating/fieldAccessorCache.ts:5381": [ + [0, 0, 0, "Unexpected any. Specify a different type.", "0"] + ], "public/app/features/templating/formatVariableValue.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], @@ -3361,6 +3360,9 @@ exports[`better eslint`] = { "public/app/features/templating/macroRegistry.test.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], + "public/app/features/templating/templateProxies.ts:5381": [ + [0, 0, 0, "Unexpected any. Specify a different type.", "0"] + ], "public/app/features/templating/template_srv.mock.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], @@ -3377,11 +3379,9 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "9"], [0, 0, 0, "Unexpected any. Specify a different type.", "10"], [0, 0, 0, "Unexpected any. Specify a different type.", "11"], - [0, 0, 0, "Unexpected any. Specify a different type.", "12"], + [0, 0, 0, "Do not use any type assertions.", "12"], [0, 0, 0, "Unexpected any. Specify a different type.", "13"], - [0, 0, 0, "Do not use any type assertions.", "14"], - [0, 0, 0, "Unexpected any. Specify a different type.", "15"], - [0, 0, 0, "Do not use any type assertions.", "16"] + [0, 0, 0, "Do not use any type assertions.", "14"] ], "public/app/features/transformers/FilterByValueTransformer/ValueMatchers/BasicMatcherEditor.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], @@ -5264,6 +5264,9 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Unexpected any. Specify a different type.", "2"] ], + "public/app/plugins/panel/flamegraph/components/FlameGraphTopWrapper.tsx:5381": [ + [0, 0, 0, "Unexpected any. Specify a different type.", "0"] + ], "public/app/plugins/panel/gauge/GaugeMigrations.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], @@ -6010,6 +6013,10 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"] ], + "public/app/plugins/panel/trend/suggestions.ts:5381": [ + [0, 0, 0, "Do not use any type assertions.", "0"], + [0, 0, 0, "Unexpected any. Specify a different type.", "1"] + ], "public/app/plugins/panel/xychart/AutoEditor.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], diff --git a/.drone.yml b/.drone.yml index cc144f74868..9c5f364a85e 100644 --- a/.drone.yml +++ b/.drone.yml @@ -797,6 +797,12 @@ services: volumes: - name: mysql path: /var/lib/mysql +- environment: {} + image: redis:6.2.11-alpine + name: redis +- environment: {} + image: memcached:1.6.9-alpine + name: memcached steps: - commands: - is_fork=$(curl "https://$GITHUB_TOKEN@api.github.com/repos/grafana/grafana/pulls/$DRONE_PULL_REQUEST" @@ -892,6 +898,26 @@ steps: MYSQL_HOST: mysql image: grafana/build-container:1.7.2 name: mysql-integration-tests +- commands: + - dockerize -wait tcp://redis:6379/0 -timeout 120s + - go clean -testcache + - go test -run IntegrationRedis -covermode=atomic -timeout=2m ./pkg/... + depends_on: + - wire-install + environment: + REDIS_URL: redis://redis:6379/0 + image: grafana/build-container:1.7.2 + name: redis-integration-tests +- commands: + - dockerize -wait tcp://memcached:11211 -timeout 120s + - go clean -testcache + - go test -run IntegrationMemcached -covermode=atomic -timeout=2m ./pkg/... + depends_on: + - wire-install + environment: + MEMCACHED_HOSTS: memcached:11211 + image: grafana/build-container:1.7.2 + name: memcached-integration-tests trigger: event: - pull_request @@ -1797,6 +1823,12 @@ services: volumes: - name: mysql path: /var/lib/mysql +- environment: {} + image: redis:6.2.11-alpine + name: redis +- environment: {} + image: memcached:1.6.9-alpine + name: memcached steps: - commands: - mkdir -p bin @@ -1870,6 +1902,26 @@ steps: MYSQL_HOST: mysql image: grafana/build-container:1.7.2 name: mysql-integration-tests +- commands: + - dockerize -wait tcp://redis:6379/0 -timeout 120s + - go clean -testcache + - go test -run IntegrationRedis -covermode=atomic -timeout=2m ./pkg/... + depends_on: + - wire-install + environment: + REDIS_URL: redis://redis:6379/0 + image: grafana/build-container:1.7.2 + name: redis-integration-tests +- commands: + - dockerize -wait tcp://memcached:11211 -timeout 120s + - go clean -testcache + - go test -run IntegrationMemcached -covermode=atomic -timeout=2m ./pkg/... + depends_on: + - wire-install + environment: + MEMCACHED_HOSTS: memcached:11211 + image: grafana/build-container:1.7.2 + name: memcached-integration-tests trigger: branch: main event: @@ -4956,6 +5008,12 @@ services: volumes: - name: mysql path: /var/lib/mysql +- environment: {} + image: redis:6.2.11-alpine + name: redis +- environment: {} + image: memcached:1.6.9-alpine + name: memcached steps: - commands: - mkdir -p bin @@ -5022,6 +5080,26 @@ steps: MYSQL_HOST: mysql image: grafana/build-container:1.7.2 name: mysql-integration-tests +- commands: + - dockerize -wait tcp://redis:6379/0 -timeout 120s + - go clean -testcache + - go test -run IntegrationRedis -covermode=atomic -timeout=2m ./pkg/... + depends_on: + - wire-install + environment: + REDIS_URL: redis://redis:6379/0 + image: grafana/build-container:1.7.2 + name: redis-integration-tests +- commands: + - dockerize -wait tcp://memcached:11211 -timeout 120s + - go clean -testcache + - go test -run IntegrationMemcached -covermode=atomic -timeout=2m ./pkg/... + depends_on: + - wire-install + environment: + MEMCACHED_HOSTS: memcached:11211 + image: grafana/build-container:1.7.2 + name: memcached-integration-tests trigger: ref: - refs/heads/v[0-9]* @@ -5617,7 +5695,7 @@ services: - name: mysql path: /var/lib/mysql - environment: {} - image: redis:6.2.1-alpine + image: redis:6.2.11-alpine name: redis - environment: {} image: memcached:1.6.9-alpine @@ -5718,8 +5796,7 @@ steps: - commands: - dockerize -wait tcp://redis:6379/0 -timeout 120s - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=5m {}' + - go test -run IntegrationRedis -covermode=atomic -timeout=2m ./pkg/... depends_on: - wire-install environment: @@ -5729,8 +5806,7 @@ steps: - commands: - dockerize -wait tcp://memcached:11211 -timeout 120s - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=5m {}' + - go test -run IntegrationMemcached -covermode=atomic -timeout=2m ./pkg/... depends_on: - wire-install environment: @@ -6112,6 +6188,12 @@ services: volumes: - name: mysql path: /var/lib/mysql +- environment: {} + image: redis:6.2.11-alpine + name: redis +- environment: {} + image: memcached:1.6.9-alpine + name: memcached steps: - commands: - mkdir -p bin @@ -6178,6 +6260,26 @@ steps: MYSQL_HOST: mysql image: grafana/build-container:1.7.2 name: mysql-integration-tests +- commands: + - dockerize -wait tcp://redis:6379/0 -timeout 120s + - go clean -testcache + - go test -run IntegrationRedis -covermode=atomic -timeout=2m ./pkg/... + depends_on: + - wire-install + environment: + REDIS_URL: redis://redis:6379/0 + image: grafana/build-container:1.7.2 + name: redis-integration-tests +- commands: + - dockerize -wait tcp://memcached:11211 -timeout 120s + - go clean -testcache + - go test -run IntegrationMemcached -covermode=atomic -timeout=2m ./pkg/... + depends_on: + - wire-install + environment: + MEMCACHED_HOSTS: memcached:11211 + image: grafana/build-container:1.7.2 + name: memcached-integration-tests trigger: event: - promote @@ -6230,7 +6332,7 @@ services: - name: mysql path: /var/lib/mysql - environment: {} - image: redis:6.2.1-alpine + image: redis:6.2.11-alpine name: redis - environment: {} image: memcached:1.6.9-alpine @@ -6332,8 +6434,7 @@ steps: - commands: - dockerize -wait tcp://redis:6379/0 -timeout 120s - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=5m {}' + - go test -run IntegrationRedis -covermode=atomic -timeout=2m ./pkg/... depends_on: - wire-install environment: @@ -6343,8 +6444,7 @@ steps: - commands: - dockerize -wait tcp://memcached:11211 -timeout 120s - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=5m {}' + - go test -run IntegrationMemcached -covermode=atomic -timeout=2m ./pkg/... depends_on: - wire-install environment: @@ -6653,6 +6753,6 @@ kind: secret name: enterprise2_security_prefix --- kind: signature -hmac: 675c90070f9b68e15f349d079fbafa5288c3e5c30c345a4c9678d69afd1cc5a7 +hmac: 54bded4dc7c3ffbbf3859a4f8f6364f59f3b6e0696152a0b835211eca7119e50 ... diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 11503dd8765..59d3c75414e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -407,6 +407,7 @@ lerna.json @grafana/frontend-ops /public/app/plugins/panel/table/ @grafana/grafana-bi-squad /public/app/plugins/panel/table-old/ @grafana/grafana-bi-squad /public/app/plugins/panel/timeseries/ @grafana/dataviz-squad +/public/app/plugins/panel/trend/ @grafana/dataviz-squad /public/app/plugins/panel/geomap/ @grafana/dataviz-squad /public/app/plugins/panel/canvas/ @grafana/dataviz-squad /public/app/plugins/panel/candlestick/ @grafana/dataviz-squad diff --git a/.github/commands.json b/.github/commands.json index 9aacbac983d..f2e9cc2223c 100644 --- a/.github/commands.json +++ b/.github/commands.json @@ -322,5 +322,157 @@ "addToProject": { "url": "https://github.com/orgs/grafana/projects/78" } + }, + { + "type": "label", + "name": "area/panel/candlestick", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/canvas", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/barchart", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/bargauge", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/72" + } + }, + { + "type": "label", + "name": "area/panel/gauge", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/72" + } + }, + { + "type": "label", + "name": "area/panel/geomap", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/graph", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/heatmap", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/histogram", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/icon", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/piechart", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/72" + } + }, + { + "type": "label", + "name": "area/panel/stat", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/72" + } + }, + { + "type": "label", + "name": "area/panel/state-timeline", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/status-history", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/timeseries", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/xychart", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/oss-dataviz", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/56" + } + }, + { + "type": "label", + "name": "area/panel/oss-bi", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/72" + } + }, + { + "type": "label", + "name": "area/panel/table", + "action": "addToProject", + "addToProject": { + "url": "https://github.com/orgs/grafana/projects/72" + } } ] diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index b07cf46eeba..f98a8f141f0 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -17,13 +17,13 @@ jobs: id: regex-match with: text: ${{ github.event.inputs.version }} - regex: '^(\d+.\d+).\d+(?:-beta\d+)?$' + regex: '^(\d+.\d+).\d+(?:-(?:(beta\d+)|(pre)))?$' - uses: actions-ecosystem/action-regex-match@v2.0.2 if: ${{ inputs.version_call != '' }} id: regex-match-version-call with: text: ${{ inputs.version_call }} - regex: '^(\d+.\d+).\d+(?:-beta\d+)?$' + regex: '^(\d+.\d+).\d+(?:-(?:(beta\d+)|(pre)))?$' - name: Validate input version if: ${{ steps.regex-match.outputs.match == '' && github.event.inputs.version != '' }} run: | @@ -50,7 +50,7 @@ jobs: echo "branch_exist=$(git ls-remote --heads https://github.com/grafana/grafana.git v${{ steps.regex-match.outputs.group1 }}.x | wc -l)" >> $GITHUB_OUTPUT - name: Check input version is aligned with branch(main) - if: ${{ github.event.inputs.version != '' && steps.intermedia.outputs.branch_exist == '0' && !contains(steps.intermedia.outputs.short_ref, 'main') }} + if: ${{ github.event.inputs.version != '' && steps.intermedia.outputs.branch_exist == '0' && !contains(github.event.inputs.version, 'pre') && !contains(steps.intermedia.outputs.short_ref, 'main') }} run: | echo "When you want to deliver a new new minor version, you might want to create a new branch first \ with naming convention v[major].[minor].x, and just run the workflow on that branch. \ diff --git a/.github/workflows/doc-validator.yml b/.github/workflows/doc-validator.yml index 5444eef33a0..d9a8ecc2521 100644 --- a/.github/workflows/doc-validator.yml +++ b/.github/workflows/doc-validator.yml @@ -7,7 +7,7 @@ jobs: doc-validator: runs-on: "ubuntu-latest" container: - image: "grafana/doc-validator:v1.9.0" + image: "grafana/doc-validator:v1.10.0" steps: - name: "Checkout code" uses: "actions/checkout@v3" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d35fb8b890c..6dcef56e776 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,7 @@ You can contribute to Grafana in several ways. Here are some examples: - Organize meetups and user groups in your local area. - Help others by answering questions about Grafana. -**Please note:** We do not currently accept contributions for translations. Please do not submit pull requests for messages.po files - they will be rejected. +**Please note:** We do not currently accept contributions for translations. Please do not submit pull requests translating grafana.json files - they will be rejected. We do accept contributions to mark up phrases for translation. See [Internationalization](contribute/internationalization.md). For more ways to contribute, check out the [Open Source Guides](https://opensource.guide/how-to-contribute/). diff --git a/Makefile b/Makefile index 5d5d9f4387b..ad161a619d8 100644 --- a/Makefile +++ b/Makefile @@ -143,6 +143,18 @@ test-go-integration-mysql: devenv-mysql ## Run integration tests for mysql backe $(GO) clean -testcache $(GO) list './pkg/...' | xargs -I {} sh -c 'GRAFANA_TEST_DB=mysql go test -run Integration -covermode=atomic -timeout=2m {}' +.PHONY: test-go-integration-redis +test-go-integration-redis: ## Run integration tests for redis cache. + @echo "test backend integration redis tests" + $(GO) clean -testcache + REDIS_URL=localhost:6379 $(GO) test -run IntegrationRedis -covermode=atomic -timeout=2m ./pkg/... + +.PHONY: test-go-integration-memcached +test-go-integration-memcached: ## Run integration tests for memcached cache. + @echo "test backend integration memcached tests" + $(GO) clean -testcache + MEMCACHED_HOSTS=localhost:11211 $(GO) test -run IntegrationMemcached -covermode=atomic -timeout=2m ./pkg/... + test-js: ## Run tests for frontend. @echo "test frontend" yarn test diff --git a/devenv/datasources.yaml b/devenv/datasources.yaml index 4be1fe4b35f..9f2fad5e059 100644 --- a/devenv/datasources.yaml +++ b/devenv/datasources.yaml @@ -124,6 +124,7 @@ datasources: - name: gdev-elasticsearch type: elasticsearch + uid: gdev-elasticsearch access: proxy database: "[logs-]YYYY.MM.DD" url: http://localhost:9200 diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_compare.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_compare.json deleted file mode 100644 index 2ab0785563b..00000000000 --- a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_compare.json +++ /dev/null @@ -1,10995 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": false, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "limit": 100, - "name": "Annotations & Alerts", - "showIn": 0, - "type": "dashboard" - } - ] - }, - "editable": true, - "graphTooltip": 0, - "iteration": 1620904436360, - "links": [ - { - "asDropdown": true, - "icon": "external link", - "tags": [ - "gdev", - "elasticsearch", - "datasource-test" - ], - "title": "Dashboards", - "type": "dashboards" - } - ], - "panels": [ - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 5, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "id": "1", - "type": "count" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Basic (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "hiddenSeries": false, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "id": "1", - "type": "count" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Basic (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 10 - }, - "hiddenSeries": false, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "1m", - "min_doc_count": 50 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "id": "1", - "type": "count" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Basic (version one) - interval 1m + min doc count 50", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 10 - }, - "hiddenSeries": false, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "1m", - "min_doc_count": 50 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "id": "1", - "type": "count" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Basic (version two) - interval 1m + min doc count 50", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 19 - }, - "hiddenSeries": false, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 10 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "id": "1", - "type": "count" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Basic (version one) - interval 5m + trim edges=10", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 19 - }, - "hiddenSeries": false, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 10 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "id": "1", - "type": "count" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Basic (version two) - interval 5m + trim edges=10", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Basic date histogram with count", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 1 - }, - "id": 11, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 2 - }, - "hiddenSeries": false, - "id": 12, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "avg (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 2 - }, - "hiddenSeries": false, - "id": 13, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "avg (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 11 - }, - "hiddenSeries": false, - "id": 14, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "sum (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 11 - }, - "hiddenSeries": false, - "id": 15, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "sum (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 20 - }, - "hiddenSeries": false, - "id": 16, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "max" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "max (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 20 - }, - "hiddenSeries": false, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "max" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "max (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 29 - }, - "hiddenSeries": false, - "id": 17, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "min" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "min (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 29 - }, - "hiddenSeries": false, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "min" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "min (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 38 - }, - "hiddenSeries": false, - "id": 18, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sort": "min", - "sortDesc": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": true, - "count": true, - "max": true, - "min": true, - "std_deviation": true, - "std_deviation_bounds_lower": true, - "std_deviation_bounds_upper": true, - "sum": true - }, - "settings": {}, - "type": "extended_stats" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "extended stats (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 38 - }, - "hiddenSeries": false, - "id": 23, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sort": "min", - "sortDesc": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": true, - "count": true, - "max": true, - "min": true, - "std_deviation": true, - "std_deviation_bounds_lower": true, - "std_deviation_bounds_upper": true, - "sum": true - }, - "settings": {}, - "type": "extended_stats" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "extended stats (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 47 - }, - "hiddenSeries": false, - "id": 19, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": { - "percents": [ - 25, - 50, - 75, - 95, - 99 - ] - }, - "type": "percentiles" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "percentiles (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 47 - }, - "hiddenSeries": false, - "id": 24, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": { - "percents": [ - 25, - 50, - 75, - 95, - 99 - ] - }, - "type": "percentiles" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "percentiles (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 56 - }, - "hiddenSeries": false, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "cardinality" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "unique count (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "decimals": 3, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 56 - }, - "hiddenSeries": false, - "id": 25, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "cardinality" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "unique count (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Basic date histogram with metric aggregation", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 2 - }, - "id": 27, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 3 - }, - "hiddenSeries": false, - "id": 55, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "count" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 3 - }, - "hiddenSeries": false, - "id": 34, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "count" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 12 - }, - "hiddenSeries": false, - "id": 29, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "avg (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 12 - }, - "hiddenSeries": false, - "id": 56, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "avg (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 21 - }, - "hiddenSeries": false, - "id": 30, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "sum" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "sum (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 21 - }, - "hiddenSeries": false, - "id": 35, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "sum" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "sum (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 30 - }, - "hiddenSeries": false, - "id": 31, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "max" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "max (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 30 - }, - "hiddenSeries": false, - "id": 36, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "max" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "max (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 39 - }, - "hiddenSeries": false, - "id": 32, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "min" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "min (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 39 - }, - "hiddenSeries": false, - "id": 37, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "min" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "min (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 48 - }, - "hiddenSeries": false, - "id": 33, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "cardinality" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "unique count (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 48 - }, - "hiddenSeries": false, - "id": 38, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "cardinality" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": { - "minimize": false, - "model": "simple", - "window": 5 - }, - "type": "moving_avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "unique count (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Basic date histogram with moving average aggregation", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 3 - }, - "id": 39, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 4 - }, - "hiddenSeries": false, - "id": 57, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "count" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 4 - }, - "hiddenSeries": false, - "id": 41, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "count" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 13 - }, - "hiddenSeries": false, - "id": 40, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "avg (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 13 - }, - "hiddenSeries": false, - "id": 58, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "avg (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 22 - }, - "hiddenSeries": false, - "id": 42, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "sum" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "sum (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 22 - }, - "hiddenSeries": false, - "id": 43, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "sum" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "sum (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 31 - }, - "hiddenSeries": false, - "id": 44, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "max" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "max (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 31 - }, - "hiddenSeries": false, - "id": 45, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "max" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "max (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 40 - }, - "hiddenSeries": false, - "id": 46, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "min" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "min (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 40 - }, - "hiddenSeries": false, - "id": 47, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "min" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "min (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 49 - }, - "hiddenSeries": false, - "id": 48, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "cardinality" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "unique count (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 49 - }, - "hiddenSeries": false, - "id": 49, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "cardinality" - }, - { - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "derivative" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "unique count (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Basic date histogram with derivative aggregation", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 4 - }, - "id": 70, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 5 - }, - "hiddenSeries": false, - "id": 71, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:344", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:340", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "count" - }, - { - "$$hashKey": "object:341", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 5 - }, - "hiddenSeries": false, - "id": 77, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:344", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:340", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "count" - }, - { - "$$hashKey": "object:341", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 14 - }, - "hiddenSeries": false, - "id": 72, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:546", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:542", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - }, - { - "$$hashKey": "object:543", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "avg (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 14 - }, - "hiddenSeries": false, - "id": 78, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:546", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:542", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - }, - { - "$$hashKey": "object:543", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "avg (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 23 - }, - "hiddenSeries": false, - "id": 73, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:731", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:727", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "sum" - }, - { - "$$hashKey": "object:728", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "sum (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 23 - }, - "hiddenSeries": false, - "id": 79, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:731", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:727", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "sum" - }, - { - "$$hashKey": "object:728", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "sum (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 32 - }, - "hiddenSeries": false, - "id": 74, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:885", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:881", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "max" - }, - { - "$$hashKey": "object:882", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "max (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 32 - }, - "hiddenSeries": false, - "id": 80, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:885", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:881", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "max" - }, - { - "$$hashKey": "object:882", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "max (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 41 - }, - "hiddenSeries": false, - "id": 75, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:1039", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:1035", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "min" - }, - { - "$$hashKey": "object:1036", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "min (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 41 - }, - "hiddenSeries": false, - "id": 81, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:1039", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:1035", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "min" - }, - { - "$$hashKey": "object:1036", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "min (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 50 - }, - "hiddenSeries": false, - "id": 76, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:1193", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:1189", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "cardinality" - }, - { - "$$hashKey": "object:1190", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "unique count (version one) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 50 - }, - "hiddenSeries": false, - "id": 82, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:1193", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:1189", - "field": "@value", - "hide": true, - "id": "1", - "meta": {}, - "settings": {}, - "type": "cardinality" - }, - { - "$$hashKey": "object:1190", - "field": "1", - "id": "3", - "meta": {}, - "pipelineAgg": "1", - "settings": {}, - "type": "cumulative_sum" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "unique count (version two) - interval 5m", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Basic date histogram with cumulative sum aggregation", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 5 - }, - "id": 60, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 6 - }, - "hiddenSeries": false, - "id": 63, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "hide": true, - "id": "1", - "type": "count" - }, - { - "field": "select field", - "id": "3", - "meta": {}, - "pipelineVariables": [ - { - "name": "var1", - "pipelineAgg": "1" - } - ], - "settings": { - "script": "params.var1 * 1000" - }, - "type": "bucket_script" - } - ], - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count * 1000 (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 6 - }, - "hiddenSeries": false, - "id": 64, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "hide": true, - "id": "1", - "type": "count" - }, - { - "field": "select field", - "id": "3", - "meta": {}, - "pipelineVariables": [ - { - "name": "var1", - "pipelineAgg": "1" - } - ], - "settings": { - "script": "params.var1 * 1000" - }, - "type": "bucket_script" - } - ], - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count * 1000 (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 14 - }, - "hiddenSeries": false, - "id": 65, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "hide": true, - "id": "1", - "type": "count" - }, - { - "field": "@value", - "hide": true, - "id": "3", - "meta": {}, - "settings": {}, - "type": "avg" - }, - { - "field": "select field", - "id": "4", - "meta": {}, - "pipelineVariables": [ - { - "name": "var1", - "pipelineAgg": "1" - }, - { - "name": "var2", - "pipelineAgg": "3" - } - ], - "settings": { - "script": "params.var1 * params.var2" - }, - "type": "bucket_script" - } - ], - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count * avg (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 14 - }, - "hiddenSeries": false, - "id": 66, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "hide": true, - "id": "1", - "type": "count" - }, - { - "field": "@value", - "hide": true, - "id": "3", - "meta": {}, - "settings": {}, - "type": "avg" - }, - { - "field": "select field", - "id": "4", - "meta": {}, - "pipelineVariables": [ - { - "name": "var1", - "pipelineAgg": "1" - }, - { - "name": "var2", - "pipelineAgg": "3" - } - ], - "settings": { - "script": "params.var1 * params.var2" - }, - "type": "bucket_script" - } - ], - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count * avg (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Basic date histogram with bucket script aggregation", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 54, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_one" - }, - "decimals": 3, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 7 - }, - "hiddenSeries": false, - "id": 51, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sort": "min", - "sortDesc": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "alias": "{{@source}} - {{@hostname}} - {{@metric}} {{metric}}", - "bucketAggs": [ - { - "fake": true, - "field": "@source", - "id": "4", - "settings": { - "min_doc_count": 1, - "order": "desc", - "orderBy": "_count", - "size": "10" - }, - "type": "terms" - }, - { - "fake": true, - "field": "@metric", - "id": "5", - "settings": { - "min_doc_count": 1, - "order": "desc", - "orderBy": "_term", - "size": "10" - }, - "type": "terms" - }, - { - "fake": true, - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": 1, - "order": "desc", - "orderBy": "_term", - "size": "5" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "id": "1", - "type": "count" - }, - { - "field": "@value", - "id": "6", - "meta": {}, - "settings": {}, - "type": "avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count/average with triple terms agg (version one) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "$version_two" - }, - "decimals": 3, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 7 - }, - "hiddenSeries": false, - "id": 52, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sort": "min", - "sortDesc": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "paceLength": 10, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "alias": "{{@source}} - {{@hostname}} - {{@metric}} {{metric}}", - "bucketAggs": [ - { - "fake": true, - "field": "@source", - "id": "4", - "settings": { - "min_doc_count": 1, - "order": "desc", - "orderBy": "_count", - "size": "10" - }, - "type": "terms" - }, - { - "fake": true, - "field": "@metric", - "id": "5", - "settings": { - "min_doc_count": 1, - "order": "desc", - "orderBy": "_term", - "size": "10" - }, - "type": "terms" - }, - { - "fake": true, - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": 1, - "order": "desc", - "orderBy": "_term", - "size": "5" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "id": "1", - "type": "count" - }, - { - "field": "@value", - "id": "6", - "meta": {}, - "settings": {}, - "type": "avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "count/average with triple terms agg (version two) - interval auto", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Multiple metrics and aggregations", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 7 - }, - "id": 103, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 8 - }, - "hiddenSeries": false, - "id": 104, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "_count", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "id": "1", - "type": "count" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by Doc Count", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 8 - }, - "hiddenSeries": false, - "id": 107, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "_count", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "id": "1", - "type": "count" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by Doc Count", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 16 - }, - "hiddenSeries": false, - "id": 116, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "_term", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "id": "1", - "type": "count" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by Term value", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 16 - }, - "hiddenSeries": false, - "id": 117, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "_term", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "id": "1", - "type": "count" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by Term value", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 24 - }, - "hiddenSeries": false, - "id": 105, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "type": "avg" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by avg", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 24 - }, - "hiddenSeries": false, - "id": 108, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "type": "avg" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by avg", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 32 - }, - "hiddenSeries": false, - "id": 106, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "type": "cardinality" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by unique count", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 32 - }, - "hiddenSeries": false, - "id": 109, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.4.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "type": "cardinality" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by unique count", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Terms order by simple aggregation", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 8 - }, - "id": 84, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 9 - }, - "hiddenSeries": false, - "id": 86, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[avg]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": true, - "count": false, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (avg)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 9 - }, - "hiddenSeries": false, - "id": 94, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[avg]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": true, - "count": false, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (avg)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 17 - }, - "hiddenSeries": false, - "id": 87, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[min]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": true, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (min)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 17 - }, - "hiddenSeries": false, - "id": 95, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[min]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": true, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (min)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 25 - }, - "hiddenSeries": false, - "id": 88, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[max]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": true, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (max)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 25 - }, - "hiddenSeries": false, - "id": 96, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[max]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": true, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (max)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 33 - }, - "hiddenSeries": false, - "id": 89, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[sum]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": true - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (sum)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 33 - }, - "hiddenSeries": false, - "id": 97, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[sum]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": true - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (sum)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 41 - }, - "hiddenSeries": false, - "id": 90, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[count]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": true, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (count)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 41 - }, - "hiddenSeries": false, - "id": 98, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[count]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": true, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (count)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 49 - }, - "hiddenSeries": false, - "id": 91, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[std_deviation]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": false, - "std_deviation": true, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (std dev)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 49 - }, - "hiddenSeries": false, - "id": 99, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[std_deviation]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": false, - "std_deviation": true, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (std dev)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 57 - }, - "hiddenSeries": false, - "id": 92, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[std_upper]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": true, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (std dev upper)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 57 - }, - "hiddenSeries": false, - "id": 100, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[std_upper]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": false, - "std_deviation_bounds_upper": true, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (std dev upper)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 65 - }, - "hiddenSeries": false, - "id": 93, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[std_lower]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": true, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (std dev lower)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 65 - }, - "hiddenSeries": false, - "id": 101, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[std_lower]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "avg": false, - "count": false, - "max": false, - "min": false, - "std_deviation": false, - "std_deviation_bounds_lower": true, - "std_deviation_bounds_upper": false, - "sum": false - }, - "type": "extended_stats" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by extended stats (std dev lower)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Terms order by extended stats", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 9 - }, - "id": 111, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 10 - }, - "hiddenSeries": false, - "id": 112, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[25.0]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "settings": { - "percents": [ - "25" - ] - }, - "type": "percentiles" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by percentile (25)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 10 - }, - "hiddenSeries": false, - "id": 114, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "desc", - "orderBy": "1[25.0]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "settings": { - "percents": [ - "25" - ] - }, - "type": "percentiles" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by percentile (25)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_one}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 18 - }, - "hiddenSeries": false, - "id": 113, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[99.0]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "settings": { - "percents": [ - "99" - ] - }, - "type": "percentiles" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by percentile (99)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": { - "uid": "${version_two}" - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 18 - }, - "hiddenSeries": false, - "id": 115, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.0-pre", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "", - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": "0", - "order": "asc", - "orderBy": "1[99.0]", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "settings": { - "percents": [ - "99" - ] - }, - "type": "percentiles" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Terms order by percentile (99)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "title": "Terms order by percentile", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 119, - "panels": [], - "title": "Inline scripts", - "type": "row" - }, - { - "datasource": { - "uid": "${version_one}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "viz": false, - "legend": false, - "tooltip": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 121, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "alias": "New Script Format", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "settings": { - "script": "_value * 2" - }, - "type": "avg" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - }, - { - "alias": "Old Script Format", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "hide": false, - "metrics": [ - { - "field": "@value", - "id": "1", - "settings": { - "script": { - "inline": "_value * 1.5" - } - }, - "type": "avg" - } - ], - "query": "", - "refId": "B", - "timeField": "@timestamp" - } - ], - "title": "Old & new script format", - "type": "timeseries" - }, - { - "datasource": { - "uid": "${version_two}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "viz": false, - "legend": false, - "tooltip": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 122, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "alias": "New Script Format", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "settings": { - "script": "_value * 2" - }, - "type": "avg" - } - ], - "query": "", - "refId": "A", - "timeField": "@timestamp" - }, - { - "alias": "Old Script Format", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto" - }, - "type": "date_histogram" - } - ], - "hide": false, - "metrics": [ - { - "field": "@value", - "id": "1", - "settings": { - "script": { - "inline": "_value * 1.5" - } - }, - "type": "avg" - } - ], - "query": "", - "refId": "B", - "timeField": "@timestamp" - } - ], - "title": "Old & new script format", - "type": "timeseries" - } - ], - "refresh": false, - "schemaVersion": 33, - "style": "dark", - "tags": [ - "elasticsearch", - "gdev", - "datasource-test" - ], - "templating": { - "list": [ - { - "current": { - "selected": false, - "text": "gdev-elasticsearch-v5-metrics", - "value": "gdev-elasticsearch-v5-metrics" - }, - "hide": 0, - "includeAll": false, - "label": "Version One", - "multi": false, - "name": "version_one", - "options": [], - "query": "elasticsearch", - "queryValue": "", - "refresh": 1, - "regex": "/^gdev.*metrics$/", - "skipUrlSync": false, - "type": "datasource" - }, - { - "current": { - "selected": false, - "text": "gdev-elasticsearch-v56-metrics", - "value": "gdev-elasticsearch-v56-metrics" - }, - "hide": 0, - "includeAll": false, - "label": "Version Two", - "multi": false, - "name": "version_two", - "options": [], - "query": "elasticsearch", - "queryValue": "", - "refresh": 1, - "regex": "/^gdev.*metrics$/", - "skipUrlSync": false, - "type": "datasource" - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Datasource tests - Elasticsearch comparison", - "uid": "fuFWehBmk", - "version": 4 -} diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_complex.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_complex.json new file mode 100644 index 00000000000..5c277b491f2 --- /dev/null +++ b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_complex.json @@ -0,0 +1,5300 @@ +{ + "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, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 8, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m", + "min_doc_count": 50 + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic - interval 1m + min doc count 50", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m", + "min_doc_count": 0, + "trimEdges": 10 + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic - interval 5m + trim edges = 10", + "type": "timeseries" + } + ], + "title": "Date histogram with count", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 7, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 2 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - avg - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 2 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "percents": [ + "25", + "50", + "75", + "95", + "99" + ] + }, + "type": "percentiles" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - percentiles - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "min" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - min - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 19, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - sum - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - max - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "avg": true, + "count": true, + "max": true, + "min": true, + "std_deviation": true, + "std_deviation_bounds_lower": true, + "std_deviation_bounds_upper": true, + "sum": true + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - extended stats - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 23, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "cardinality" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - unique count - interval auto", + "type": "timeseries" + } + ], + "title": "Date histogram with metric aggregation", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 2 + }, + "id": 6, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 3 + }, + "id": 26, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": false, + "id": "1", + "type": "count" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - count - interval 5m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 3 + }, + "id": 29, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "hide": false, + "id": "1", + "type": "cardinality" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - unique count - interval 5m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 31, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - max - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 34, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - avg - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "type": "sum" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - sum - interval 1m", + "type": "timeseries" + } + ], + "title": "Date histogram with moving functions", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 5, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 4 + }, + "id": 37, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "precision_threshold": "10" + }, + "type": "cardinality" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "derivative" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "derivative - unique count - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 4 + }, + "id": 39, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "derivative" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "derivative - max - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 42, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "type": "sum" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "derivative" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "derivative - sum - interval auto", + "type": "timeseries" + } + ], + "title": "Date histogram with derivative", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 4, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 5 + }, + "id": 43, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "precision_threshold": "10" + }, + "type": "cardinality" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "cumulative sum - unique count - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 5 + }, + "id": 46, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "settings": { + "script": "_value * 0.1" + }, + "type": "avg" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "cumulative sum - avg - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 48, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "10s" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "cumulative sum - count - interval 10s", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 49, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m", + "trimEdges": "100" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "min" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "cumulative sum - min - interval 1m - trim edges 100", + "type": "timeseries" + } + ], + "title": "Date histogram with cumulative sum aggregation", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 3, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 51, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": true, + "id": "1", + "type": "count" + }, + { + "field": "value", + "hide": true, + "id": "4", + "type": "avg" + }, + { + "id": "5", + "pipelineVariables": [ + { + "name": "var1", + "pipelineAgg": "1" + }, + { + "name": "var2", + "pipelineAgg": "4" + } + ], + "settings": { + "script": "params.var1 * params.var2" + }, + "type": "bucket_script" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count * avg - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 54, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": true, + "id": "1", + "type": "count" + }, + { + "id": "3", + "pipelineVariables": [ + { + "name": "var1", + "pipelineAgg": "1" + } + ], + "settings": { + "script": "params.var1 * 1000" + }, + "type": "bucket_script" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count * 1000 - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 57, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "Alias", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": true, + "id": "1", + "type": "count" + }, + { + "id": "3", + "pipelineVariables": [ + { + "name": "var1", + "pipelineAgg": "1" + } + ], + "settings": { + "script": "params.var1 * 1000" + }, + "type": "bucket_script" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count * 1000 - interval 1m", + "type": "timeseries" + } + ], + "title": "Date histogram with bucket script aggregation", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 2, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 7 + }, + "id": 55, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "4", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "metric", + "id": "5", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "level", + "id": "6", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": false, + "id": "1", + "type": "count" + }, + { + "field": "value", + "id": "3", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count/average with triple terms agg - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 7 + }, + "id": 60, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "{{hostname}} - {{metric}} - {{level}}", + "bucketAggs": [ + { + "field": "hostname", + "id": "4", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "metric", + "id": "5", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "level", + "id": "6", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": false, + "id": "1", + "type": "count" + }, + { + "field": "value", + "id": "3", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count/average with triple terms agg - interval auto", + "transformations": [], + "type": "timeseries" + } + ], + "title": "Multiple metrics and aggregations", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 62, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 61, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "0", + "order": "desc", + "orderBy": "1", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "cardinality" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by unique count", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 70, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "0", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by Term value", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 71, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by Doc Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 73, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by avg", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 76, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "hostname: {{hostname}}", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by avg with alias", + "type": "timeseries" + } + ], + "title": "Terms order by simple aggregation", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 63, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 78, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[std_lower]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "std_deviation_bounds_lower": true, + "std_deviation_bounds_upper": false + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by extended stats (std dev lower)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 80, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[std_lower]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "std_deviation": true, + "std_deviation_bounds_lower": false, + "std_deviation_bounds_upper": false + }, + "settings": { + "script": "_value * 4", + "sigma": "3" + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by extended stats (std dev)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 82, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[sum]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1h" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "meta": { + "std_deviation": false, + "std_deviation_bounds_lower": false, + "std_deviation_bounds_upper": false, + "sum": true + }, + "settings": { + "script": "_value * 4", + "sigma": "3" + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by extended stats (sum)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 83, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[count]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "10m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "meta": { + "avg": true, + "count": true, + "std_deviation": false, + "std_deviation_bounds_lower": false, + "std_deviation_bounds_upper": false, + "sum": false + }, + "settings": { + "script": "_value * 4", + "sigma": "3" + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by extended stats (count,avg)", + "type": "timeseries" + } + ], + "title": "Terms order by extended stats", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 64, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 85, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[25.0]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "settings": { + "percents": [ + "25", + "50", + "75", + "95", + "99" + ], + "script": "_value * 2" + }, + "type": "percentiles" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by percentile", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 88, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[99.0]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "percents": [ + "99" + ] + }, + "type": "percentiles" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by percentile (99)", + "type": "timeseries" + } + ], + "title": "Terms order by percentile", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 65, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 89, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "New script format", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "script": "_value * 2" + }, + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "alias": "Old script format", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "hide": false, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "script": "_value * 1.5" + }, + "type": "avg" + } + ], + "query": "", + "refId": "B", + "timeField": "@timestamp" + } + ], + "title": "Old & new script format", + "type": "timeseries" + } + ], + "title": "Inline scripts", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 66, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 92, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "size": "500" + }, + "type": "raw_document" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Raw documents in table", + "transformations": [ + { + "id": "extractFields", + "options": { + "format": "json", + "replace": true, + "source": "A" + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 36 + }, + "id": 93, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "size": "10" + }, + "type": "raw_data" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Raw data", + "transformations": [], + "type": "table" + } + ], + "title": "Raw data and documents", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 67, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 95, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "limit": "10" + }, + "type": "logs" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Logs", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 94, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "limit": "10" + }, + "type": "logs" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Logs", + "type": "logs" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 96, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "limit": "10" + }, + "type": "logs" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Logs", + "type": "table" + } + ], + "title": "Logs", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "gdev", + "elasticsearch", + "datasource-test" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Datasource tests - Elasticsearch complex", + "uid": "es_complex", + "version": 1, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_migration.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_migration.json new file mode 100644 index 00000000000..d0790a5c3e2 --- /dev/null +++ b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_migration.json @@ -0,0 +1,10352 @@ +{ + "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, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 8, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m", + "min_doc_count": 50 + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic - interval 1m + min doc count 50", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m", + "min_doc_count": 50 + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic - interval 1m + min doc count 50 (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 25 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 25 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 33 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m", + "min_doc_count": 0, + "trimEdges": 10 + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic - interval 5m + trim edges = 10", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 33 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m", + "min_doc_count": 0, + "trimEdges": 10 + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic - interval 5m + trim edges = 10 (backend)", + "type": "timeseries" + } + ], + "title": "Date histogram with count", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 7, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - avg - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic with aggregation - avg - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "percents": [ + "25", + "50", + "75", + "95", + "99" + ] + }, + "type": "percentiles" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - percentiles - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 17, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "percents": [ + "25", + "50", + "75", + "95", + "99" + ] + }, + "type": "percentiles" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic with aggregation - percentiles - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 34 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "min" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - min - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 34 + }, + "id": 20, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "min" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic with aggregation - min - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 42 + }, + "id": 19, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - sum - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 42 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic with aggregation - sum - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 50 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - max - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 50 + }, + "id": 24, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic with aggregation - max - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 58 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "avg": true, + "count": true, + "max": true, + "min": true, + "std_deviation": true, + "std_deviation_bounds_lower": true, + "std_deviation_bounds_upper": true, + "sum": true + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - extended stats - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 58 + }, + "id": 28, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "avg": true, + "count": true, + "max": true, + "min": true, + "std_deviation": true, + "std_deviation_bounds_lower": true, + "std_deviation_bounds_upper": true, + "sum": true + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic with aggregation - extended stats - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 66 + }, + "id": 23, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "cardinality" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Basic with aggregation - unique count - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 66 + }, + "id": 25, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "cardinality" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Basic with aggregation - unique count - interval auto (backend)", + "type": "timeseries" + } + ], + "title": "Date histogram with metric aggregation", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 2 + }, + "id": 6, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 26, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": false, + "id": "1", + "type": "count" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - count - interval 5m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 30, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": false, + "id": "1", + "type": "count" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "moving function - count - interval 5m (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 29, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "hide": false, + "id": "1", + "type": "cardinality" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - unique count - interval 5m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 32, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "hide": false, + "id": "1", + "type": "cardinality" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "moving function - unique count - interval 5m (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 31, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - max - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 33, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "moving function - max - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 34, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - avg - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 36, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "moving function - avg - interval 1m (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 51 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "type": "sum" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "moving function - sum - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 51 + }, + "id": 38, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "type": "sum" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "settings": { + "script": "MovingFunctions.max(values)", + "window": "10" + }, + "type": "moving_fn" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "moving function - sum - interval 1m (backend)", + "type": "timeseries" + } + ], + "title": "Date histogram with moving functions", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 5, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 37, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "precision_threshold": "10" + }, + "type": "cardinality" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "derivative" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "derivative - unique count - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 40, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "precision_threshold": "10" + }, + "type": "cardinality" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "derivative" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "derivative - unique count - interval 1m (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 39, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "derivative" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "derivative - max - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 28 + }, + "id": 41, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "derivative" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "derivative - max - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 36 + }, + "id": 42, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "type": "sum" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "derivative" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "derivative - sum - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 36 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "type": "sum" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "derivative" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "derivative - sum - interval auto (backend)", + "type": "timeseries" + } + ], + "title": "Date histogram with derivative", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 4, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 43, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "precision_threshold": "10" + }, + "type": "cardinality" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "cumulative sum - unique count - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 45, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "precision_threshold": "10" + }, + "type": "cardinality" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "cumulative sum - unique count - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 46, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "settings": { + "script": "_value * 0.1" + }, + "type": "avg" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "cumulative sum - avg - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 29 + }, + "id": 47, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "settings": { + "script": "_value * 0.1" + }, + "type": "avg" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "cumulative sum - avg - interval 1m (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 37 + }, + "id": 48, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "10s" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "cumulative sum - count - interval 10s", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 37 + }, + "id": 50, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "10s" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "cumulative sum - count - interval 10s (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 45 + }, + "id": 49, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m", + "trimEdges": "100" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "min" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "cumulative sum - min - interval 1m - trim edges 100", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 45 + }, + "id": 52, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m", + "trimEdges": "100" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "min" + }, + { + "field": "1", + "id": "4", + "pipelineAgg": "1", + "type": "cumulative_sum" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "cumulative sum - min - interval 1m - trim edges 100 (backend)", + "type": "timeseries" + } + ], + "title": "Date histogram with cumulative sum aggregation", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 3, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 51, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": true, + "id": "1", + "type": "count" + }, + { + "field": "value", + "hide": true, + "id": "4", + "type": "avg" + }, + { + "id": "5", + "pipelineVariables": [ + { + "name": "var1", + "pipelineAgg": "1" + }, + { + "name": "var2", + "pipelineAgg": "4" + } + ], + "settings": { + "script": "params.var1 * params.var2" + }, + "type": "bucket_script" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count * avg - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 53, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": true, + "id": "1", + "type": "count" + }, + { + "field": "value", + "hide": true, + "id": "4", + "type": "avg" + }, + { + "id": "5", + "pipelineVariables": [ + { + "name": "var1", + "pipelineAgg": "1" + }, + { + "name": "var2", + "pipelineAgg": "4" + } + ], + "settings": { + "script": "params.var1 * params.var2" + }, + "type": "bucket_script" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "count * avg - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 54, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": true, + "id": "1", + "type": "count" + }, + { + "id": "3", + "pipelineVariables": [ + { + "name": "var1", + "pipelineAgg": "1" + } + ], + "settings": { + "script": "params.var1 * 1000" + }, + "type": "bucket_script" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count * 1000 - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 56, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": true, + "id": "1", + "type": "count" + }, + { + "id": "3", + "pipelineVariables": [ + { + "name": "var1", + "pipelineAgg": "1" + } + ], + "settings": { + "script": "params.var1 * 1000" + }, + "type": "bucket_script" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "count * 1000 - interval 1m (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 57, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "Alias", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": true, + "id": "1", + "type": "count" + }, + { + "id": "3", + "pipelineVariables": [ + { + "name": "var1", + "pipelineAgg": "1" + } + ], + "settings": { + "script": "params.var1 * 1000" + }, + "type": "bucket_script" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count * 1000 - interval 1m", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 58, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "Alias", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": true, + "id": "1", + "type": "count" + }, + { + "id": "3", + "pipelineVariables": [ + { + "name": "var1", + "pipelineAgg": "1" + } + ], + "settings": { + "script": "params.var1 * 1000" + }, + "type": "bucket_script" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "count * 1000 - interval 1m (backend)", + "type": "timeseries" + } + ], + "title": "Date histogram with bucket script aggregation", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 2, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 55, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "4", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "metric", + "id": "5", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "level", + "id": "6", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": false, + "id": "1", + "type": "count" + }, + { + "field": "value", + "id": "3", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count/average with triple terms agg - interval auto", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 23 + }, + "id": 59, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "4", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "metric", + "id": "5", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "level", + "id": "6", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": false, + "id": "1", + "type": "count" + }, + { + "field": "value", + "id": "3", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "count/average with triple terms agg - interval auto (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 60, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "{{hostname}} - {{metric}} - {{level}}", + "bucketAggs": [ + { + "field": "hostname", + "id": "4", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "metric", + "id": "5", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "level", + "id": "6", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": false, + "id": "1", + "type": "count" + }, + { + "field": "value", + "id": "3", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "count/average with triple terms agg - interval auto", + "transformations": [], + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 68, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "{{hostname}} - {{metric}} - {{level}}", + "bucketAggs": [ + { + "field": "hostname", + "id": "4", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_count", + "size": "10" + }, + "type": "terms" + }, + { + "field": "metric", + "id": "5", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "level", + "id": "6", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "hide": false, + "id": "1", + "type": "count" + }, + { + "field": "value", + "id": "3", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "count/average with triple terms agg - interval auto (backend)", + "type": "timeseries" + } + ], + "title": "Multiple metrics and aggregations", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 62, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 40 + }, + "id": 61, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "0", + "order": "desc", + "orderBy": "1", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "cardinality" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by unique count", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 40 + }, + "id": 69, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "0", + "order": "desc", + "orderBy": "1", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "cardinality" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by unique count (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 70, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "0", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by Term value", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 72, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "0", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by Term value (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 56 + }, + "id": 71, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by Doc Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 56 + }, + "id": 74, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by Doc Count (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 64 + }, + "id": 73, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by avg", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 64 + }, + "id": 75, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by avg (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 72 + }, + "id": 76, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "hostname: {{hostname}}", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by avg with alias", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 72 + }, + "id": 77, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "hostname: {{hostname}}", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by avg with alias (backend)", + "type": "timeseries" + } + ], + "title": "Terms order by simple aggregation", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 63, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 78, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[std_lower]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "std_deviation_bounds_lower": true, + "std_deviation_bounds_upper": false + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by extended stats (std dev lower)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 79, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[std_lower]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "std_deviation_bounds_lower": true, + "std_deviation_bounds_upper": false + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by extended stats (std dev lower) (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 80, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[std_lower]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "std_deviation": true, + "std_deviation_bounds_lower": false, + "std_deviation_bounds_upper": false + }, + "settings": { + "script": "_value * 4", + "sigma": "3" + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by extended stats (std dev)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 81, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[std_lower]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "std_deviation": true, + "std_deviation_bounds_lower": false, + "std_deviation_bounds_upper": false + }, + "settings": { + "script": "_value * 4", + "sigma": "3" + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by extended stats (std dev) (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 57 + }, + "id": 82, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[sum]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1h" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "meta": { + "std_deviation": false, + "std_deviation_bounds_lower": false, + "std_deviation_bounds_upper": false, + "sum": true + }, + "settings": { + "script": "_value * 4", + "sigma": "3" + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by extended stats (sum)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 57 + }, + "id": 84, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[sum]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "1h" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "meta": { + "std_deviation": false, + "std_deviation_bounds_lower": false, + "std_deviation_bounds_upper": false, + "sum": true + }, + "settings": { + "script": "_value * 4", + "sigma": "3" + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by extended stats (sum) (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 65 + }, + "id": 83, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[count]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "10m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "meta": { + "avg": true, + "count": true, + "std_deviation": false, + "std_deviation_bounds_lower": false, + "std_deviation_bounds_upper": false, + "sum": false + }, + "settings": { + "script": "_value * 4", + "sigma": "3" + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by extended stats (count,avg)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 65 + }, + "id": 86, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[count]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "10m" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "meta": { + "avg": true, + "count": true, + "std_deviation": false, + "std_deviation_bounds_lower": false, + "std_deviation_bounds_upper": false, + "sum": false + }, + "settings": { + "script": "_value * 4", + "sigma": "3" + }, + "type": "extended_stats" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by extended stats (count,avg) (backend)", + "type": "timeseries" + } + ], + "title": "Terms order by extended stats", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 64, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 85, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[25.0]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "settings": { + "percents": [ + "25", + "50", + "75", + "95", + "99" + ], + "script": "_value * 2" + }, + "type": "percentiles" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by percentile", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 87, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[25.0]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "float", + "id": "1", + "settings": { + "percents": [ + "25", + "50", + "75", + "95", + "99" + ], + "script": "_value * 2" + }, + "type": "percentiles" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by percentile (backend)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 34 + }, + "id": 88, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[99.0]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "percents": [ + "99" + ] + }, + "type": "percentiles" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Terms order by percentile (99)", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 34 + }, + "id": 90, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "1[99.0]", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "percents": [ + "99" + ] + }, + "type": "percentiles" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "B", + "type": "math" + } + ], + "title": "Terms order by percentile (99) (backend)", + "type": "timeseries" + } + ], + "title": "Terms order by percentile", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 65, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 89, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "New script format", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "script": "_value * 2" + }, + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "alias": "Old script format", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "hide": false, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "script": "_value * 1.5" + }, + "type": "avg" + } + ], + "query": "", + "refId": "B", + "timeField": "@timestamp" + } + ], + "title": "Old & new script format", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 11 + }, + "id": 91, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "New script format", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "script": "_value * 2" + }, + "type": "avg" + } + ], + "query": "", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "alias": "Old script format", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "hide": false, + "metrics": [ + { + "field": "value", + "id": "1", + "settings": { + "script": "_value * 1.5" + }, + "type": "avg" + } + ], + "query": "", + "refId": "B", + "timeField": "@timestamp" + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "0", + "hide": false, + "refId": "C", + "type": "math" + } + ], + "title": "Old & new script format (backend)", + "type": "timeseries" + } + ], + "title": "Inline scripts", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 66, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 92, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "size": "500" + }, + "type": "raw_document" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Raw documents in table", + "transformations": [ + { + "id": "extractFields", + "options": { + "format": "json", + "replace": true, + "source": "A" + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 36 + }, + "id": 93, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "size": "10" + }, + "type": "raw_data" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Raw data", + "transformations": [], + "type": "table" + } + ], + "title": "Raw data and documents", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 67, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 95, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "limit": "10" + }, + "type": "logs" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Logs", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 29 + }, + "id": 94, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "limit": "10" + }, + "type": "logs" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Logs", + "type": "logs" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 37 + }, + "id": 96, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "settings": { + "limit": "10" + }, + "type": "logs" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Logs", + "type": "table" + } + ], + "title": "Logs", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "gdev", + "elasticsearch", + "datasource-test" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Datasource tests - Elasticsearch migration", + "uid": "es_migration", + "version": 1, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_simple.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_simple.json new file mode 100644 index 00000000000..3a95e86e807 --- /dev/null +++ b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_simple.json @@ -0,0 +1,1128 @@ +{ + "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, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "2", + "settings": { + "min_doc_count": "1", + "order": "asc", + "orderBy": "1", + "size": "5" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "3", + "settings": { + "interval": "auto", + "min_doc_count": "0", + "timeZone": "utc", + "trimEdges": "0" + }, + "type": "date_histogram" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "field": "value", + "id": "1", + "type": "max" + } + ], + "query": "*", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Top 5 servers", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "bucketAggs": [ + { + "field": "metric", + "id": "3", + "settings": { + "min_doc_count": 1, + "order": "asc", + "orderBy": "1", + "size": "5" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "dsType": "elasticsearch", + "metrics": [ + { + "field": "value", + "id": "1", + "type": "avg" + } + ], + "query": "metric:cpu", + "refId": "A", + "target": "", + "timeField": "@timestamp" + }, + { + "alias": "", + "bucketAggs": [ + { + "field": "metric", + "id": "3", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + }, + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto" + }, + "type": "date_histogram" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "hide": false, + "metrics": [ + { + "field": "float", + "id": "1", + "type": "avg" + } + ], + "query": "metric:latency", + "refId": "B", + "timeField": "@timestamp" + } + ], + "title": "Average metrics", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "{{metric}}", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "5m", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "dsType": "elasticsearch", + "metrics": [ + { + "field": "value", + "id": "1", + "meta": {}, + "settings": { + "percents": [ + 25, + 50, + 75, + 95, + 99 + ] + }, + "type": "percentiles" + } + ], + "query": "metric:cpu", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Percentiles & metric filter", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "{{metric}}", + "bucketAggs": [ + { + "field": "@timestamp", + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "dsType": "elasticsearch", + "metrics": [ + { + "field": "value", + "id": "1", + "meta": { + "std_deviation_bounds_lower": true, + "std_deviation_bounds_upper": true + }, + "settings": {}, + "type": "extended_stats" + } + ], + "query": "metric:cpu", + "refId": "A", + "target": "", + "timeField": "@timestamp" + } + ], + "title": "Standard dev", + "type": "timeseries" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 5, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "hostname", + "id": "2", + "settings": { + "min_doc_count": 1, + "order": "asc", + "orderBy": "_term", + "size": "0" + }, + "type": "terms" + }, + { + "field": "level", + "id": "5", + "settings": { + "min_doc_count": "1", + "order": "desc", + "orderBy": "_term", + "size": "10" + }, + "type": "terms" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "dsType": "elasticsearch", + "metrics": [ + { + "field": "value", + "id": "1", + "meta": {}, + "settings": {}, + "type": "avg" + }, + { + "field": "value", + "id": "3", + "meta": {}, + "settings": {}, + "type": "max" + }, + { + "field": "value", + "id": "4", + "meta": {}, + "settings": {}, + "type": "sum" + } + ], + "query": "", + "refId": "B", + "timeField": "@timestamp" + } + ], + "title": "ES metrics", + "type": "table" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 10, + "options": { + "controls": { + "mouseWheelZoom": true, + "showAttribution": true, + "showDebug": false, + "showMeasure": false, + "showScale": false, + "showZoom": true + }, + "layers": [ + { + "config": { + "showLegend": true, + "style": { + "color": { + "fixed": "dark-green" + }, + "opacity": 0.4, + "rotation": { + "fixed": 0, + "max": 360, + "min": -360, + "mode": "mod" + }, + "size": { + "fixed": 5, + "max": 15, + "min": 2 + }, + "symbol": { + "fixed": "img/icons/marker/circle.svg", + "mode": "fixed" + }, + "textConfig": { + "fontSize": 12, + "offsetX": 0, + "offsetY": 0, + "textAlign": "center", + "textBaseline": "middle" + } + } + }, + "location": { + "mode": "auto" + }, + "name": "Layer 1", + "tooltip": true, + "type": "markers" + } + ], + "tooltip": { + "mode": "details" + }, + "view": { + "allLayers": true, + "id": "zero", + "lat": 0, + "lon": 0, + "zoom": 1 + } + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [ + { + "field": "location", + "id": "2", + "settings": { + "precision": "3" + }, + "type": "geohash_grid" + } + ], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "metrics": [ + { + "id": "1", + "type": "count" + } + ], + "query": "", + "refId": "A", + "timeField": "@timestamp" + } + ], + "title": "Location with count in Geomap", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": {}, + "renameByName": { + "location": "geohash" + } + } + } + ], + "type": "geomap" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 33 + }, + "id": 6, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "dsType": "elasticsearch", + "metrics": [ + { + "id": "1", + "settings": { + "limit": "500" + }, + "type": "logs" + } + ], + "query": "", + "refId": "B", + "timeField": "@timestamp" + } + ], + "title": "Logs", + "transformations": [], + "type": "logs" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 33 + }, + "id": 9, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": false, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "dsType": "elasticsearch", + "metrics": [ + { + "id": "1", + "settings": { + "limit": "500" + }, + "type": "logs" + } + ], + "query": "", + "refId": "B", + "timeField": "@timestamp" + } + ], + "title": "Logs reordered", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": {}, + "indexByName": { + "@timestamp": 0, + "_id": 3, + "_index": 4, + "_source": 5, + "_type": 6, + "counter": 7, + "description": 8, + "float": 9, + "highlight": 10, + "hostname": 11, + "label": 12, + "level": 1, + "line": 2, + "location": 13, + "metric": 14, + "shapes": 15, + "sort": 16, + "value": 17 + }, + "renameByName": {} + } + } + ], + "type": "logs" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 8, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "dsType": "elasticsearch", + "metrics": [ + { + "id": "1", + "settings": { + "size": "10" + }, + "type": "raw_data" + } + ], + "query": "", + "refId": "B", + "timeField": "@timestamp" + } + ], + "title": "Raw data in table", + "transformations": [], + "type": "table" + }, + { + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 7, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "alias": "", + "bucketAggs": [], + "datasource": { + "type": "elasticsearch", + "uid": "gdev-elasticsearch" + }, + "dsType": "elasticsearch", + "metrics": [ + { + "id": "1", + "settings": { + "size": "500" + }, + "type": "raw_document" + } + ], + "query": "", + "refId": "B", + "timeField": "@timestamp" + } + ], + "title": "Raw document with json transformation in table", + "transformations": [ + { + "id": "extractFields", + "options": { + "format": "json", + "replace": true, + "source": "B" + } + } + ], + "type": "table" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "gdev", + "elasticsearch", + "datasource-test" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Datasource tests - Elasticsearch simple", + "uid": "es_simple", + "version": 1, + "weekStart": "" +} diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_v7.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_v7.json deleted file mode 100644 index 02b3ced02f6..00000000000 --- a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_v7.json +++ /dev/null @@ -1,736 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": false, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "limit": 100, - "name": "Annotations & Alerts", - "showIn": 0, - "type": "dashboard" - }, - { - "datasource": "gdev-elasticsearch-v7-logs", - "enable": false, - "iconColor": "rgba(255, 96, 96, 1)", - "limit": 100, - "name": "test", - "query": "", - "showIn": 0, - "textField": "description", - "type": "alert" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "iteration": 1591027717495, - "links": [ - { - "asDropdown": true, - "icon": "external link", - "tags": ["gdev", "elasticsearch", "datasource-test"], - "title": "Dashboards", - "type": "dashboards" - } - ], - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "gdev-elasticsearch-v7-metrics", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "id": 1, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "field": "@hostname", - "id": "3", - "settings": { - "min_doc_count": 1, - "order": "asc", - "orderBy": "1", - "size": "5" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "dsType": "elasticsearch", - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "max" - } - ], - "query": "*", - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Top 5 servers", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "Count": "#6ED0E0" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "gdev-elasticsearch-v7-metrics", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 6, - "w": 12, - "x": 0, - "y": 7 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Count", - "lines": false, - "yaxis": 2, - "zindex": -1 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "{{metric}}", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "dsType": "elasticsearch", - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": { - "percents": [25, 50, 75, 95, 99] - }, - "type": "percentiles" - } - ], - "query": "@metric:cpu", - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Percentiles & Metric filter", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "Count": "#6ED0E0" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "gdev-elasticsearch-v7-metrics", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 6, - "w": 12, - "x": 12, - "y": 7 - }, - "hiddenSeries": false, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Count", - "lines": false, - "yaxis": 2, - "zindex": -1 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "alias": "{{metric}}", - "bucketAggs": [ - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "dsType": "elasticsearch", - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": { - "std_deviation_bounds_lower": true, - "std_deviation_bounds_upper": true - }, - "settings": {}, - "type": "extended_stats" - } - ], - "query": "@metric:cpu", - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Standard dev", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "columns": [ - { - "text": "@hostname", - "value": "@hostname" - }, - { - "text": "Average", - "value": "Average" - }, - { - "text": "Max", - "value": "Max" - }, - { - "text": "Sum", - "value": "Sum" - } - ], - "datasource": "gdev-elasticsearch-v7-metrics", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fontSize": "100%", - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 13 - }, - "id": 6, - "links": [], - "pageSize": null, - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": true - }, - "styles": [ - { - "align": "auto", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "@timestamp", - "type": "date" - }, - { - "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, - "pattern": "/.*/", - "thresholds": [], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "bucketAggs": [ - { - "field": "@hostname", - "id": "2", - "settings": { - "min_doc_count": 1, - "order": "asc", - "orderBy": "_term", - "size": "0" - }, - "type": "terms" - } - ], - "dsType": "elasticsearch", - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - }, - { - "field": "@value", - "id": "3", - "meta": {}, - "settings": {}, - "type": "max" - }, - { - "field": "@value", - "id": "4", - "meta": {}, - "settings": {}, - "type": "sum" - } - ], - "refId": "B", - "timeField": "@timestamp" - } - ], - "title": "ES Metrics", - "transform": "table", - "type": "table-old" - }, - { - "columns": [ - { - "text": "@timestamp", - "value": "@timestamp" - }, - { - "text": "@message", - "value": "@message" - }, - { - "text": "tags", - "value": "tags" - }, - { - "text": "description", - "value": "description" - } - ], - "datasource": "gdev-elasticsearch-v7-logs", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fontSize": "100%", - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 20 - }, - "id": 5, - "links": [], - "pageSize": null, - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": true - }, - "styles": [ - { - "align": "auto", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "@timestamp", - "type": "date" - } - ], - "targets": [ - { - "bucketAggs": [], - "dsType": "elasticsearch", - "metrics": [ - { - "field": "select field", - "id": "1", - "meta": {}, - "settings": { - "size": 500 - }, - "type": "raw_document" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "title": "ES Log query", - "transform": "json", - "type": "table-old" - }, - { - "circleMaxSize": 30, - "circleMinSize": 2, - "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], - "datasource": "gdev-elasticsearch-v7-metrics", - "decimals": 0, - "esGeoPoint": "@location", - "esMetric": "Average", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "gridPos": { - "h": 12, - "w": 24, - "x": 0, - "y": 27 - }, - "hideEmpty": false, - "hideZero": false, - "id": 8, - "initialZoom": "1", - "links": [], - "locationData": "geohash", - "mapCenter": "(0°, 0°)", - "mapCenterLatitude": 0, - "mapCenterLongitude": 0, - "maxDataPoints": 1, - "mouseWheelZoom": false, - "showLegend": true, - "stickyLabels": false, - "tableQueryOptions": { - "geohashField": "geohash", - "latitudeField": "latitude", - "longitudeField": "longitude", - "metricField": "metric", - "queryType": "geohash" - }, - "targets": [ - { - "bucketAggs": [ - { - "fake": true, - "field": "@location", - "id": "3", - "settings": { - "precision": 2 - }, - "type": "geohash_grid" - } - ], - "metrics": [ - { - "field": "@value", - "id": "1", - "meta": {}, - "settings": {}, - "type": "avg" - } - ], - "refId": "A", - "target": "", - "timeField": "@timestamp" - } - ], - "thresholds": "0,10", - "title": "World map panel", - "type": "grafana-worldmap-panel", - "unitPlural": "", - "unitSingle": "", - "valueName": "total" - } - ], - "schemaVersion": 25, - "style": "dark", - "tags": ["elasticsearch", "gdev", "datasource-test"], - "templating": { - "list": [ - { - "datasource": "gdev-elasticsearch-v7-metrics", - "filters": [], - "hide": 0, - "label": "", - "name": "Filters", - "skipUrlSync": false, - "type": "adhoc" - } - ] - }, - "time": { - "from": "now-30m", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], - "status": "Stable", - "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Datasource tests - Elasticsearch v7", - "uid": "Y-RvmuRWk", - "version": 1 -} diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_v7_filebeat.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_v7_filebeat.json deleted file mode 100644 index a5003193b11..00000000000 --- a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_v7_filebeat.json +++ /dev/null @@ -1,241 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "iteration": 1591027736516, - "links": [ - { - "asDropdown": true, - "icon": "external link", - "tags": ["gdev", "elasticsearch", "datasource-test"], - "title": "Dashboards", - "type": "dashboards" - } - ], - "panels": [ - { - "aliasColors": { - "error": "red" - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "gdev-elasticsearch-v7-filebeat", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 5, - "w": 24, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": false, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "bucketAggs": [ - { - "fake": true, - "field": "fields.level", - "id": "3", - "settings": { - "min_doc_count": 1, - "order": "desc", - "orderBy": "_term", - "size": "10" - }, - "type": "terms" - }, - { - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "5m", - "min_doc_count": 1, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "field": "select field", - "id": "1", - "type": "count" - } - ], - "query": "fields.app:grafana", - "refId": "A", - "timeField": "@timestamp" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Panel Title", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "datasource": "gdev-elasticsearch-v7-filebeat", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "gridPos": { - "h": 22, - "w": 24, - "x": 0, - "y": 5 - }, - "id": 2, - "links": [], - "options": { - "showLabels": false, - "showTime": true, - "sortOrder": "Descending", - "wrapLogMessage": true - }, - "targets": [ - { - "bucketAggs": [ - { - "$$hashKey": "object:522", - "field": "@timestamp", - "id": "2", - "settings": { - "interval": "auto", - "min_doc_count": 0, - "trimEdges": 0 - }, - "type": "date_histogram" - } - ], - "metrics": [ - { - "$$hashKey": "object:484", - "field": "select field", - "id": "1", - "meta": {}, - "settings": {}, - "type": "logs" - } - ], - "query": "fields.app:grafana", - "refId": "A", - "timeField": "@timestamp" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Panel Title", - "type": "logs" - } - ], - "schemaVersion": 25, - "style": "dark", - "tags": ["elasticsearch", "gdev", "datasource-test"], - "templating": { - "list": [ - { - "datasource": "gdev-elasticsearch-v7-filebeat", - "filters": [], - "hide": 0, - "label": "", - "name": "Filters", - "skipUrlSync": false, - "type": "adhoc" - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], - "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"] - }, - "timezone": "", - "title": "Datasource tests - Elasticsearch v7 Filebeat", - "uid": "M94gguRWz", - "version": 1 -} diff --git a/devenv/dev-dashboards/panel-common/shared_queries.json b/devenv/dev-dashboards/panel-common/shared_queries.json index b29485f4c3f..a4804559089 100644 --- a/devenv/dev-dashboards/panel-common/shared_queries.json +++ b/devenv/dev-dashboards/panel-common/shared_queries.json @@ -3,7 +3,10 @@ "list": [ { "builtIn": 1, - "datasource": "-- Grafana --", + "datasource": { + "type": "datasource", + "uid": "grafana" + }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", @@ -13,17 +16,69 @@ ] }, "editable": true, - "gnetId": null, + "fiscalYearStartMonth": 0, "graphTooltip": 0, "links": [], + "liveNow": false, "panels": [ { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "fill": 0, - "fillGradient": 6, + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 60, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 6, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, "gridPos": { "h": 15, "w": 12, @@ -31,89 +86,79 @@ "y": 0 }, "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", "options": { - "dataLinks": [] + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } }, - "percentage": false, - "pointradius": 2, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, + "pluginVersion": "9.5.0-pre", "targets": [ { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, "refId": "A", "scenarioId": "csv_metric_values", "stringInput": "1,20,90,30,5,0,100" }, { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, "refId": "B", "scenarioId": "csv_metric_values", "stringInput": "1,20,90,30,5,-100,200" }, { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, "refId": "C", "scenarioId": "csv_metric_values", "stringInput": "2.5,3.5,4.5,10.5,20.5,21.5,19.5" } ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, "title": "Raw Data Graph", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } + "type": "timeseries" }, { - "datasource": "-- Dashboard --", + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, "gridPos": { "h": 5, "w": 12, @@ -122,44 +167,59 @@ }, "id": 4, "options": { - "fieldOptions": { - "calcs": ["lastNotNull"], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.5.0-pre", + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "panelId": 2, + "refId": "A" + } + ], + "title": "Last non-null", + "type": "gauge" + }, + { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", "value": 80 } ] - }, - "override": {}, - "values": false + } }, - "orientation": "auto", - "showThresholdLabels": false, - "showThresholdMarkers": true + "overrides": [] }, - "pluginVersion": "6.4.0-pre", - "targets": [ - { - "panelId": 2, - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Last non-null", - "type": "gauge" - }, - { - "datasource": "-- Dashboard --", "gridPos": { "h": 5, "w": 12, @@ -168,63 +228,49 @@ }, "id": 6, "options": { - "fieldOptions": { - "calcs": ["min"], - "defaults": { - "mappings": [], - "max": 100, - "min": 0, - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "override": {}, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "min" + ], + "fields": "", "values": false }, - "orientation": "auto", "showThresholdLabels": false, "showThresholdMarkers": true }, - "pluginVersion": "6.4.0-pre", + "pluginVersion": "9.5.0-pre", "targets": [ { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, "panelId": 2, "refId": "A" } ], - "timeFrom": null, - "timeShift": null, "title": "min", "type": "gauge" }, { - "datasource": "-- Dashboard --", - "gridPos": { - "h": 5, - "w": 12, - "x": 12, - "y": 10 + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" }, - "id": 5, - "options": { - "displayMode": "basic", - "fieldOptions": { - "calcs": ["max"], - "defaults": { - "mappings": [], - "max": 200, - "min": 0, - "thresholds": [ + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 200, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "blue", @@ -235,28 +281,102 @@ "value": 120 } ] - }, - "override": {}, + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 5, + "options": { + "displayMode": "basic", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "vertical", + "reduceOptions": { + "calcs": [ + "max" + ], + "fields": "", "values": false }, - "orientation": "vertical" + "showUnfilled": true, + "valueMode": "color" }, - "pluginVersion": "6.4.0-pre", + "pluginVersion": "9.5.0-pre", "targets": [ { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, "panelId": 2, "refId": "A" } ], - "timeFrom": null, - "timeShift": null, "title": "Max", "type": "bargauge" }, { - "columns": [], - "datasource": "-- Dashboard --", - "fontSize": "100%", + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss" + }, + { + "id": "custom.align" + } + ] + } + ] + }, "gridPos": { "h": 10, "w": 24, @@ -264,47 +384,49 @@ "y": 15 }, "id": 8, - "options": {}, - "pageSize": null, - "showHeader": true, - "sort": { - "col": 0, - "desc": true - }, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "date" + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false }, - { - "alias": "", - "colorMode": null, - "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], - "decimals": 2, - "pattern": "/.*/", - "thresholds": [], - "type": "number", - "unit": "short" - } - ], + "showHeader": true, + "showRowNums": false + }, + "pluginVersion": "9.5.0-pre", "targets": [ { + "datasource": { + "type": "datasource", + "uid": "-- Dashboard --" + }, "panelId": 2, "refId": "A" } ], - "timeFrom": null, - "timeShift": null, - "title": "Panel Title", - "transform": "timeseries_to_columns", + "title": "The data from graph above with seriesToColumns transform", + "transformations": [ + { + "id": "seriesToColumns", + "options": { + "reducers": [] + } + } + ], "type": "table" } ], - "schemaVersion": 19, + "refresh": "", + "schemaVersion": 38, "style": "dark", - "tags": ["gdev", "datasource-test"], + "tags": [ + "gdev", + "datasource-test" + ], "templating": { "list": [] }, @@ -313,10 +435,22 @@ "to": "now" }, "timepicker": { - "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] }, "timezone": "", "title": "Datasource tests - Shared Queries", "uid": "ZqZnVvFZz", - "version": 10 -} + "version": 8, + "weekStart": "" +} \ No newline at end of file diff --git a/devenv/docker/blocks/elastic/data/data.js b/devenv/docker/blocks/elastic/data/data.js index 50a9eea1488..efff9370005 100644 --- a/devenv/docker/blocks/elastic/data/data.js +++ b/devenv/docker/blocks/elastic/data/data.js @@ -81,6 +81,18 @@ async function elasticSetupIndexTemplate() { }, shapes: { type: 'nested', + }, + hostname: { + type: 'keyword', + }, + value: { + type: 'integer', + }, + metric: { + type: 'keyword', + }, + description: { + type: 'text', } }, }, @@ -119,6 +131,10 @@ function getRandomLogItem(counter, timestamp) { {"type": "triangle"}, {"type": "square"}, ], + hostname: chooseRandomElement(['hostname1', 'hostname2', 'hostname3', 'hostname4', 'hostname5', 'hostname6']), + value: counter, + metric: chooseRandomElement(['cpu', 'memory', 'latency']), + description: "this is description" }; } diff --git a/devenv/jsonnet/dev-dashboards.libsonnet b/devenv/jsonnet/dev-dashboards.libsonnet index ff4d81e4622..78eb25255c1 100644 --- a/devenv/jsonnet/dev-dashboards.libsonnet +++ b/devenv/jsonnet/dev-dashboards.libsonnet @@ -163,21 +163,21 @@ local dashboard = grafana.dashboard; id: 0, } }, - dashboard.new('elasticsearch_compare', import '../dev-dashboards/datasource-elasticsearch/elasticsearch_compare.json') + + dashboard.new('elasticsearch_complex', import '../dev-dashboards/datasource-elasticsearch/elasticsearch_complex.json') + resource.addMetadata('folder', 'dev-dashboards') + { spec+: { id: 0, } }, - dashboard.new('elasticsearch_v7', import '../dev-dashboards/datasource-elasticsearch/elasticsearch_v7.json') + + dashboard.new('elasticsearch_migration', import '../dev-dashboards/datasource-elasticsearch/elasticsearch_migration.json') + resource.addMetadata('folder', 'dev-dashboards') + { spec+: { id: 0, } }, - dashboard.new('elasticsearch_v7_filebeat', import '../dev-dashboards/datasource-elasticsearch/elasticsearch_v7_filebeat.json') + + dashboard.new('elasticsearch_simple', import '../dev-dashboards/datasource-elasticsearch/elasticsearch_simple.json') + resource.addMetadata('folder', 'dev-dashboards') + { spec+: { diff --git a/docs/sources/administration/data-source-management/index.md b/docs/sources/administration/data-source-management/index.md index c51e53d282b..aff513500ea 100644 --- a/docs/sources/administration/data-source-management/index.md +++ b/docs/sources/administration/data-source-management/index.md @@ -46,7 +46,8 @@ By default, data sources in an organization can be queried by any user in that o You can assign data source permissions to users, teams, and roles which will allow access to query or edit the data source. -1. Navigate to **Administration > Data sources**. +1. Click **Connections** in the left-side menu. +1. Under Your connections, click **Data sources**. 1. Select the data source to which you want to assign permissions. 1. On the Permissions tab, click **Add a permission**. 1. Select **User**, **Team**, or **Role**. @@ -58,7 +59,8 @@ You can assign data source permissions to users, teams, and roles which will all ### Edit data source permissions for users, teams, or roles -1. Navigate to **Administration > Data sources**. +1. Click **Connections** in the left-side menu. +1. Under Your connections, click **Data sources**. 1. Select the data source for which you want to edit permissions. 1. On the Permissions tab, find the user, team, or role permission you want to update. 1. Select a different option in the **Permission** dropdown. @@ -67,7 +69,8 @@ You can assign data source permissions to users, teams, and roles which will all ### Remove data source permissions for users, teams, or roles -1. Navigate to **Administration > Data sources**. +1. Click **Connections** in the left-side menu. +1. Under Your connections, click **Data sources**. 1. Select the data source from which you want to remove permissions. 1. On the Permissions tab, find the user, team, or role permission you want to remove. 1. Click the **X** next to the permission. @@ -122,9 +125,10 @@ You must be an Org admin or Grafana admin to enable query caching for a data sou By default, data source queries are not cached. To enable query caching for a single data source: -1. On the left-side menu, click **Administration > Data sources**. +1. Click **Connections** in the left-side menu. +1. Under Your Connections, click **Data sources**. 1. In the data source list, click the data source that you want to turn on caching for. -1. Open the Cache tab. +1. Go to the Cache tab. 1. Click **Enable**. 1. (Optional) Choose custom TTLs for the data source's queries and resources caching. If you skip this step, then Grafana uses the default TTL. @@ -140,9 +144,10 @@ To configure global settings for query caching, refer to the [Query caching sect To disable query caching for a single data source: -1. On the left-side menu, click **Administration > Data sources**. +1. Click **Connections** in the left-side menu. +1. Under Your Connections, click **Data sources**. 1. In the data source list, click the data source that you want to turn off caching for. -1. In the Cache tab, click **Disable**. +1. On the Cache tab, click **Disable**. To disable query caching for an entire Grafana instance, set the `enabled` flag to `false` in the [Query caching section of Enterprise Configuration]({{< relref "../../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}). You will no longer see the Cache tab on any data sources, and no data source queries will be cached. @@ -152,7 +157,8 @@ If you experience performance issues or repeated queries become slower to execut > **Note:** This action impacts all cache-enabled data sources. If you are using Memcached, the system clears all data from the Memcached instance. -1. On the left-side menu, click **Administration > Data sources**. +1. Click **Connections** in the left-side menu. +1. Under Your Connections, click **Data sources**. 1. In the data source list, click the data source that you want to clear the cache for. 1. In the Cache tab, click **Clear cache**. diff --git a/docs/sources/administration/plugin-management/index.md b/docs/sources/administration/plugin-management/index.md index 6ca96b2baa3..6e3eff53e43 100644 --- a/docs/sources/administration/plugin-management/index.md +++ b/docs/sources/administration/plugin-management/index.md @@ -77,7 +77,7 @@ Before following the steps below, make sure you are logged in as a Grafana admin -- Administrators can find the Plugin catalog at **Configuration > Plugins**. +- Administrators can find the Plugin catalog at **Administration > Plugins**. ### Browse plugins diff --git a/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md b/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md index 33c22c8a913..5176af499f4 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md @@ -207,3 +207,4 @@ The following list contains role-based access control scopes. | `settings:*` | Restrict an action to a subset of settings. For example, `settings:*` matches all settings, `settings:auth.saml:*` matches all SAML settings, and `settings:auth.saml:enabled` matches the enable property on the SAML settings. | | `teams:*`
`teams:id:*` | Restrict an action to a set of teams from an organization. For example, `teams:*` matches any team and `teams:id:1` matches the team whose ID is `1`. | | `users:*`
`users:id:*` | Restrict an action to a set of users from an organization. For example, `users:*` matches any user and `users:id:1` matches the user whose ID is `1`. | +| `n/a` | `n/a` means not applicable. If an action has `n/a` specified for the scope, then the action does not require a scope. For example, the `teams:create` action does not require a scope and allows users to create teams. | diff --git a/docs/sources/alerting/manage-notifications/template-notifications/using-go-templating-language.md b/docs/sources/alerting/manage-notifications/template-notifications/using-go-templating-language.md index b6529d4f7b2..a1b5267c338 100644 --- a/docs/sources/alerting/manage-notifications/template-notifications/using-go-templating-language.md +++ b/docs/sources/alerting/manage-notifications/template-notifications/using-go-templating-language.md @@ -71,6 +71,16 @@ The name of the annotation is {{ .Name }}, and the value is {{ .Value }} {{ end }} ``` +## The index function + +To print a specific annotation or label use the `index` function. + +``` +{{ range .Alerts }} +The name of the alert is {{ index .Labels "alertname" }} +{{ end }} +``` + ## If statements You can use if statements in templates. For example, to print `There are no alerts` if there are no alerts in `.Alerts` you would write the following: diff --git a/docs/sources/dashboards/build-dashboards/manage-library-panels/index.md b/docs/sources/dashboards/build-dashboards/manage-library-panels/index.md index ab1c8e1f06f..56d67efafca 100644 --- a/docs/sources/dashboards/build-dashboards/manage-library-panels/index.md +++ b/docs/sources/dashboards/build-dashboards/manage-library-panels/index.md @@ -25,8 +25,8 @@ When you create a library panel, the panel on the source dashboard is converted 1. Open a panel in edit mode. 1. In the panel display options, click the down arrow option to bring changes to the visualization. - {{< figure src="/static/img/docs/library-panels/create-lib-panel-from-edit-8-0.png" class="docs-image--no-shadow" max-width= "800px" caption="Screenshot of the edit panel" >}} -1. Click the **Library panels** option, and then click **Create library panel** to open the create dialog. + {{< figure src="/media/docs/grafana/panels-visualizations/screenshot-create-lib-panel-from-edit-9-5.png" class="docs-image--no-shadow" max-width= "800px" >}} +1. Click **Library panels**, and then click **+ Create library panel** to open the create dialog. 1. In **Library panel name**, enter the name. 1. In **Save in folder**, select the folder to save the library panel. 1. Click **Create library panel** to save your changes. @@ -34,14 +34,16 @@ When you create a library panel, the panel on the source dashboard is converted Once created, you can modify the library panel using any dashboard on which it appears. After you save the changes, all instances of the library panel reflect these modifications. -{{< figure src="/static/img/docs/library-panels/create-from-more-8-0.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the edit panel" >}} +You can also create a library panel directly from the edit menu of any panel. + +{{< figure src="/media/docs/grafana/panels-visualizations/screenshot-create-from-more-9-5.png" class="docs-image--no-shadow" max-width= "900px" >}} ## Add a library panel to a dashboard Add a Grafana library panel to a dashboard when you want to provide visualizations to other dashboard users. 1. Click **Dashboards** in the left-side menu. -1. Click **New** and select **New Dashboard**. +1. Click **New** and select **New Dashboard** in the dropdown. 1. On the empty dashboard, click **+ Import library panel**. You will see a list of your library panels. @@ -60,6 +62,7 @@ Unlink a library panel when you want to make a change to the panel and not affec 1. Hover over any part of the panel to display the actions menu on the top right corner. 1. Click the menu and select **Edit**. 1. Click **Unlink** on the top right corner of the page. +1. Click **Yes, unlink**. ## View a list of library panels @@ -69,7 +72,7 @@ You can view a list of available library panels and search for a library panel. 1. Click **Library panels**. You can see a list of previously defined library panels. - {{< figure src="/static/img/docs/library-panels/library-panel-list-8-0.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the edit panel" >}} + {{< figure src="/media/docs/grafana/panels-visualizations/screenshot-library-panel-list-9-5.png" class="docs-image--no-shadow" max-width= "900px" >}} 1. Search for a specific library panel if you know its name. diff --git a/docs/sources/dashboards/build-dashboards/manage-version-history/index.md b/docs/sources/dashboards/build-dashboards/manage-version-history/index.md index 8ab7439f047..c2b8e3fa286 100644 --- a/docs/sources/dashboards/build-dashboards/manage-version-history/index.md +++ b/docs/sources/dashboards/build-dashboards/manage-version-history/index.md @@ -17,7 +17,7 @@ weight: 400 Whenever you save a version of your dashboard, a copy of that version is saved so that previous versions of your dashboard are never lost. A list of these versions is available by entering the dashboard settings and then selecting "Versions" in the left side menu. - +![Dashboards versions list](/media/docs/grafana/dashboards/screenshot-dashboard-versions-list.png) The dashboard version history feature lets you compare and restore to previously saved dashboard versions. @@ -25,20 +25,18 @@ The dashboard version history feature lets you compare and restore to previously To compare two dashboard versions, select the two versions from the list that you wish to compare. Once selected, the "Compare versions" button will become clickable. Click the button to view the diff between the two versions. - +![Dashboard versions selected](/media/docs/grafana/dashboards/screenshot-dashboard-versions-select.png) Upon clicking the button, you'll be brought to the diff view. By default, you'll see a textual summary of the changes, like in the image below. - +![Dashboards versions diff](/media/docs/grafana/dashboards/screenshot-dashboard-versions-diff-basic.png) -If you want to view the diff of the raw JSON that represents your dashboard, you can do that as well by clicking the "View JSON Diff" button at the bottom. - -If you want to restore to the version you are diffing against, you can do so by clicking the "Restore to version \" button in the top right. +If you want to view the diff of the raw JSON that represents your dashboard, you can do that as well by clicking the expand icon for the View JSON Diff section at the bottom. ## Restoring to a previously saved dashboard version -If you need to restore to a previously saved dashboard version, you can do so by either clicking the "Restore" button on the right of a row in the dashboard version list, or by clicking the "Restore to version \" button appearing in the diff view. Clicking the button will bring up the following popup prompting you to confirm the restoration. +If you need to restore to a previously saved dashboard version, you can do so by either clicking the "Restore" button on the right of a row in the dashboard version list, or by clicking the **Restore to version \** button appearing in the diff view. Clicking the button will bring up the following popup prompting you to confirm the restoration. - +![Restore dashboard version](/media/docs/grafana/dashboards/screenshot-dashboard-versions-restore.png) After restoring to a previous version, a new version will be created containing the same exact data as the previous version, only with a different version number. This is indicated in the "Notes column" for the row in the new dashboard version. This is done simply to ensure your previous dashboard versions are not affected by the change. diff --git a/docs/sources/dashboards/create-manage-playlists/index.md b/docs/sources/dashboards/create-manage-playlists/index.md index e3c12996a26..9be403a304d 100644 --- a/docs/sources/dashboards/create-manage-playlists/index.md +++ b/docs/sources/dashboards/create-manage-playlists/index.md @@ -26,21 +26,22 @@ Use the information in this section to access existing playlists. Start and cont ### Access a playlist -1. Hover your cursor over Grafana’s side menu. -1. Click **Playlists**. You will see a list of existing playlists. +1. Click **Dashboards** in the left-side menu. +1. Click **Playlists** to see a list of existing playlists. ### Start a playlist -You can start a playlist in five different view modes. View mode determine how the menus and navigation bar appear on the dashboards. +You can start a playlist in five different view modes. View modes determine how the menus and navigation bar appear on the dashboards. By default, each dashboard is displayed for the amount of time entered in the Interval field, which you set when you create or edit a playlist. After you start a playlist, you can control it with the navbar at the top of the page. -1. [Access](#access-playlist) the playlist page to see a list of existing playlists. -1. Find the playlist you want to start, then click **Start playlist**. The start playlist dialog opens. -1. Select one of the five playlist modes available based on the information in the following table. -1. Click **Start **. +1. Click **Dashboards** in the left-side menu. +1. Click **Playlists** to see a list of existing playlists. +1. Find the playlist you want to start, then click **Start playlist**. +1. In the modal that opens, select one of the five playlist modes available, based on the information in the table below. +1. Click **Start \**. -The playlist displays each dashboard for the time specified in the `Interval` field, set when creating or editing a playlist. Once a playlist starts, you can [control](#control-a-playlist) it using the navbar at the top of your screen. +The playlist displays each dashboard for the time specified in the **Interval** field, set when creating or editing a playlist. Once a playlist starts, you can [control](#control-a-playlist) it using the navbar at the top of your screen. | Mode | Description | | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -67,7 +68,9 @@ You can control a playlist in **Normal** or **TV** mode after it's started, usin You can create a playlist to present dashboards in a sequence, with a set order and time interval between dashboards. -1. In the playlist page, click **New playlist**. The New playlist page opens. +1. Click **Dashboards** in the left-side menu. +1. Click **Playlists** to see a list of existing playlists. +1. Click **New playlist**. The New playlist page opens. 1. In the **Name** text box, enter a descriptive name. 1. In the **Interval** text box, enter a time interval. Grafana displays a particular dashboard for the interval of time specified here before moving on to the next dashboard. 1. In Dashboards, add existing dashboards to the playlist using **Add by title** and **Add by tag** drop-down options. The dashboards you add are listed in a sequential order. @@ -82,8 +85,8 @@ You can create a playlist to present dashboards in a sequence, with a set order You can save a playlist and add it to your **Playlists** page, where you can start it. Be sure that all the dashboards you want to appear in your playlist are added when creating or editing the playlist before saving it. -1. To access the Playlist feature, hover your cursor over Grafana's side menu. -1. Click **Playlists**. +1. Click **Dashboards** in the left-side menu. +1. Click **Playlists** to see a list of existing playlists. 1. Click on the playlist. 1. Edit the playlist. 1. Ensure that your playlist has a **Name**, **Interval**, and at least one **Dashboard** added to it. @@ -95,36 +98,47 @@ You can edit a playlist by updating its name, interval time, and by adding, remo ### Edit a playlist -1. In the playlist page, click **Edit playlist**. The Edit playlist page opens. +1. Click **Dashboards** in the left-side menu. +1. Click **Playlists** to see a list of existing playlists. +1. Find the playlist you want to update and click **Edit playlist**. 1. Update the name and time interval, then add or remove dashboards from the playlist using instructions in [Create a playlist](#create-a-playlist). 1. Click **Save** to save your changes. ### Delete a playlist -1. Click **Playlists**. -1. Next to the Playlist you want to delete, click **Remove[x]**. +1. Click **Dashboards** in the left-side menu. +1. Click **Playlists** to see a list of existing playlists. +1. Find the playlist you want to remove. +1. Click **Delete playlist**. ### Rearrange dashboard order -1. Next to the dashboard you want to move, click the up or down arrow. +1. Click **Dashboards** in the left-side menu. +1. Click **Playlists** to see a list of existing playlists. +1. Find the playlist you want to update and click **Edit playlist**. +1. Click and drag the dashboards into your desired order. 1. Click **Save** to save your changes. ### Remove a dashboard -1. Click **Remove[x]** to remove a dashboard from the playlist. +1. Click **Dashboards** in the left-side menu. +1. Click **Playlists** to see a list of existing playlists. +1. Find the playlist you want to update and click **Edit playlist**. +1. Click **\[x\]** on the name of the dashboard you want to remove from the playlist. 1. Click **Save** to save your changes. ## Share a playlist in a view mode You can share a playlist by copying the link address on the view mode you prefer, and pasting the URL to your destination. -1. From the Dashboards submenu, click **Playlists**. -1. Next to the playlist you want to share, click **Start playlist**. -1. In the dropdown, right click the view mode you prefer. -1. Click **Copy Link Address** to copy the URL to your clipboard. +1. Click **Dashboards** in the left-side menu. +1. Click **Playlists** to see a list of existing playlists. +1. Click the share icon of the playlist you want to share. +1. Select the view mode you prefer. +1. Click **Copy** next to the Link URL to copy it to your clipboard. - Example: The URL for the first playlist on the Grafana Play site in Kiosk mode will look like this: + For example, the URL for the first playlist on the Grafana Play site in Kiosk mode will look like this: - [https://play.grafana.org/playlists/play/1?kiosk](https://play.grafana.org/playlists/play/1?kiosk). + [https://play.grafana.org/playlists/play/1?kiosk](https://play.grafana.org/playlists/play/1?kiosk). -1. Paste the URL to your destination. +1. Paste the URL to your destination. diff --git a/docs/sources/dashboards/manage-dashboards/index.md b/docs/sources/dashboards/manage-dashboards/index.md index 2a18a59b3cd..fb16052b0ef 100644 --- a/docs/sources/dashboards/manage-dashboards/index.md +++ b/docs/sources/dashboards/manage-dashboards/index.md @@ -48,14 +48,16 @@ Folders help you organize and group dashboards, which is useful when you have ma **To create a dashboard folder:** -1. Sign in to Grafana and on the side menu, click **Dashboards > New folder**. +1. Sign in to Grafana. +1. Click **Dashboards** in the left-side menu. +1. On the Dashboards page, click **New** and select **New folder** in the dropdown. 1. Enter a unique name and click **Create**. When you save a dashboard, you can either select a folder for the dashboard to be saved in or create a new folder. ## Manage dashboards -On the **Manage dashboards and folders** page, you can: +On the Dashboards page, you can: - create a folder - create a dashboard @@ -65,17 +67,17 @@ On the **Manage dashboards and folders** page, you can: ### Dashboard folder page -You can complete the following tasks on the **Dashboard Folder** page: +You can complete the following tasks on a dashboard folder page: - Move or delete dashboards in a folder -- Rename a folder (available under the **Settings** tab) +- Rename a folder (available on the Settings tab) - Assign permissions to folders (which are inherited by the dashboards in the folder) -To navigate to the dashboard folder page, click the cog appears when you hover over a folder in the dashboard search result list or the **Manage dashboards and folders** page. +To navigate to the dashboard folder page, hover over the name of the folder and click **Go to folder** in the dashboard search result list or on the Dashboards page. ### Dashboard permissions -You can assign permissions to a folder. Any permissions you assign are inherited by the dashboards in the folder. An Access Control List (ACL) is used where **Organization Role**, **Team** and a **User** can be assigned permissions. +You can assign permissions to a folder. Any permissions you assign are inherited by the dashboards in the folder. An Access Control List (ACL) is used where **Organization Role**, **Team**, and a **User** can be assigned permissions. For more information about dashboard permissions, refer to [Dashboard permissions]({{< relref "../../administration/roles-and-permissions/#dashboard-permissions" >}}). @@ -87,10 +89,11 @@ You can use the Grafana UI or the [HTTP API]({{< relref "../../developers/http_a The dashboard export action creates a Grafana JSON file that contains everything you need, including layout, variables, styles, data sources, queries, and so on, so that you can later import the dashboard. +1. Click **Dashboards** in the left-side menu. 1. Open the dashboard you want to export. -2. Click the **Share** icon. -3. Click **Export**. -4. Click **Save to file**. +1. Click the **Share** icon. +1. Click **Export**. +1. Click **Save to file**. Grafana downloads a JSON file to your local machine. @@ -102,7 +105,8 @@ A template variable of the type `Constant` will automatically be hidden in the d ### Import a dashboard -1. Click **Dashboards > Import** in the side menu. +1. Click **Dashboards** in the left-side menu. +1. Click **New** and select **Import** in the dropdown menu. 1. Perform one of the following steps: - Upload a dashboard JSON file @@ -118,7 +122,7 @@ The import process enables you to change the name of the dashboard, pick the dat Find dashboards for common server applications at [Grafana.com/dashboards](https://grafana.com/dashboards). -{{< figure src="/static/img/docs/v50/gcom_dashboard_list.png" max-width="700px" >}} +{{< figure src="/media/docs/grafana/dashboards/screenshot-gcom-dashboards.png" >}} ## Troubleshoot dashboards diff --git a/docs/sources/dashboards/share-dashboards-panels/index.md b/docs/sources/dashboards/share-dashboards-panels/index.md index 868a1fe6d9a..3c677ad6226 100644 --- a/docs/sources/dashboards/share-dashboards-panels/index.md +++ b/docs/sources/dashboards/share-dashboards-panels/index.md @@ -52,10 +52,11 @@ You can share a dashboard as a direct link or as a snapshot. You can also export > **Note:** If you change a dashboard, ensure that you save the changes before sharing. -1. Navigate to the home page of your Grafana instance. -1. Click on the share icon in the top navigation. +1. Click **Dashboards** in the left-side menu. +1. Click the dashboard you want to share. +1. Click the share icon at the top of the screen. - The share dialog opens and shows the **Link** tab. + The share dialog opens and shows the Link tab. ### Share a direct link @@ -73,7 +74,8 @@ A dashboard snapshot shares an interactive dashboard publicly. Grafana strips se You can publish snapshots to your local instance or to [snapshots.raintank.io](http://snapshots.raintank.io). The latter is a free service provided by Grafana Labs that enables you to publish dashboard snapshots to an external Grafana instance. Anyone with the link can view it. You can set an expiration time if you want the snapshot removed after a certain time period. -1. Click **Local Snapshot** or **Publish to snapshots.raintank.io**. +1. Click the **Snapshot** tab. +1. Click **Publish to snapshots.raintank.io** or **Local Snapshot**. Grafana generates a link of the snapshot. @@ -91,7 +93,9 @@ You can generate and save PDF files of any dashboard. > **Note:** Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}). -1. In the upper-right corner of the dashboard that you want to export as PDF, click the **Share dashboard** icon. +1. Click **Dashboards** in the left-side menu. +1. Click the dashboard you want to share. +1. Click the share icon at the top of the screen. 1. On the PDF tab, select a layout option for the exported dashboard: **Portrait** or **Landscape**. 1. Click **Save as PDF** to render the dashboard as a PDF file. @@ -101,8 +105,8 @@ You can generate and save PDF files of any dashboard. You can share a panel as a direct link, as a snapshot, or as an embedded link. You can also create library panels using the **Share** option on any panel. -1. Click a panel title to open the panel menu. -1. Click **Share**. +1. Hover over any part of the panel to display the actions menu on the top right corner. +1. Click the menu and select **Share**. The share dialog opens and shows the **Link** tab. @@ -139,8 +143,8 @@ A panel snapshot shares an interactive panel publicly. Grafana strips sensitive You can publish snapshots to your local instance or to [snapshots.raintank.io](http://snapshots.raintank.io). The latter is a free service provided by [Grafana Labs](https://grafana.com), that enables you to publish dashboard snapshots to an external Grafana instance. You can optionally set an expiration time if you want the snapshot to be removed after a certain time period. -1. In the **Share Panel** dialog, click **Snapshot** to open the tab. -1. Click **Local Snapshot** or **Publish to snapshots.raintank.io**. +1. In the **Share Panel** dialog, click **Snapshot** to go to the tab. +1. Click **Publish to snapshots.raintank.io** or **Local Snapshot**. Grafana generates the link of the snapshot. diff --git a/docs/sources/dashboards/use-dashboards/index.md b/docs/sources/dashboards/use-dashboards/index.md index d10eb022fa9..9753b8884df 100644 --- a/docs/sources/dashboards/use-dashboards/index.md +++ b/docs/sources/dashboards/use-dashboards/index.md @@ -27,27 +27,28 @@ The dashboard user interface provides a number of features that you can use to c The following image and descriptions highlights all dashboards features. -{{< figure src="/static/img/docs/v91/dashboard-features/dashboard-features.png" width="700px" >}} +{{< figure src="/media/docs/grafana/dashboards/screenshot-dashboard-annotated-9-5-0.png" width="700px" >}} -- **Grafana home** (1): Click the Grafana home icon to be redirected to the home page configured in the Grafana instance. +- **Grafana home** (1): Click **Home** in the breadcrumb to be redirected to the home page configured in the Grafana instance. - **Dashboard title** (2): When you click the dashboard title you can search for dashboard contained in the current folder. -- **Share dashboard** (3): Use this option to share the current dashboard by link or snapshot. You can also export the dashboard definition from the share modal. -- **Add a new panel** (4): Use this option to add a panel, dashboard row, or library panel to the current dashboard. -- **Dashboard settings** (5): Use this option to change dashboard name, folder, and tags and manage variables and annotation queries. For more information about dashboard settings, refer to [Modify dashboard settings]({{< relref "../build-dashboards/modify-dashboard-settings/" >}}). -- **Time picker dropdown** (6): Click to select relative time range options and set custom absolute time ranges. +- **Share dashboard or panel** (3): Use this option to share the current dashboard or panel by link or snapshot. You can also export the dashboard definition from the share modal. +- **Add** (4): Use this option to add a panel, dashboard row, or library panel to the current dashboard. +- **Save dashboard** (5): Click to save changes to your dashboard. +- **Dashboard insights** (6): Click to view analytics about your dashboard including information about users, activity, query counts. +- **Dashboard settings** (7): Use this option to change dashboard name, folder, and tags and manage variables and annotation queries. For more information about dashboard settings, refer to [Modify dashboard settings]({{< relref "../build-dashboards/modify-dashboard-settings/" >}}). +- **Time picker dropdown** (8): Click to select relative time range options and set custom absolute time ranges. - You can change the **Timezone** and **fiscal year** settings from the time range controls by clicking the **Change time settings** button. - Time settings are saved on a per-dashboard basis. -- **Zoom out time range** (7): Click to zoom out the time range. For more information about how to use time range controls, refer to [Common time range controls]({{< relref "#common-time-range-controls" >}}). -- **Refresh dashboard** (8): Click to immediately trigger queries and refresh dashboard data. -- **Refresh dashboard time interval** (9): Click to select a dashboard auto refresh time interval. -- **View mode** (10): Click to display the dashboard on a large screen such as a TV or a kiosk. View mode hides irrelevant information such as navigation menus. For more information about view mode, refer to [How to Create Kiosks to Display Dashboards on a TV](https://grafana.com/blog/2019/05/02/grafana-tutorial-how-to-create-kiosks-to-display-dashboards-on-a-tv/). -- **Dashboard panel** (11): The primary building block of a dashboard is the panel. To add a new panel, dashboard row, or library panel, click **Add panel**. +- **Zoom out time range** (9): Click to zoom out the time range. For more information about how to use time range controls, refer to [Common time range controls]({{< relref "#common-time-range-controls" >}}). +- **Refresh dashboard** (10): Click to immediately trigger queries and refresh dashboard data. +- **Refresh dashboard time interval** (11): Click to select a dashboard auto refresh time interval. +- **View mode** (12): Click to display the dashboard on a large screen such as a TV or a kiosk. View mode hides irrelevant information such as navigation menus. For more information about view mode, refer to [How to Create Kiosks to Display Dashboards on a TV](https://grafana.com/blog/2019/05/02/grafana-tutorial-how-to-create-kiosks-to-display-dashboards-on-a-tv/). +- **Dashboard panel** (13): The primary building block of a dashboard is the panel. To add a new panel, dashboard row, or library panel, click **Add panel**. - Library panels can be shared among many dashboards. - To move a panel, drag the panel header to another location. - To resize a panel, click and drag the lower right corner of the panel. -- **Graph legend** (12): Change series colors, y-axis and series visibility directly from the legend. -- **Search** (13): Click **Search** to search for dashboards by name or panel title. -- **Dashboard row** (14): A dashboard row is a logical divider within a dashboard that groups panels together. +- **Graph legend** (14): Change series colors, y-axis and series visibility directly from the legend. +- **Dashboard row** (15): A dashboard row is a logical divider within a dashboard that groups panels together. - Rows can be collapsed or expanded allowing you to hide parts of the dashboard. - Panels inside a collapsed row do not issue queries. - Use [repeating rows]({{< relref "../build-dashboards/create-dashboard/#configure-repeating-rows" >}}) to dynamically create rows based on a template variable. @@ -129,7 +130,7 @@ Hover your cursor over the field to see the exact time stamps in the range and t Click the current time range to change it. You can change the current time using a _relative time range_, such as the last 15 minutes, or an _absolute time range_, such as `2020-05-14 00:00:00 to 2020-05-15 23:59:59`. - + #### Relative time range diff --git a/docs/sources/dashboards/variables/add-template-variables/index.md b/docs/sources/dashboards/variables/add-template-variables/index.md index d26e4b0e434..deda7868f77 100644 --- a/docs/sources/dashboards/variables/add-template-variables/index.md +++ b/docs/sources/dashboards/variables/add-template-variables/index.md @@ -44,17 +44,17 @@ weight: 100 The following table lists the types of variables shipped with Grafana. -| Variable type | Description | -| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Query | Query-generated list of values such as metric names, server names, sensor IDs, data centers, and so on. [Add a query variable]({{< relref "#add-a-query-variable" >}}). | -| Custom | Define the variable options manually using a comma-separated list. [Add a custom variable]({{< relref "#add-a-custom-variable" >}}). | -| Text box | Display a free text input field with an optional default value. [Add a text box variable]({{< relref "#add-a-text-box-variable" >}}). | -| Constant | Define a hidden constant. [Add a constant variable]({{< relref "#add-a-constant-variable" >}}). | -| Data source | Quickly change the data source for an entire dashboard. [Add a data source variable]({{< relref "#add-a-data-source-variable" >}}). | -| Interval | Interval variables represent time spans. [Add an interval variable]({{< relref "#add-an-interval-variable" >}}). | -| Ad hoc filters | Key/value filters that are automatically added to all metric queries for a data source (InfluxDB, Prometheus, and Elasticsearch only). [Add ad hoc filters]({{< relref "#add-ad-hoc-filters" >}}). | -| Global variables | Built-in variables that can be used in expressions in the query editor. Refer to [Global variables]({{< relref "#global-variables" >}}). | -| Chained variables | Variable queries can contain other variables. Refer to [Chained variables]({{< relref "#chained-variables" >}}). | +| Variable type | Description | +| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Query | Query-generated list of values such as metric names, server names, sensor IDs, data centers, and so on. [Add a query variable]({{< relref "#add-a-query-variable" >}}). | +| Custom | Define the variable options manually using a comma-separated list. [Add a custom variable]({{< relref "#add-a-custom-variable" >}}). | +| Text box | Display a free text input field with an optional default value. [Add a text box variable]({{< relref "#add-a-text-box-variable" >}}). | +| Constant | Define a hidden constant. [Add a constant variable]({{< relref "#add-a-constant-variable" >}}). | +| Data source | Quickly change the data source for an entire dashboard. [Add a data source variable]({{< relref "#add-a-data-source-variable" >}}). | +| Interval | Interval variables represent time spans. [Add an interval variable]({{< relref "#add-an-interval-variable" >}}). | +| Ad hoc filters | Key/value filters that are automatically added to all metric queries for a data source (Prometheus, Loki, InfluxDB, and Elasticsearch only). [Add ad hoc filters]({{< relref "#add-ad-hoc-filters" >}}). | +| Global variables | Built-in variables that can be used in expressions in the query editor. Refer to [Global variables]({{< relref "#global-variables" >}}). | +| Chained variables | Variable queries can contain other variables. Refer to [Chained variables]({{< relref "#chained-variables" >}}). | ## Enter General options @@ -194,7 +194,7 @@ Ad hoc filters are one of the most complex and flexible variable options availab Interpolating a variable with multiple values selected is tricky as it is not straight forward how to format the multiple values into a string that is valid in the given context where the variable is used. Grafana tries to solve this by allowing each data source plugin to inform the templating interpolation engine what format to use for multiple values. -> **Note:** The **Custom all value** option on the variable must be blank for Grafana to format all values into a single string. If leave it blank, then the Grafana concatenates (adds together) all the values in the query. Something like `value1,value2,value3`. If a custom `all` value is used, then instead the value will be something like `*` or `all`. +> **Note:** The **Custom all value** option on the variable must be blank for Grafana to format all values into a single string. If it is left blank, then Grafana concatenates (adds together) all the values in the query. Something like `value1,value2,value3`. If a custom `all` value is used, then instead the value will be something like `*` or `all`. #### Multi-value variables with a Graphite data source @@ -281,6 +281,8 @@ This variable is the `$__interval` variable in milliseconds, not a time interval This variable is only available in the Singlestat panel and can be used in the prefix or suffix fields on the Options tab. The variable will be replaced with the series name or alias. +> **Note:** The Singlestat panel is no longer available from Grafana 8.0. + ### $\_\_org This variable is the ID of the current organization. @@ -398,7 +400,7 @@ apps.fakesite.web_server_01.cpu.* #### InfluxDB example -In this example, you have several data centers. Each data center has a different subset of hosts. It is based on the [InfluxDB Templated](https://play.grafana.org/d/000000002/influxdb-templated?orgId=1). +In this example, you have several data centers. Each data center has a different subset of hosts. It is based on the [InfluxDB Templated](https://play.grafana.org/d/000000002/influxdb-templated?orgId=1) dashboard. In this example, when the user changes the value of the `datacenter` variable, it changes the dropdown options returned by the `host` variable. The `host` variable uses the **Multi-value** option and **Include all option**, allowing users to select some or all options presented at any time. The `datacenter` does not use either option, so you can only select one data center at a time. @@ -407,7 +409,7 @@ In this example, when the user changes the value of the `datacenter` variable, i The query for this variable basically says, "Give me all the data centers that exist." ``` -SHOW TAG VALUES WITH KEY = "datacenter" +SHOW TAG VALUES WITH KEY = "datacenter" ``` The values returned are `America`, `Africa`, `Asia`, and `Europe`. diff --git a/docs/sources/datasources/alertmanager/_index.md b/docs/sources/datasources/alertmanager/_index.md index 0e69a550f71..3c4ac6b793d 100644 --- a/docs/sources/datasources/alertmanager/_index.md +++ b/docs/sources/datasources/alertmanager/_index.md @@ -28,24 +28,25 @@ When using Prometheus, contact points and notification policies are read-only in ## Configure the data source -**To access the data source configuration page:** +To configure basic settings for the data source, complete the following steps: -1. Select the **Data sources** section from the **Administration** menu -2. Select the **Alertmanager** data source +1. Click **Connections** in the left-side menu. +1. Under Your connections, click **Data sources**. +1. Enter `Alertmanager` in the search bar. +1. Click **Alertmanager**. -Set the data source's basic configuration options carefully: + The **Settings** tab of the data source is displayed. -| Name | Description | -| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Name** | Sets the name you use to refer to the data source | -| **Default** | Sets whether the data source is pre-selected for new panels and queries | -| **Alertmanager** | | -| **Implementation** | Alertmanager implementation. **Mimir**, **Cortex,** and **Prometheus** are supported | -| **Receive Grafana Alerts** | When enabled the Alertmanager receives alert instances from Grafana-managed alert rules. **Important:** It works only if Grafana alerting is configured to send its alert instances to external Alertmanagers | -| **HTTP** | | -| **URL** | Sets the HTTP protocol, IP, and port of your Alertmanager instance, such as `https://alertmanager.example.org:9093` | -| **Access** | Only **Server** access mode is functional | -| | | +1. Set the data source's basic configuration options: + + | Name | Description | + | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | **Name** | Sets the name you use to refer to the data source | + | **Default** | Sets whether the data source is pre-selected for new panels and queries | + | **Alertmanager Implementation** | Alertmanager implementation. **Mimir**, **Cortex,** and **Prometheus** are supported | + | **Receive Grafana Alerts** | When enabled the Alertmanager receives alert instances from Grafana-managed alert rules. **Important:** It works only if Grafana alerting is configured to send its alert instances to external Alertmanagers | + | **HTTP URL** | Sets the HTTP protocol, IP, and port of your Alertmanager instance, such as `https://alertmanager.example.org:9093` | + | **Access** | Only **Server** access mode is functional | ## Provision the Alertmanager data source diff --git a/docs/sources/datasources/aws-cloudwatch/_index.md b/docs/sources/datasources/aws-cloudwatch/_index.md index 3bb9a4160ef..ab5b0372780 100644 --- a/docs/sources/datasources/aws-cloudwatch/_index.md +++ b/docs/sources/datasources/aws-cloudwatch/_index.md @@ -31,11 +31,12 @@ Once you've added the data source, you can [configure it]({{< relref "#configure ## Configure the data source -**To access the data source configuration page:** +1. Click **Connections** in the left-side menu. +1. Under Your connections, click **Data sources**. +1. Enter `CloudWatch` in the search bar. +1. Click **CloudWatch**. -1. Hover the cursor over the **Configuration** (gear) icon. -1. Select **Data Sources**. -1. Select the CloudWatch data source. + The **Settings** tab of the data source is displayed. ### Configure AWS authentication @@ -49,7 +50,7 @@ For authentication options and configuration details, refer to [AWS authenticati To read CloudWatch metrics and EC2 tags, instances, regions, and alarms, you must grant Grafana permissions via IAM. You can attach these permissions to the IAM role or IAM user you configured in [AWS authentication]({{< relref "./aws-authentication/" >}}). -**Metrics-only:** +##### Metrics-only permissions ```json { @@ -84,7 +85,7 @@ You can attach these permissions to the IAM role or IAM user you configured in [ } ``` -**Logs-only:** +##### Logs-only permissions ```json { @@ -119,7 +120,7 @@ You can attach these permissions to the IAM role or IAM user you configured in [ } ``` -**Metrics and Logs:** +##### Metrics and logs permissions ```json { @@ -167,7 +168,7 @@ You can attach these permissions to the IAM role or IAM user you configured in [ } ``` -**Cross-account observability: (see below) ** +##### Cross-account observability permissions ```json { @@ -234,7 +235,7 @@ For more information about provisioning, and for available configuration options #### Provisioning examples -**Using AWS SDK (default):** +##### Using AWS SDK (default) ```yaml apiVersion: 1 @@ -246,7 +247,7 @@ datasources: defaultRegion: eu-west-2 ``` -**Using credentials' profile name (non-default):** +##### Using credentials' profile name (non-default) ```yaml apiVersion: 1 @@ -261,7 +262,7 @@ datasources: profile: secondary ``` -**Using accessKey and secretKey:** +##### Using accessKey and secretKey ```yaml apiVersion: 1 @@ -277,7 +278,7 @@ datasources: secretKey: '' ``` -**Using AWS SDK Default and ARN of IAM Role to Assume:** +##### Using AWS SDK Default and ARN of IAM Role to Assume ```yaml apiVersion: 1 @@ -375,3 +376,7 @@ For more information, refer to the AWS documentation for [Service Quotas](https: The CloudWatch plugin enables you to monitor and troubleshoot applications across multiple regional accounts. Using cross-account observability, you can seamlessly search, visualize and analyze metrics and logs without worrying about account boundaries. To use this feature, configure in the [AWS console under Cloudwatch Settings](https://aws.amazon.com/blogs/aws/new-amazon-cloudwatch-cross-account-observability/), a monitoring and source account, and then add the necessary IAM permissions as described above. + +## CloudWatch Logs data protection + +CloudWatch Logs can safeguard data by using log group data protection policies. If you have data protection enabled for a log group, then any sensitive data that matches the data identifiers you've selected will be masked. In order to view masked data you will need to have the `logs:Unmask` IAM permission enabled. See the AWS documentation on how to [help protect sensitive log data with masking](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/mask-sensitive-log-data.html) to learn more about this. diff --git a/docs/sources/datasources/aws-cloudwatch/query-editor/index.md b/docs/sources/datasources/aws-cloudwatch/query-editor/index.md index 08fb9717366..2911fa63d72 100644 --- a/docs/sources/datasources/aws-cloudwatch/query-editor/index.md +++ b/docs/sources/datasources/aws-cloudwatch/query-editor/index.md @@ -92,7 +92,7 @@ For example, to apply arithmetic operations to a metric, apply a unique string i > **Note:** If you use the expression field to reference another query, like `queryA * 2`, you can't create an alert rule based on that query. -##### Period macro +#### Period macro If you're using a CloudWatch [`SEARCH`](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/search-expression-syntax.html) expression, you may want to use the `$__period_auto` macro rather than specifying a period explicitly. The `$__period_auto` macro will resolve to a [CloudWatch period](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_GetMetricData.html) that is suitable for the chosen time range. @@ -218,9 +218,17 @@ When making `stats` queries in [Explore]({{< relref "../../../explore/" >}}), ma {{< figure src="/static/img/docs/v70/explore-mode-switcher.png" max-width="500px" class="docs-image--right" caption="Explore mode switcher" >}} -### Getting started +## Cross-account observability -To enable cross-account observability, first enable it in CloudWatch using the official [CloudWatch docs](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Unified-Cross-Account.html), then add [two new API actions]({{< relref "../#cross-account-observability" >}}) to the IAM policy attached to the role/user running the plugin. +The CloudWatch plugin allows monitoring and troubleshooting applications that span multiple accounts within a region. Using cross-account observability, you can seamlessly search, visualize, and analyze metrics and logs without worrying about account boundaries. + +### Get started + +To enable cross-account observability, complete the following steps: + +1. Go to the [Amazon CloudWatch docs](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Unified-Cross-Account.html) and follow the instructions on enabling cross-account observability. + +1. Add [two API actions](/docs/grafana/latest/datasources/aws-cloudwatch/#cross-account-observability-permissions) to the IAM policy attached to the role/user running the plugin. Cross-account querying is available in the plugin through the `Logs` mode and the `Metric search` mode. Once you have it configured correctly, you'll see a "Monitoring account" badge displayed in the query editor header. diff --git a/docs/sources/datasources/graphite/_index.md b/docs/sources/datasources/graphite/_index.md index f8c05a0925a..11275b7d75e 100644 --- a/docs/sources/datasources/graphite/_index.md +++ b/docs/sources/datasources/graphite/_index.md @@ -24,26 +24,29 @@ Once you've added the Graphite data source, you can [configure it]({{< relref "# ## Configure the data source -**To access the data source configuration page:** +To configure basic settings for the data source, complete the following steps: -1. Hover the cursor over the **Configuration** (gear) icon. -1. Select **Data Sources**. -1. Select the Graphite data source. +1. Click **Connections** in the left-side menu. +1. Under Your connections, click **Data sources**. +1. Enter `Graphite` in the search bar. +1. Click **Graphite**. -Set the data source's basic configuration options carefully: + The **Settings** tab of the data source is displayed. -| Name | Description | -| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -| **Name** | Sets the name you use to refer to the data source in panels and queries. | -| **Default** | Sets whether the data source is pre-selected for new panels. You can set only one default data source per organization. | -| **URL** | Sets the HTTP protocol, IP, and port of your graphite-web or graphite-api installation. | -| **Auth** | For details, refer to [Configure Authentication]({{< relref "../../setup-grafana/configure-security/configure-authentication/" >}}). | -| **Basic Auth** | Enables basic authentication to the data source. | -| **User** | Sets the user name for basic authentication. | -| **Password** | Sets the password for basic authentication. | -| **Custom HTTP Headers** | Click **Add header** to add a custom HTTP header. | -| **Header** | Defines the custom header name. | -| **Value** | Defines the custom header value. | +1. Set the data source's basic configuration options: + + | Name | Description | + | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | + | **Name** | Sets the name you use to refer to the data source in panels and queries. | + | **Default** | Sets whether the data source is pre-selected for new panels. You can set only one default data source per organization. | + | **URL** | Sets the HTTP protocol, IP, and port of your graphite-web or graphite-api installation. | + | **Auth** | For details, refer to [Configure Authentication]({{< relref "../../setup-grafana/configure-security/configure-authentication/" >}}). | + | **Basic Auth** | Enables basic authentication to the data source. | + | **User** | Sets the user name for basic authentication. | + | **Password** | Sets the password for basic authentication. | + | **Custom HTTP Headers** | Click **Add header** to add a custom HTTP header. | + | **Header** | Defines the custom header name. | + | **Value** | Defines the custom header value. | You can also configure settings specific to the Graphite data source: diff --git a/docs/sources/datasources/influxdb/_index.md b/docs/sources/datasources/influxdb/_index.md index 95e7a04ebef..11a5fb064cc 100644 --- a/docs/sources/datasources/influxdb/_index.md +++ b/docs/sources/datasources/influxdb/_index.md @@ -41,14 +41,13 @@ To configure basic settings for the data source, complete the following steps: 1. Set the data source's basic configuration options carefully: - | Name | Description | - + | Name | Description | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | - | **Name** | Sets the name you use to refer to the data source in panels and queries. We recommend something like `InfluxDB-InfluxQL`. | - | **Default** | Sets whether the data source is pre-selected for new panels. | - | **URL** | The HTTP protocol, IP address, and port of your InfluxDB API. InfluxDB's default API port is 8086. | - | **Min time interval** | _(Optional)_ Refer to [Min time interval]({{< relref "#configure-min-time-interval" >}}). | - | **Max series** | _(Optional)_ Limits the number of series and tables that Grafana processes. Lower this number to prevent abuse, and increase it if you have many small time series and not all are shown. Defaults to 1,000. | + | **Name** | Sets the name you use to refer to the data source in panels and queries. We recommend something like `InfluxDB-InfluxQL`. | + | **Default** | Sets whether the data source is pre-selected for new panels. | + | **URL** | The HTTP protocol, IP address, and port of your InfluxDB API. InfluxDB's default API port is 8086. | + | **Min time interval** | _(Optional)_ Refer to [Min time interval]({{< relref "#configure-min-time-interval" >}}). | + | **Max series** | _(Optional)_ Limits the number of series and tables that Grafana processes. Lower this number to prevent abuse, and increase it if you have many small time series and not all are shown. Defaults to 1,000. | You can also configure settings specific to the InfluxDB data source. These options are described in the sections below. diff --git a/docs/sources/datasources/loki/query-editor/index.md b/docs/sources/datasources/loki/query-editor/index.md index abbce0d0c73..b3cea436004 100644 --- a/docs/sources/datasources/loki/query-editor/index.md +++ b/docs/sources/datasources/loki/query-editor/index.md @@ -54,45 +54,10 @@ Code mode's autocompletion feature works automatically while typing. The query editor can autocomplete static functions, aggregations, and keywords, and also dynamic items like labels. The autocompletion dropdown includes documentation for the suggested items where available. -### Label browser - -You can use the Loki label browser to navigate through your labels and values, and build queries. - -**To navigate Loki and build a query:** - -1. Choose labels to locate. -1. Search for the values of your selected labels. - - The search field supports fuzzy search, and the label browser also supports faceting to list only possible label combinations. - -1. Choose a query type between [**logs query**]({{< relref "#create-a-log-query" >}}) and [**rate metrics query**]({{< relref "#create-a-metric-query" >}}). - You can also validate the selector. - -{{< figure src="/static/img/docs/v75/loki_label_browser.png" class="docs-image--no-shadow" max-width="800px" caption="The Loki label browser" >}} - -### Configure query settings - -| Name | Description | -| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| **Type** | Selects the query type to run. The `instant` type queries against a single point in time. We use the "To" time from the time range. The `range` type queries over the selected range of time. | -| **Line limit** | Defines the upper limit for the number of log lines returned by a query. The default is Loki's configured maximum lines limit. | -| **Legend** | _(Available only in a dashboard)_ Controls the time series name, using a name or pattern. For example, `{{hostname}}` is replaced with the label value for the label `hostname`. | -| **Resolution** | Sets the step parameter of Loki metrics range queries. With a resolution of `1/1`, each pixel corresponds to one data point. `1/2` retrieves one data point for every other pixel, `1/10` retrieves one data point per 10 pixels, and so on. Lower resolutions perform better. | - ## Builder mode Use Builder mode to visually construct queries, without needing to manually enter LogQL. -### Review toolbar features - -In addition to the **Run query** button and mode switcher, Builder mode provides additional elements: - -| Name | Description | -| ------------------------- | ----------------------------------------------------------------------------------------- | -| **Kick start your query** | A list of useful operation patterns you can use to add multiple operations to your query. | -| **Label browser** | Used to navigate through your labels and values, and also build queries. | -| **Explain query** | Displays a step-by-step explanation of all query components and operations. | - ### Use the Labels selector Select labels and their values from the dropdown list. @@ -108,11 +73,11 @@ The query editor groups operations into related sections, and you can type while The query editor displays a query's operations as boxes in the operations section. Each operation's header displays its name, and additional action buttons appear when you hover your cursor over the header: -| Button | Action | -| ------ | ----------------------------------------------------------------- | -| `v` | Replaces the operation with different operation of the same type. | -| `info` | Opens the operation's description tooltip. | -| `x` | Removes the operation. | +| Button | Action | +| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | +| {{< figure src="/static/img/docs/v95/loki_operation_replace.png" class="docs-image--no-shadow" max-width="30px" >}} | Replaces the operation with different operation of the same type. | +| {{< figure src="/static/img/docs/v95/loki_operation_description.png" class="docs-image--no-shadow" max-width="30px" >}} | Opens the operation's description tooltip. | +| {{< figure src="/static/img/docs/v95/loki_operation_remove.png" class="docs-image--no-shadow" max-width="30px" >}} | Removes the operation. | Some operations have additional parameters under the operation header. For details about each operation, use the `info` button to view the operation's description, or refer to the [Loki documentation](/docs/loki/latest/operations/). @@ -125,10 +90,6 @@ To re-order operations manually, drag the operation box by its name and drop it In same cases the query editor can detect which operations would be most appropriate for a selected log stream. In such cases it will show a hint next to the `+ Operations` button. Click on the hint to add the operations to your query. -### Explain query - -This section is only shown if the `Explain query` switch from the query editor top toolbar is set to `on`. It shows a step by step explanation of all query parts and the operations. - ## Create a log query Loki log queries return the contents of the log lines. @@ -205,6 +166,45 @@ You can use LogQL to wrap a log query with functions that create metrics from yo For more information about metric queries, refer to the [Loki metric queries documentation](/docs/loki/latest/logql/metric_queries/). +## Review toolbar features + +In addition to the **Run query** button and mode switcher, Builder mode provides additional elements: + +| Name | Description | +| ------------------------- | ----------------------------------------------------------------------------------------- | +| **Kick start your query** | A list of useful operation patterns you can use to add multiple operations to your query. | +| **Label browser** | Used to navigate through your labels and values, and also build queries. | +| **Explain query** | Displays a step-by-step explanation of all query components and operations. | + +### Label browser + +You can use the Loki label browser to navigate through your labels and values, and build queries. + +**To navigate Loki and build a query:** + +1. Choose labels to locate. +1. Search for the values of your selected labels. + + The search field supports fuzzy search, and the label browser also supports faceting to list only possible label combinations. + +1. Choose a query type between [**logs query**]({{< relref "#create-a-log-query" >}}) and [**rate metrics query**]({{< relref "#create-a-metric-query" >}}). + You can also validate the selector. + +{{< figure src="/static/img/docs/v75/loki_label_browser.png" class="docs-image--no-shadow" max-width="800px" caption="The Loki label browser" >}} + +### Explain query + +This section is only shown if the `Explain query` switch from the query editor top toolbar is set to `on`. It shows a step by step explanation of all query parts and the operations. + +## Configure query settings + +| Name | Description | +| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **Type** | Selects the query type to run. The `instant` type queries against a single point in time. We use the "To" time from the time range. The `range` type queries over the selected range of time. | +| **Line limit** | Defines the upper limit for the number of log lines returned by a query. The default is Loki's configured maximum lines limit. | +| **Legend** | _(Available only in a dashboard)_ Controls the time series name, using a name or pattern. For example, `{{hostname}}` is replaced with the label value for the label `hostname`. | +| **Resolution** | Sets the step parameter of Loki metrics range queries. With a resolution of `1/1`, each pixel corresponds to one data point. `1/2` retrieves one data point for every other pixel, `1/10` retrieves one data point per 10 pixels, and so on. Lower resolutions perform better. | + ## Apply annotations [Annotations]({{< relref "../../../dashboards/build-dashboards/annotate-visualizations" >}}) overlay rich event information on top of graphs. diff --git a/docs/sources/datasources/parca.md b/docs/sources/datasources/parca.md index b37f88022d2..8ef350f6bbd 100644 --- a/docs/sources/datasources/parca.md +++ b/docs/sources/datasources/parca.md @@ -18,16 +18,25 @@ Grafana ships with built-in support for Parca, a continuous profiling OSS databa ## Configure the Parca data source -To access Parca settings, click the **Configuration** (gear) icon, then click **Data Sources** > **Parca**. +To configure basic settings for the data source, complete the following steps: -| Name | Description | -| ------------ | ------------------------------------------------------------------ | -| `Name` | A name to specify the data source in panels, queries, and Explore. | -| `Default` | The default data source will be pre-selected for new panels. | -| `URL` | The URL of the Parca instance, e.g., `http://localhost:4100` | -| `Basic Auth` | Enable basic authentication to the Parca data source. | -| `User` | User name for basic authentication. | -| `Password` | Password for basic authentication. | +1. Click **Connections** in the left-side menu. +1. Under Your connections, click **Data sources**. +1. Enter `Parca` in the search bar. +1. Click **Parca**. + + The **Settings** tab of the data source is displayed. + +1. Set the data source's basic configuration options: + + | Name | Description | + | ------------ | ------------------------------------------------------------------ | + | `Name` | A name to specify the data source in panels, queries, and Explore. | + | `Default` | The default data source will be pre-selected for new panels. | + | `URL` | The URL of the Parca instance, e.g., `http://localhost:4100` | + | `Basic Auth` | Enable basic authentication to the Parca data source. | + | `User` | User name for basic authentication. | + | `Password` | Password for basic authentication. | ## Querying diff --git a/docs/sources/datasources/phlare.md b/docs/sources/datasources/phlare.md index ee0a9dab141..09d19dbedb2 100644 --- a/docs/sources/datasources/phlare.md +++ b/docs/sources/datasources/phlare.md @@ -18,17 +18,26 @@ Grafana ships with built-in support for Phlare, a horizontally scalable, highly- ## Configure the Phlare data source -To access Phlare settings, click the **Configuration** (gear) icon, then click **Data Sources** > **Phlare**. +To configure basic settings for the data source, complete the following steps: -| Name | Description | -| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `Name` | A name to specify the data source in panels, queries, and Explore. | -| `Default` | The default data source will be pre-selected for new panels. | -| `URL` | The URL of the Phlare instance, e.g., `http://localhost:4100` | -| `Basic Auth` | Enable basic authentication to the Phlare data source. | -| `User` | User name for basic authentication. | -| `Password` | Password for basic authentication. | -| `Minimal step` | Similar to Prometheus, Phlare scrapes profiles at certain intervals. To prevent querying at smaller interval use Minimal step same or higher than your Phlare scrape interval. | +1. Click **Connections** in the left-side menu. +1. Under Your connections, click **Data sources**. +1. Enter `Phlare` in the search bar. +1. Click **Phlare**. + + The **Settings** tab of the data source is displayed. + +1. Set the data source's basic configuration options: + + | Name | Description | + | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | + | `Name` | A name to specify the data source in panels, queries, and Explore. | + | `Default` | The default data source will be pre-selected for new panels. | + | `URL` | The URL of the Phlare instance, e.g., `http://localhost:4100` | + | `Basic Auth` | Enable basic authentication to the Phlare data source. | + | `User` | User name for basic authentication. | + | `Password` | Password for basic authentication. | + | `Minimal step` | Similar to Prometheus, Phlare scrapes profiles at certain intervals. To prevent querying at smaller interval use Minimal step same or higher than your Phlare scrape interval. | ## Querying diff --git a/docs/sources/datasources/prometheus/_index.md b/docs/sources/datasources/prometheus/_index.md index 4e51f5f0a0d..04a414ffd41 100644 --- a/docs/sources/datasources/prometheus/_index.md +++ b/docs/sources/datasources/prometheus/_index.md @@ -45,40 +45,38 @@ To configure basic settings for the data source, complete the following steps: 1. Set the data source's basic configuration options: - | Name | Description | - + | Name | Description | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | `Name` | The data source name. This is how you refer to the data source in panels and queries. | - | `Default` | Default data source that is pre-selected for new panels. | - | `URL` | The URL of your Prometheus server, for example, `http://prometheus.example.org:9090`. | - | `Access` | Only Server access mode is functional. If Server mode is already selected this option is hidden. Otherwise change to Server mode to prevent errors. | - | `Basic Auth` | Enable basic authentication to the Prometheus data source. | - | `User` | User name for basic authentication. | - | `Password` | Password for basic authentication. | - | `Manage alerts via Alerting UI` | Toggle whether to enable Alertmanager integration for this data source. | - | `Scrape interval` | Set this to the typical scrape and evaluation interval configured in Prometheus. Defaults to 15s. | - | `HTTP method` | Use either POST or GET HTTP method to query your data source. POST is the recommended and pre-selected method as it allows bigger queries. Change this to GET if you have a Prometheus version older than 2.1 or if POST requests are restricted in your network. | - | `Type` | The type of your Prometheus server; `Prometheus`, `Cortex`, `Thanos`, `Mimir`. When selected, the **Version** field attempts to populate automatically using the Prometheus [buildinfo](https://semver.org/) API. Some Prometheus types, such as Cortex, don't support this API and must be manually populated. | - | `Version` | The version of your Prometheus server, note that this field is not visible until the Prometheus type is selected. | - | `Disable metrics lookup` | Checking this option will disable the metrics chooser and metric/label support in the query field's autocomplete. This helps if you have performance issues with bigger Prometheus instances. | - | `Custom query parameters` | Add custom parameters to the Prometheus query URL. For example `timeout`, `partial_response`, `dedup`, or `max_source_resolution`. Multiple parameters should be concatenated together with an '&'. | - | **Exemplars configuration** | | - | `Internal link` | Enable this option is you have an internal link. When you enable this option, you will see a data source selector. Select the backend tracing data store for your exemplar data. | - | `Data source` | You will see this option only if you enable `Internal link` option. Select the backend tracing data store for your exemplar data. | - | `URL` | You will see this option only if the `Internal link` option is disabled. Enter the full URL of the external link. You can interpolate the value from the field with `${__value.raw }` macro. | - | `URL Label` | (Optional) add a custom display label to override the value of the `Label name` field. | - | `Label name` | Add a name for the exemplar traceID property. | + | `Name` | The data source name. This is how you refer to the data source in panels and queries. | + | `Default` | Default data source that is pre-selected for new panels. | + | `URL` | The URL of your Prometheus server, for example, `http://prometheus.example.org:9090`. | + | `Access` | Only Server access mode is functional. If Server mode is already selected this option is hidden. Otherwise change to Server mode to prevent errors. | + | `Basic Auth` | Enable basic authentication to the Prometheus data source. | + | `User` | User name for basic authentication. | + | `Password` | Password for basic authentication. | + | `Manage alerts via Alerting UI` | Toggle whether to enable Alertmanager integration for this data source. | + | `Scrape interval` | Set this to the typical scrape and evaluation interval configured in Prometheus. Defaults to 15s. | + | `HTTP method` | Use either POST or GET HTTP method to query your data source. POST is the recommended and pre-selected method as it allows bigger queries. Change this to GET if you have a Prometheus version older than 2.1 or if POST requests are restricted in your network. | + | `Type` | The type of your Prometheus server; `Prometheus`, `Cortex`, `Thanos`, `Mimir`. When selected, the **Version** field attempts to populate automatically using the Prometheus [buildinfo](https://semver.org/) API. Some Prometheus types, such as Cortex, don't support this API and must be manually populated. | + | `Version` | The version of your Prometheus server, note that this field is not visible until the Prometheus type is selected. | + | `Disable metrics lookup` | Checking this option will disable the metrics chooser and metric/label support in the query field's autocomplete. This helps if you have performance issues with bigger Prometheus instances. | + | `Custom query parameters` | Add custom parameters to the Prometheus query URL. For example `timeout`, `partial_response`, `dedup`, or `max_source_resolution`. Multiple parameters should be concatenated together with an '&'. | + | **Exemplars configuration** | | + | `Internal link` | Enable this option is you have an internal link. When you enable this option, you will see a data source selector. Select the backend tracing data store for your exemplar data. | + | `Data source` | You will see this option only if you enable `Internal link` option. Select the backend tracing data store for your exemplar data. | + | `URL` | You will see this option only if the `Internal link` option is disabled. Enter the full URL of the external link. You can interpolate the value from the field with `${__value.raw }` macro. | + | `URL Label` | (Optional) add a custom display label to override the value of the `Label name` field. | + | `Label name` | Add a name for the exemplar traceID property. | **Exemplars configuration:** - | Name | Description | - + | Name | Description | | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | **Internal link** | Enable this option if you have an internal link. When enabled, this reveals the data source selector. Select the backend tracing data store for your exemplar data. | - | **Data source** | _(Visible only if you enable `Internal link`)_ Selects the backend tracing data store for your exemplar data. | - | **URL** | _(Visible only if you disable `Internal link`)_ Defines the external link's full URL. You can interpolate the value from the field by using the [`${__value.raw}` macro]({{< relref "../..//panels-visualizations/configure-data-links/#value-variables" >}}). | - | **URL label** | _(Optional)_ Adds a custom display label to override the value of the `Label name` field. | - | **Label name** | Adds a name for the exemplar traceID property. | + | **Internal link** | Enable this option if you have an internal link. When enabled, this reveals the data source selector. Select the backend tracing data store for your exemplar data. | + | **Data source** | _(Visible only if you enable `Internal link`)_ Selects the backend tracing data store for your exemplar data. | + | **URL** | _(Visible only if you disable `Internal link`)_ Defines the external link's full URL. You can interpolate the value from the field by using the [`${__value.raw}` macro]({{< relref "../..//panels-visualizations/configure-data-links/#value-variables" >}}). | + | **URL label** | _(Optional)_ Adds a custom display label to override the value of the `Label name` field. | + | **Label name** | Adds a name for the exemplar traceID property. | ### Provision the data source diff --git a/docs/sources/datasources/tempo/_index.md b/docs/sources/datasources/tempo/_index.md index be7cedffa78..0b10a4bada8 100644 --- a/docs/sources/datasources/tempo/_index.md +++ b/docs/sources/datasources/tempo/_index.md @@ -38,15 +38,14 @@ To configure basic settings for the data source, complete the following steps: 1. Set the data source's basic configuration options: - | Name | Description | - + | Name | Description | | -------------- | ------------------------------------------------------------------------ | - | **Name** | Sets the name you use to refer to the data source in panels and queries. | - | **Default** | Sets the data source that's pre-selected for new panels. | - | **URL** | Sets the URL of the Tempo instance, such as `http://tempo`. | - | **Basic Auth** | Enables basic authentication to the Tempo data source. | - | **User** | Sets the user name for basic authentication. | - | **Password** | Sets the password for basic authentication. | + | **Name** | Sets the name you use to refer to the data source in panels and queries. | + | **Default** | Sets the data source that's pre-selected for new panels. | + | **URL** | Sets the URL of the Tempo instance, such as `http://tempo`. | + | **Basic Auth** | Enables basic authentication to the Tempo data source. | + | **User** | Sets the user name for basic authentication. | + | **Password** | Sets the password for basic authentication. | You can also configure settings specific to the Tempo data source. These options are described in the sections below. @@ -232,6 +231,10 @@ datasources: spanBar: type: 'Tag' tag: 'http.path' + traceQuery: + timeShiftEnabled: true + spanStartTimeShift: 15m + spanEndTimeShift: 20m ``` ## Query the data source diff --git a/docs/sources/datasources/testdata/_index.md b/docs/sources/datasources/testdata/_index.md index 27b42124717..ad3c17bc64b 100644 --- a/docs/sources/datasources/testdata/_index.md +++ b/docs/sources/datasources/testdata/_index.md @@ -33,11 +33,10 @@ To configure basic settings for the data source, complete the following steps: The **Settings** tab of the data source is displayed. The data source doesn't provide any settings beyond the most basic options common to all data sources: - | Name | Description | - + | Name | Description | | ----------- | ------------------------------------------------------------------------ | - | **Name** | Sets the name you use to refer to the data source in panels and queries. | - | **Default** | Defines whether this data source is pre-selected for new panels. | + | **Name** | Sets the name you use to refer to the data source in panels and queries. | + | **Default** | Defines whether this data source is pre-selected for new panels. | ## Create mock data diff --git a/docs/sources/datasources/zipkin/_index.md b/docs/sources/datasources/zipkin/_index.md index 0a02fe196c8..c3cb2878c66 100644 --- a/docs/sources/datasources/zipkin/_index.md +++ b/docs/sources/datasources/zipkin/_index.md @@ -38,15 +38,14 @@ To configure basic settings for the data source, complete the following steps: 1. Set the data source's basic configuration options: - | Name | Description | - + | Name | Description | | -------------- | ------------------------------------------------------------------------ | - | **Name** | Sets the name you use to refer to the data source in panels and queries. | - | **Default** | Defines whether this data source is pre-selected for new panels. | - | **URL** | Sets the URL of the Zipkin instance, such as `http://localhost:9411`. | - | **Basic Auth** | Enables basic authentication for the Zipkin data source. | - | **User** | Defines the user name for basic authentication. | - | **Password** | Defines the password for basic authentication. | + | **Name** | Sets the name you use to refer to the data source in panels and queries. | + | **Default** | Defines whether this data source is pre-selected for new panels. | + | **URL** | Sets the URL of the Zipkin instance, such as `http://localhost:9411`. | + | **Basic Auth** | Enables basic authentication for the Zipkin data source. | + | **User** | Defines the user name for basic authentication. | + | **Password** | Defines the password for basic authentication. | ### Trace to logs diff --git a/docs/sources/introduction/_index.md b/docs/sources/introduction/_index.md index f74466dd5a0..511c3f788d6 100644 --- a/docs/sources/introduction/_index.md +++ b/docs/sources/introduction/_index.md @@ -8,7 +8,7 @@ weight: 5 # Grafana OSS -[Grafana open source software](https://grafana.com/oss/) enables you to query, visualize, alert on, and explore your metrics, logs, and traces wherever they are stored. Grafana OSS provides you with tools to turn your time-series database (TSDB) data into insightful graphs and visualizations. +[Grafana open source software](https://grafana.com/oss/) enables you to query, visualize, alert on, and explore your metrics, logs, and traces wherever they are stored. Grafana OSS provides you with tools to turn your time-series database (TSDB) data into insightful graphs and visualizations. The Grafana OSS plugin framework also enables you to connect other data sources like NoSQL/SQL databases, ticketing tools like Jira or ServiceNow, and CI/CD tooling like GitLab. After you have [installed Grafana]({{< relref "../setup-grafana/installation/" >}}) and set up your first dashboard using instructions in [Getting started with Grafana]({{< relref "../getting-started/build-first-dashboard.md" >}}), you will have many options to choose from depending on your requirements. For example, if you want to view weather data and statistics about your smart home, then you can create a [playlist]({{< relref "../dashboards/create-manage-playlists/" >}}). If you are the administrator for an enterprise and are managing Grafana for multiple teams, then you can set up [provisioning]({{< relref "../administration/provisioning/" >}}) and [authentication]({{< relref "../setup-grafana/configure-security/configure-authentication/" >}}). @@ -71,3 +71,5 @@ In addition to Grafana, Grafana Labs also provides the following open source pro **Grafana Tempo:** Grafana Tempo is an open source, easy-to-use and high-volume distributed tracing backend. For more information, refer to [Grafana Tempo documentation](https://grafana.com/docs/tempo/latest/?pg=oss-tempo&plcmt=hero-txt/). **Grafana Mimir:** Grafana Mimir is an open source software project that provides a scalable long-term storage for Prometheus. For more information about Grafana Mimir, refer to [Grafana Mimir documentation](https://grafana.com/docs/mimir/latest/). + +**Grafana Phlare:** Grafana Phlare is an open-source software project for aggregating continuous profiling data. Continuous profiling is an observability signal that enables you to understand your workload's resource (CPU, memory, etc.) usage to the exact line number. For more information about using Grafana Phlare, refer to [Grafana Phlare documentation](https://grafana.com/docs/phlare/latest/). diff --git a/docs/sources/panels-visualizations/visualizations/dashboard-list/index.md b/docs/sources/panels-visualizations/visualizations/dashboard-list/index.md index 662475f6b33..94b579778f2 100644 --- a/docs/sources/panels-visualizations/visualizations/dashboard-list/index.md +++ b/docs/sources/panels-visualizations/visualizations/dashboard-list/index.md @@ -26,6 +26,8 @@ On each dashboard load, this panel queries the dashboard list, always providing Use these options to refine your visualization. +- **Include current time range -** Select this option to propagate the time range of the current dashboard to the dashboard links. When the user clicks a link, the linked dashboard opens with the indicated time range already set. +- **Include current template variable values -** Select this option to include template variables currently used as query parameters in a link. When the user clicks the link, any matching templates in the linked dashboard are set to the values from the link. Learn more about [Dashboard URL variables]({{< relref "../../../dashboards/build-dashboards/create-dashboard-url-variables/" >}}). - **Starred -** Display starred dashboards in alphabetical order. - **Recently viewed -** Display recently viewed dashboards in alphabetical order. - **Search -** Display dashboards by search query or tags. You must enter at least one value in **Query** or **Tags**. For the **Query** and **Tags** fields. Variable interpolation is supported, for example,`$my_var` or `${my_var}`. diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index d6061a3ee0a..7b9aff01b69 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -47,6 +47,7 @@ Some stable features are enabled by default. You can disable a stable feature by | `validateDashboardsOnSave` | Validate dashboard JSON POSTed to api/dashboards/db | | `autoMigrateOldPanels` | Migrate old angular panels to supported versions (graph, table-old, worldmap, etc) | | `disableAngular` | Dynamic flag to disable angular at runtime. The preferred method is to set `angular_support_enabled` to `false` in the [security] settings, which allows you to change the state at runtime. | +| `grpcServer` | Run the GRPC server | | `accessControlOnCall` | Access control primitives for OnCall | | `alertingNoNormalState` | Stop maintaining state of alerts that are not firing | | `disableElasticsearchBackendExploreQuery` | Disable executing of Elasticsearch Explore queries trough backend | @@ -59,7 +60,6 @@ Alpha features might be changed or removed without prior notice. | Feature toggle name | Description | | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `alertingBigTransactions` | Use big transactions for alerting database writes | | `dashboardPreviews` | Create and show thumbnails for dashboard search results | | `live-service-web-worker` | This will use a webworker thread to processes events rather than the main thread | | `queryOverLive` | Use Grafana Live WebSocket to execute backend queries | @@ -83,6 +83,7 @@ Alpha features might be changed or removed without prior notice. | `showDashboardValidationWarnings` | Show warnings when dashboards do not validate against the schema | | `mysqlAnsiQuotes` | Use double quotes to escape keyword in a MySQL query | | `elasticsearchBackendMigration` | Use Elasticsearch as backend data source | +| `showTraceId` | Show trace ids for requests | | `datasourceOnboarding` | Enable data source onboarding page | | `secureSocksDatasourceProxy` | Enable secure socks tunneling for supported core datasources | | `authnService` | Use new auth service to perform authentication | @@ -105,6 +106,7 @@ Alpha features might be changed or removed without prior notice. | `alertStateHistoryLokiPrimary` | Enable a remote Loki instance as the primary source for state history reads. | | `alertStateHistoryLokiOnly` | Disable Grafana alerts from emitting annotations when a remote Loki instance is available. | | `unifiedRequestLog` | Writes error logs to the request logger | +| `pyroscopeFlameGraph` | Changes flame graph to pyroscope one | ## Development feature toggles @@ -113,6 +115,5 @@ The following toggles require explicitly setting Grafana's [app mode]({{< relref | Feature toggle name | Description | | ------------------- | --------------------------------------------------- | | `k8s` | Explore native k8s integrations | -| `grpcServer` | Run GRPC server | | `entityStore` | SQL-based entity store (requires storage flag also) | | `nestedFolders` | Enable folder nesting | diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/enhanced-ldap/index.md b/docs/sources/setup-grafana/configure-security/configure-authentication/enhanced-ldap/index.md index 1bc215476a8..947fab9e93f 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/enhanced-ldap/index.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/enhanced-ldap/index.md @@ -19,6 +19,7 @@ weight: 900 The enhanced LDAP integration adds additional functionality on top of the [LDAP integration]({{< relref "ldap/" >}}) available in the open source edition of Grafana. > **Note:** Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud Advanced](/docs/grafana-cloud). +> If you are a Grafana Cloud customer, please [open a support ticket in the Cloud Portal](/profile/org#support) to request this feature. > To control user access with role-based permissions, refer to [role-based access control]({{< relref "../../../../administration/roles-and-permissions/access-control/" >}}). diff --git a/docs/sources/whatsnew/whats-new-in-v9-4.md b/docs/sources/whatsnew/whats-new-in-v9-4.md index d47d7a20c23..feea36c9224 100644 --- a/docs/sources/whatsnew/whats-new-in-v9-4.md +++ b/docs/sources/whatsnew/whats-new-in-v9-4.md @@ -296,6 +296,10 @@ We've added support for JWT authentication. We've added support for custom session parameters. +## Postgres, MySQL, and MSSQL data sources + +The `database` property is now under the `jsonData` key in the data source configuration. This change is backward compatible, and existing configurations will continue to work. + ## Before you upgrade There are no known breaking changes associated with this version of Grafana. diff --git a/e2e/dashboards-suite/dashboard-public-create.spec.ts b/e2e/dashboards-suite/dashboard-public-create.spec.ts index 304f502dfa3..5b0bb7b159d 100644 --- a/e2e/dashboards-suite/dashboard-public-create.spec.ts +++ b/e2e/dashboards-suite/dashboard-public-create.spec.ts @@ -8,7 +8,11 @@ e2e.scenario({ skipScenario: false, scenario: () => { // Opening a dashboard without template variables - e2e().intercept('POST', '/api/ds/query').as('query'); + e2e() + .intercept({ + pathname: '/api/ds/query', + }) + .as('query'); e2e.flows.openDashboard({ uid: 'ZqZnVvFZz' }); e2e().wait('@query'); @@ -65,7 +69,12 @@ e2e.scenario({ skipScenario: false, scenario: () => { // Opening a dashboard without template variables - e2e().intercept('POST', '/api/ds/query').as('query'); + e2e() + .intercept({ + method: 'POST', + pathname: '/api/ds/query', + }) + .as('query'); e2e.flows.openDashboard({ uid: 'ZqZnVvFZz' }); e2e().wait('@query'); @@ -109,7 +118,12 @@ e2e.scenario({ skipScenario: false, scenario: () => { // Opening a dashboard without template variables - e2e().intercept('/api/ds/query').as('query'); + e2e() + .intercept({ + method: 'POST', + pathname: '/api/ds/query', + }) + .as('query'); e2e.flows.openDashboard({ uid: 'ZqZnVvFZz' }); e2e().wait('@query'); diff --git a/e2e/dashboards-suite/load-options-from-url.spec.ts b/e2e/dashboards-suite/load-options-from-url.spec.ts index d4e2f486eed..e42a55d7056 100644 --- a/e2e/dashboards-suite/load-options-from-url.spec.ts +++ b/e2e/dashboards-suite/load-options-from-url.spec.ts @@ -9,7 +9,7 @@ describe('Variables - Load options from Url', () => { e2e() .intercept({ method: 'POST', - url: '/api/ds/query', + pathname: '/api/ds/query*', }) .as('query'); @@ -61,7 +61,7 @@ describe('Variables - Load options from Url', () => { e2e() .intercept({ method: 'POST', - url: '/api/ds/query', + pathname: '/api/ds/query', }) .as('query'); @@ -124,7 +124,7 @@ describe('Variables - Load options from Url', () => { e2e() .intercept({ method: 'POST', - url: '/api/ds/query', + pathname: '/api/ds/query', }) .as('query'); diff --git a/e2e/dashboards-suite/set-options-from-ui.spec.ts b/e2e/dashboards-suite/set-options-from-ui.spec.ts index 94d1fbe60fd..c6d61d78c1d 100644 --- a/e2e/dashboards-suite/set-options-from-ui.spec.ts +++ b/e2e/dashboards-suite/set-options-from-ui.spec.ts @@ -61,7 +61,11 @@ describe('Variables - Set options from ui', () => { it('adding a value that is not part of dependents options should add the new values dependant options', () => { e2e.flows.login('admin', 'admin'); e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&var-datacenter=A&var-server=AA&var-pod=AAA` }); - e2e().intercept('/api/ds/query').as('query'); + e2e() + .intercept({ + pathname: '/api/ds/query', + }) + .as('query'); e2e().wait('@query'); @@ -119,7 +123,7 @@ describe('Variables - Set options from ui', () => { e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&var-datacenter=A&var-datacenter=B&var-server=AA&var-server=BB&var-pod=AAA&var-pod=BBB`, }); - e2e().intercept('/api/ds/query').as('query'); + e2e().intercept({ pathname: '/api/ds/query' }).as('query'); e2e().wait('@query'); diff --git a/e2e/panels-suite/panelEdit_base.spec.ts b/e2e/panels-suite/panelEdit_base.spec.ts index 44c3e8d25ee..2ae5daa1cd2 100644 --- a/e2e/panels-suite/panelEdit_base.spec.ts +++ b/e2e/panels-suite/panelEdit_base.spec.ts @@ -9,7 +9,11 @@ e2e.scenario({ addScenarioDashBoard: false, skipScenario: false, scenario: () => { - e2e().intercept('/api/ds/query').as('query'); + e2e() + .intercept({ + pathname: '/api/ds/query', + }) + .as('query'); e2e.flows.openDashboard({ uid: 'TkZXxlNG3' }); e2e().wait('@query'); @@ -79,6 +83,7 @@ e2e.scenario({ e2e.components.PluginVisualization.current().should((e) => expect(e).to.contain('Time series')); // Check that table view works + e2e.components.Panels.Panel.loadingBar().should('not.exist'); e2e.components.PanelEditor.toggleTableView().click({ force: true }); e2e.components.Panels.Visualization.Table.header() .should('be.visible') diff --git a/e2e/sql-suite/mysql.spec.ts b/e2e/sql-suite/mysql.spec.ts index ab535220c98..91ab9d7379a 100644 --- a/e2e/sql-suite/mysql.spec.ts +++ b/e2e/sql-suite/mysql.spec.ts @@ -11,24 +11,30 @@ describe('MySQL datasource', () => { it('code editor autocomplete should handle table name escaping/quoting', () => { e2e.flows.login('admin', 'admin'); - e2e().intercept('POST', '**/api/ds/query', (req) => { - if (req.body.queries[0].refId === 'datasets') { - req.alias = 'datasets'; - req.reply({ - body: datasetResponse, - }); - } else if (req.body.queries[0].refId === 'tables') { - req.alias = 'tables'; - req.reply({ - body: tablesResponse, - }); - } else if (req.body.queries[0].refId === 'fields') { - req.alias = 'fields'; - req.reply({ - body: fieldsResponse, - }); + e2e().intercept( + 'POST', + { + pathname: '/api/ds/query', + }, + (req) => { + if (req.body.queries[0].refId === 'datasets') { + req.alias = 'datasets'; + req.reply({ + body: datasetResponse, + }); + } else if (req.body.queries[0].refId === 'tables') { + req.alias = 'tables'; + req.reply({ + body: tablesResponse, + }); + } else if (req.body.queries[0].refId === 'fields') { + req.alias = 'fields'; + req.reply({ + body: fieldsResponse, + }); + } } - }); + ); e2e.pages.Explore.visit(); diff --git a/e2e/various-suite/exemplars.spec.ts b/e2e/various-suite/exemplars.spec.ts index fa07c4755d6..70c286902a0 100644 --- a/e2e/various-suite/exemplars.spec.ts +++ b/e2e/various-suite/exemplars.spec.ts @@ -32,16 +32,21 @@ describe('Exemplars', () => { }); it('should be able to navigate to configured data source', () => { - let intercept = 'prometheus'; - e2e().intercept('/api/ds/query', (req) => { - if (intercept === 'prometheus') { - // For second intercept, we want to send tempo response - intercept = 'tempo'; - req.reply({ fixture: 'exemplars-query-response.json' }); - } else { - req.reply({ fixture: 'tempo-response.json' }); + e2e().intercept( + { + pathname: '/api/ds/query', + }, + (req) => { + const datasourceType = req.body.queries[0].datasource.type; + if (datasourceType === 'prometheus') { + req.reply({ fixture: 'exemplars-query-response.json' }); + } else if (datasourceType === 'tempo') { + req.reply({ fixture: 'tempo-response.json' }); + } else { + req.reply({}); + } } - }); + ); e2e.pages.Explore.visit(); diff --git a/e2e/various-suite/explore.spec.ts b/e2e/various-suite/explore.spec.ts index 8ba2fede78e..d81db71fce0 100644 --- a/e2e/various-suite/explore.spec.ts +++ b/e2e/various-suite/explore.spec.ts @@ -11,7 +11,15 @@ e2e.scenario({ e2e.pages.Explore.General.container().should('have.length', 1); e2e.components.RefreshPicker.runButtonV2().should('have.length', 1); + // delete query history queries that would be unrelated + e2e.components.QueryTab.queryHistoryButton().should('be.visible').click(); + cy.get('button[title="Delete query"]').each((button) => { + button.trigger('click'); + }); + e2e.components.QueryTab.queryHistoryButton().should('be.visible').click(); + e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer() + .scrollIntoView() .should('be.visible') .within(() => { e2e().get('input[id*="test-data-scenario-select-"]').should('be.visible').click(); diff --git a/go.mod b/go.mod index 14cfb1d3a12..ea79e9db324 100644 --- a/go.mod +++ b/go.mod @@ -67,7 +67,7 @@ require ( github.com/grafana/cuetsy v0.1.6 github.com/grafana/grafana-aws-sdk v0.12.0 github.com/grafana/grafana-azure-sdk-go v1.6.0 - github.com/grafana/grafana-plugin-sdk-go v0.157.0 + github.com/grafana/grafana-plugin-sdk-go v0.158.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/hashicorp/go-hclog v1.2.0 github.com/hashicorp/go-plugin v1.4.3 diff --git a/go.sum b/go.sum index 072c1dae840..3d3f7a3665d 100644 --- a/go.sum +++ b/go.sum @@ -1297,6 +1297,8 @@ github.com/grafana/grafana-plugin-sdk-go v0.94.0/go.mod h1:3VXz4nCv6wH5SfgB3mlW3 github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk= github.com/grafana/grafana-plugin-sdk-go v0.157.0 h1:Qm0r5A4TsG+Tmy8Vagffqv21t3R/tzFUdYZZpd9COYE= github.com/grafana/grafana-plugin-sdk-go v0.157.0/go.mod h1:FwinU1fti54nWWsacIdL8D2WfYcKOWB2VRMtxnBbY+o= +github.com/grafana/grafana-plugin-sdk-go v0.158.0 h1:kucTwr4LEa6hoSunnRqkuEeJOgbBTFrhdGNkJrMV4Zg= +github.com/grafana/grafana-plugin-sdk-go v0.158.0/go.mod h1:7/F3lL/w3MGuZTwu0jam5oL/4zNOQmhs2k8WZ9VlzhI= github.com/grafana/kindsys v0.0.0-20230309200316-812b9884a375 h1:iWFjqAU5GjIV/HetIE/Me6VF3SRw29u5QviMVbJUVQo= github.com/grafana/kindsys v0.0.0-20230309200316-812b9884a375/go.mod h1:213a3clTiegHfheYcLPLeEyHv/azK/fAF67OEbzuLzw= github.com/grafana/mysql v1.6.8 h1:kyo38C4NgghJMqaPrkWPy4rifAcipQVF+dKttfpgTCs= diff --git a/lerna.json b/lerna.json index 58e6a8163bb..75716a4cd76 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,8 @@ { "npmClient": "yarn", "useWorkspaces": true, - "packages": ["packages/*"], - "version": "9.5.0-pre" + "packages": [ + "packages/*" + ], + "version": "10.0.0-pre" } diff --git a/package.json b/package.json index 4b7f3ca6efc..1e8cf53df28 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "license": "AGPL-3.0-only", "private": true, "name": "grafana", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "repository": "github:grafana/grafana", "scripts": { "build": "yarn i18n:compile && NODE_ENV=production webpack --progress --config scripts/webpack/webpack.prod.js", @@ -266,7 +266,7 @@ "@grafana/lezer-logql": "0.1.2", "@grafana/monaco-logql": "^0.0.7", "@grafana/runtime": "workspace:*", - "@grafana/scenes": "^0.2.0", + "@grafana/scenes": "^0.3.0", "@grafana/schema": "workspace:*", "@grafana/ui": "workspace:*", "@kusto/monaco-kusto": "5.3.6", @@ -279,6 +279,7 @@ "@opentelemetry/semantic-conventions": "1.9.1", "@popperjs/core": "2.11.6", "@prometheus-io/lezer-promql": "^0.37.0-rc.1", + "@pyroscope/flamegraph": "^0.35.5", "@react-aria/button": "3.6.1", "@react-aria/dialog": "3.3.1", "@react-aria/focus": "3.8.0", diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index d997c73c4d4..70497f3d1ed 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/data", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "description": "Grafana Data Library", "keywords": [ "typescript" @@ -36,7 +36,7 @@ }, "dependencies": { "@braintree/sanitize-url": "6.0.2", - "@grafana/schema": "9.5.0-pre", + "@grafana/schema": "10.0.0-pre", "@types/d3-interpolate": "^3.0.0", "d3-interpolate": "3.0.1", "date-fns": "2.29.3", diff --git a/packages/grafana-data/src/dataframe/DataFrameJSON.test.ts b/packages/grafana-data/src/dataframe/DataFrameJSON.test.ts index 6cd11677ba0..fe6930eaf2f 100644 --- a/packages/grafana-data/src/dataframe/DataFrameJSON.test.ts +++ b/packages/grafana-data/src/dataframe/DataFrameJSON.test.ts @@ -1,6 +1,7 @@ -import { FieldType } from '../types/dataFrame'; +import { ArrayVector } from '..'; +import { DataFrame, FieldType } from '../types/dataFrame'; -import { DataFrameJSON, dataFrameFromJSON } from './DataFrameJSON'; +import { DataFrameJSON, dataFrameFromJSON, dataFrameToJSON } from './DataFrameJSON'; describe('DataFrame JSON', () => { describe('when called with a DataFrame', () => { @@ -137,5 +138,104 @@ describe('DataFrame JSON', () => { } `); }); + + it('should decode fields with nanos', () => { + const json: DataFrameJSON = { + schema: { + fields: [ + { name: 'time1', type: FieldType.time }, + { name: 'time2', type: FieldType.time }, + ], + }, + data: { + values: [ + [1, 2, 3], + [4, 5, 6], + ], + nanos: [null, [7, 8, 9]], + }, + }; + + const frame = dataFrameFromJSON(json); + expect(frame).toMatchInlineSnapshot(` + { + "fields": [ + { + "config": {}, + "entities": {}, + "name": "time1", + "type": "time", + "values": [ + 1, + 2, + 3, + ], + }, + { + "config": {}, + "entities": {}, + "name": "time2", + "nanos": [ + 7, + 8, + 9, + ], + "type": "time", + "values": [ + 4, + 5, + 6, + ], + }, + ], + "length": 3, + } + `); + }); + + it('should encode fields with nanos', () => { + const inputFrame: DataFrame = { + refId: 'A', + meta: {}, + name: 'f1', + fields: [ + { + name: 'time1', + type: FieldType.time, + config: {}, + values: new ArrayVector([11, 12, 13]), + }, + { + name: 'time2', + type: FieldType.time, + config: {}, + values: new ArrayVector([14, 15, 16]), + nanos: [17, 18, 19], + }, + ], + length: 3, + }; + + const expectedJSON: DataFrameJSON = { + schema: { + fields: [ + { name: 'time1', type: FieldType.time, config: {} }, + { name: 'time2', type: FieldType.time, config: {} }, + ], + meta: {}, + name: 'f1', + refId: 'A', + }, + data: { + nanos: [null, [17, 18, 19]], + values: [ + [11, 12, 13], + [14, 15, 16], + ], + }, + }; + + expect(dataFrameToJSON(inputFrame)).toStrictEqual(expectedJSON); + }); }); }); diff --git a/packages/grafana-data/src/dataframe/DataFrameJSON.ts b/packages/grafana-data/src/dataframe/DataFrameJSON.ts index 79dd8e14acd..47b64fe72b6 100644 --- a/packages/grafana-data/src/dataframe/DataFrameJSON.ts +++ b/packages/grafana-data/src/dataframe/DataFrameJSON.ts @@ -1,4 +1,4 @@ -import { DataFrame, FieldType, FieldConfig, Labels, QueryResultMeta } from '../types'; +import { DataFrame, FieldType, FieldConfig, Labels, QueryResultMeta, Field } from '../types'; import { ArrayVector } from '../vector'; import { guessFieldTypeFromNameAndValue } from './processDataFrame'; @@ -56,6 +56,13 @@ export interface DataFrameData { * NOTE: currently only decoding is implemented */ enums?: Array; + + /** + * Holds integers between 0 and 999999, used by time-fields + * to store the nanosecond-precision that cannot be represented + * by the millisecond-based base value. + */ + nanos?: Array; } /** @@ -188,9 +195,11 @@ export function dataFrameFromJSON(dto: DataFrameJSON): DataFrame { type = FieldType.string; } + const nanos = data?.nanos?.[index]; + // TODO: expand arrays further using bases,factors - return { + const dataFrameField: Field & { entities: FieldValueEntityLookup } = { ...f, type: type ?? guessFieldType(f.name, buffer), config: f.config ?? {}, @@ -198,6 +207,12 @@ export function dataFrameFromJSON(dto: DataFrameJSON): DataFrame { // the presence of this prop is an optimization signal & lookup for consumers entities: entities ?? {}, }; + + if (nanos != null) { + dataFrameField.nanos = nanos; + } + + return dataFrameField; }); return { @@ -216,18 +231,34 @@ export function dataFrameToJSON(frame: DataFrame): DataFrameJSON { const data: DataFrameData = { values: [], }; + + const allNanos: Array = []; + let hasNanos = false; + const schema: DataFrameSchema = { refId: frame.refId, meta: frame.meta, name: frame.name, fields: frame.fields.map((f) => { - const { values, state, display, ...sfield } = f; + const { values, nanos, state, display, ...sfield } = f; delete (sfield as any).entities; data.values.push(values.toArray()); + + if (nanos != null) { + allNanos.push(nanos); + hasNanos = true; + } else { + allNanos.push(null); + } + return sfield; }), }; + if (hasNanos) { + data.nanos = allNanos; + } + return { schema, data, diff --git a/packages/grafana-data/src/field/fieldDisplay.test.ts b/packages/grafana-data/src/field/fieldDisplay.test.ts index f7e293987c1..ebea46752bd 100644 --- a/packages/grafana-data/src/field/fieldDisplay.test.ts +++ b/packages/grafana-data/src/field/fieldDisplay.test.ts @@ -6,7 +6,7 @@ import { ReducerID } from '../transformations/fieldReducer'; import { FieldConfigPropertyItem, MappingType, SpecialValueMatch, ValueMapping } from '../types'; import { getDisplayProcessor } from './displayProcessor'; -import { getFieldDisplayValues, GetFieldDisplayValuesOptions } from './fieldDisplay'; +import { fixCellTemplateExpressions, getFieldDisplayValues, GetFieldDisplayValuesOptions } from './fieldDisplay'; import { standardFieldConfigEditorRegistry } from './standardFieldConfigEditorRegistry'; describe('FieldDisplay', () => { @@ -534,3 +534,11 @@ function createDisplayOptions(extend: Partial = {} return merge(options, extend); } + +describe('fixCellTemplateExpressions', () => { + it('Should replace __cell_x correctly', () => { + expect(fixCellTemplateExpressions('$__cell_10 asd ${__cell_15} asd [[__cell_20]]')).toEqual( + '${__data.fields[10]} asd ${__data.fields[15]} asd ${__data.fields[20]}' + ); + }); +}); diff --git a/packages/grafana-data/src/field/fieldDisplay.ts b/packages/grafana-data/src/field/fieldDisplay.ts index f21393f21d0..6bd10b415fb 100644 --- a/packages/grafana-data/src/field/fieldDisplay.ts +++ b/packages/grafana-data/src/field/fieldDisplay.ts @@ -1,4 +1,4 @@ -import { toString, isEmpty } from 'lodash'; +import { isEmpty } from 'lodash'; import { DataFrameView } from '../dataframe/DataFrameView'; import { getTimeField } from '../dataframe/processDataFrame'; @@ -96,7 +96,6 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi const data = options.data ?? []; const limit = reduceOptions.limit ? reduceOptions.limit : DEFAULT_FIELD_DISPLAY_VALUES_LIMIT; - const scopedVars: ScopedVars = {}; let hitLimit = false; @@ -125,7 +124,7 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi }; } - const displayName = field.config.displayName ?? ''; + let displayName = field.config.displayName ?? ''; const display = field.display ?? @@ -137,23 +136,10 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi // Show all rows if (reduceOptions.values) { - const usesCellValues = displayName.indexOf(VAR_CELL_PREFIX) >= 0; - for (let j = 0; j < field.values.length; j++) { - // Add all the row variables - if (usesCellValues) { - for (let k = 0; k < dataFrame.fields.length; k++) { - const f = dataFrame.fields[k]; - const v = f.values.get(j); - scopedVars[VAR_CELL_PREFIX + k] = { - value: v, - text: toString(v), - }; - } - } - field.state = setIndexForPaletteColor(field, values.length); + const scopedVars = getFieldScopedVarsWithDataContexAndRowIndex(field, j); const displayValue = display(field.values.get(j)); const rowName = getSmartDisplayNameForRow(dataFrame, field, j, replaceVariables, scopedVars); const overrideColor = lookupRowColorFromOverride(rowName, options.fieldConfig, theme); @@ -190,14 +176,13 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi }); for (const calc of calcs) { + const scopedVars = field.state?.scopedVars ?? {}; scopedVars[VAR_CALC] = { value: calc, text: calc }; + const displayValue = display(results[calc]); if (displayName !== '') { - displayValue.title = replaceVariables(displayName, { - ...field.state?.scopedVars, // series and field scoped vars - ...scopedVars, - }); + displayValue.title = replaceVariables(displayName, scopedVars); } else { displayValue.title = getFieldDisplayName(field, dataFrame, data); } @@ -247,18 +232,22 @@ function getSmartDisplayNameForRow( field: Field, rowIndex: number, replaceVariables: InterpolateFunction, - scopedVars: ScopedVars + scopedVars: ScopedVars | undefined ): string { + const displayName = field.config.displayName; + + if (displayName) { + // Handle old __cell_n syntax + if (displayName.indexOf(VAR_CELL_PREFIX)) { + return replaceVariables(fixCellTemplateExpressions(displayName), scopedVars); + } + + return replaceVariables(displayName, scopedVars); + } + let parts: string[] = []; let otherNumericFields = 0; - if (field.config.displayName) { - return replaceVariables(field.config.displayName, { - ...field.state?.scopedVars, // series and field scoped vars - ...scopedVars, - }); - } - for (const otherField of frame.fields) { if (otherField === field) { continue; @@ -382,3 +371,28 @@ function getDisplayText(display: DisplayValue, fallback: string): string { } return display.text; } + +export function fixCellTemplateExpressions(str: string) { + return str.replace(/\${__cell_(\d+)}|\[\[__cell_(\d+)\]\]|\$__cell_(\d+)/g, (match, fmt1, fmt2, fmt3) => { + return `\${__data.fields[${fmt1 ?? fmt2 ?? fmt3}]}`; + }); +} + +/** + * Clones the existing dataContext and adds rowIndex to it + */ +function getFieldScopedVarsWithDataContexAndRowIndex(field: Field, rowIndex: number): ScopedVars | undefined { + if (field.state?.scopedVars?.__dataContext) { + return { + ...field.state?.scopedVars, + __dataContext: { + value: { + ...field.state?.scopedVars?.__dataContext.value, + rowIndex, + }, + }, + }; + } + + return field.state?.scopedVars; +} diff --git a/packages/grafana-data/src/field/fieldOverrides.test.ts b/packages/grafana-data/src/field/fieldOverrides.test.ts index 59abb84e52f..c0295144ab1 100644 --- a/packages/grafana-data/src/field/fieldOverrides.test.ts +++ b/packages/grafana-data/src/field/fieldOverrides.test.ts @@ -199,35 +199,9 @@ describe('applyFieldOverrides', () => { fieldConfigRegistry: new FieldConfigOptionsRegistry(), }); - expect(withOverrides[0].fields[0].state!.scopedVars).toMatchInlineSnapshot(` - { - "__field": { - "text": "Field", - "value": {}, - }, - "__series": { - "text": "Series", - "value": { - "name": "A", - }, - }, - } - `); - - expect(withOverrides[1].fields[0].state!.scopedVars).toMatchInlineSnapshot(` - { - "__field": { - "text": "Field", - "value": {}, - }, - "__series": { - "text": "Series", - "value": { - "name": "B", - }, - }, - } - `); + expect(withOverrides[0].fields[0].state!.scopedVars?.__dataContext?.value.frame).toBe(withOverrides[0]); + expect(withOverrides[0].fields[0].state!.scopedVars?.__dataContext?.value.frameIndex).toBe(0); + expect(withOverrides[0].fields[0].state!.scopedVars?.__dataContext?.value.field).toBe(withOverrides[0].fields[0]); }); }); @@ -441,6 +415,124 @@ describe('setFieldConfigDefaults', () => { } `); }); + + it('applies field config defaults correctly when links property exist in field config and no links are defined in panel', () => { + const dsFieldConfig: FieldConfig = { + links: [ + { + title: 'Google link', + url: 'https://google.com', + }, + ], + }; + + const panelFieldConfig: FieldConfig = {}; + + const context: FieldOverrideEnv = { + data: [], + field: { type: FieldType.number } as Field, + dataFrameIndex: 0, + fieldConfigRegistry: customFieldRegistry, + }; + + // we mutate dsFieldConfig + // @ts-ignore + setFieldConfigDefaults(dsFieldConfig, panelFieldConfig, context); + + expect(dsFieldConfig).toMatchInlineSnapshot(` + { + "custom": {}, + "links": [ + { + "title": "Google link", + "url": "https://google.com", + }, + ], + } + `); + }); + + it('applies field config defaults correctly when links property exist in panel config and no links are defined in ds field config', () => { + const dsFieldConfig: FieldConfig = {}; + + const panelFieldConfig: FieldConfig = { + links: [ + { + title: 'Google link', + url: 'https://google.com', + }, + ], + }; + + const context: FieldOverrideEnv = { + data: [], + field: { type: FieldType.number } as Field, + dataFrameIndex: 0, + fieldConfigRegistry: customFieldRegistry, + }; + + // we mutate dsFieldConfig + // @ts-ignore + setFieldConfigDefaults(dsFieldConfig, panelFieldConfig, context); + + expect(dsFieldConfig).toMatchInlineSnapshot(` + { + "custom": {}, + "links": [ + { + "title": "Google link", + "url": "https://google.com", + }, + ], + } + `); + }); + + it('applies a merge strategy for links when they exist in ds config and panel', () => { + const dsFieldConfig: FieldConfig = { + links: [ + { + title: 'Google link', + url: 'https://google.com', + }, + ], + }; + + const panelFieldConfig: FieldConfig = { + links: [ + { + title: 'Grafana', + url: 'https://grafana.com', + }, + ], + }; + + const context: FieldOverrideEnv = { + data: [], + field: { type: FieldType.number } as Field, + dataFrameIndex: 0, + fieldConfigRegistry: customFieldRegistry, + }; + + // we mutate dsFieldConfig + setFieldConfigDefaults(dsFieldConfig, panelFieldConfig, context); + + expect(dsFieldConfig).toMatchInlineSnapshot(` + { + "custom": {}, + "links": [ + { + "title": "Google link", + "url": "https://google.com", + }, + { + "title": "Grafana", + "url": "https://grafana.com", + }, + ], + } + `); + }); }); describe('setDynamicConfigValue', () => { diff --git a/packages/grafana-data/src/field/fieldOverrides.ts b/packages/grafana-data/src/field/fieldOverrides.ts index ceceb40952d..f3b248a5000 100644 --- a/packages/grafana-data/src/field/fieldOverrides.ts +++ b/packages/grafana-data/src/field/fieldOverrides.ts @@ -39,10 +39,7 @@ import { mapInternalLinkToExplore } from '../utils/dataLinks'; import { FieldConfigOptionsRegistry } from './FieldConfigOptionsRegistry'; import { getDisplayProcessor, getRawDisplayProcessor } from './displayProcessor'; -import { getFrameDisplayName } from './fieldState'; -import { getFieldDisplayValuesProxy } from './getFieldDisplayValuesProxy'; import { standardFieldConfigEditorRegistry } from './standardFieldConfigEditorRegistry'; -import { getTemplateProxyForField } from './templateProxies'; interface OverrideProps { match: FieldMatcher; @@ -122,18 +119,17 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra }; }); - const scopedVars: ScopedVars = { - __series: { text: 'Series', value: { name: getFrameDisplayName(newFrame, index) } }, // might be missing - }; - for (const field of newFrame.fields) { const config = field.config; field.state!.scopedVars = { - ...scopedVars, - __field: { - text: 'Field', - value: getTemplateProxyForField(field, newFrame, options.data), + __dataContext: { + value: { + data: options.data!, + frame: newFrame, + frameIndex: index, + field: field, + }, }, }; @@ -293,6 +289,11 @@ export function setDynamicConfigValue(config: FieldConfig, value: DynamicConfigV // config -> from DS // defaults -> from Panel config export function setFieldConfigDefaults(config: FieldConfig, defaults: FieldConfig, context: FieldOverrideEnv) { + // For cases where we have links on the datasource config and the panel config, we need to merge them + if (config.links && defaults.links) { + // Combine the data source links and the panel default config links + config.links = [...config.links, ...defaults.links]; + } for (const fieldConfigProperty of context.fieldConfigRegistry.list()) { if (fieldConfigProperty.isCustom && !config.custom) { config.custom = {}; @@ -371,49 +372,29 @@ export const getLinksSupplier = } return field.config.links.map((link: DataLink) => { - let dataFrameVars = {}; - let dataContext: DataContextScopedVar = { value: { frame, field } }; + const dataContext: DataContextScopedVar = getFieldDataContextClone(frame, field, fieldScopedVars); + const dataLinkScopedVars = { + ...fieldScopedVars, + __dataContext: dataContext, + }; // We are not displaying reduction result if (config.valueRowIndex !== undefined && !isNaN(config.valueRowIndex)) { dataContext.value.rowIndex = config.valueRowIndex; - - const fieldsProxy = getFieldDisplayValuesProxy({ - frame, - rowIndex: config.valueRowIndex, - timeZone: timeZone, - }); - - dataFrameVars = { - __data: { - value: { - name: frame.name, - refId: frame.refId, - fields: fieldsProxy, - }, - text: 'Data', - }, - }; } else { dataContext.value.calculatedValue = config.calculatedValue; } - const variables: ScopedVars = { - ...fieldScopedVars, - ...dataFrameVars, - __dataContext: dataContext, - }; - if (link.onClick) { return { href: link.url, - title: replaceVariables(link.title || '', variables), + title: replaceVariables(link.title || '', dataLinkScopedVars), target: link.targetBlank ? '_blank' : undefined, onClick: (evt, origin) => { link.onClick!({ origin: origin ?? field, e: evt, - replaceVariables: (v) => replaceVariables(v, variables), + replaceVariables: (v) => replaceVariables(v, dataLinkScopedVars), }); }, origin: field, @@ -425,7 +406,7 @@ export const getLinksSupplier = return mapInternalLinkToExplore({ link, internalLink: link.internal, - scopedVars: variables, + scopedVars: dataLinkScopedVars, field, range: link.internal.range ?? ({} as any), replaceVariables, @@ -440,13 +421,13 @@ export const getLinksSupplier = if (href) { href = locationUtil.assureBaseUrl(href.replace(/\n/g, '')); - href = replaceVariables(href, variables, VariableFormatID.PercentEncode); + href = replaceVariables(href, dataLinkScopedVars, VariableFormatID.PercentEncode); href = locationUtil.processUrl(href); } const info: LinkModel = { href, - title: replaceVariables(link.title || '', variables), + title: replaceVariables(link.title || '', dataLinkScopedVars), target: link.targetBlank ? '_blank' : undefined, origin: field, }; @@ -530,3 +511,18 @@ export function useFieldOverrides( }; }, [fieldConfigRegistry, fieldConfig, data, prevSeries, timeZone, theme, replace]); } + +/** + * Clones the existing dataContext or creates a new one + */ +function getFieldDataContextClone(frame: DataFrame, field: Field, fieldScopedVars: ScopedVars) { + if (fieldScopedVars?.__dataContext) { + return { + value: { + ...fieldScopedVars.__dataContext.value, + }, + }; + } + + return { value: { frame, field, data: [frame] } }; +} diff --git a/packages/grafana-data/src/types/ScopedVars.ts b/packages/grafana-data/src/types/ScopedVars.ts index b5e6b9e0ed7..725dd051a8d 100644 --- a/packages/grafana-data/src/types/ScopedVars.ts +++ b/packages/grafana-data/src/types/ScopedVars.ts @@ -16,9 +16,11 @@ export interface ScopedVars { */ export interface DataContextScopedVar { value: { + data: DataFrame[]; frame: DataFrame; field: Field; rowIndex?: number; + frameIndex?: number; calculatedValue?: DisplayValue; }; } diff --git a/packages/grafana-data/src/types/app.ts b/packages/grafana-data/src/types/app.ts index f3ff6eafda9..f62b98ccca9 100644 --- a/packages/grafana-data/src/types/app.ts +++ b/packages/grafana-data/src/types/app.ts @@ -97,7 +97,7 @@ export class AppPlugin extends GrafanaPlugin(extension: Exclude, 'type'>) { + configureExtensionLink(extension: Omit, 'type'>) { this._extensionConfigs.push({ ...extension, type: PluginExtensionTypes.link, diff --git a/packages/grafana-data/src/types/dataFrame.ts b/packages/grafana-data/src/types/dataFrame.ts index 5ee8a3d30db..d7200416ce4 100644 --- a/packages/grafana-data/src/types/dataFrame.ts +++ b/packages/grafana-data/src/types/dataFrame.ts @@ -137,6 +137,14 @@ export interface Field> { */ config: FieldConfig; values: V; // The raw field values + + /** + * When type === FieldType.Time, this can optionally store + * the nanosecond-precison fractions as integers between + * 0 and 999999. + */ + nanos?: number[]; + labels?: Labels; /** diff --git a/packages/grafana-data/src/types/datasource.ts b/packages/grafana-data/src/types/datasource.ts index 3fe8cf36a09..02a196f0240 100644 --- a/packages/grafana-data/src/types/datasource.ts +++ b/packages/grafana-data/src/types/datasource.ts @@ -465,6 +465,11 @@ export interface DataQueryResponse { * Defaults to LoadingState.Done if state is not defined */ state?: LoadingState; + + /** + * traceIds related to the response, if available + */ + traceIds?: string[]; } export enum DataQueryErrorType { @@ -488,6 +493,7 @@ export interface DataQueryError { status?: number; statusText?: string; refId?: string; + traceId?: string; type?: DataQueryErrorType; } diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index d889e89e2f1..d2414f1c493 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -18,7 +18,6 @@ * @public */ export interface FeatureToggles { - alertingBigTransactions?: boolean; trimDefaults?: boolean; disableEnvelopeEncryption?: boolean; database_metrics?: boolean; @@ -65,6 +64,7 @@ export interface FeatureToggles { nestedFolders?: boolean; accessTokenExpirationCheck?: boolean; elasticsearchBackendMigration?: boolean; + showTraceId?: boolean; datasourceOnboarding?: boolean; emptyDashboardPage?: boolean; secureSocksDatasourceProxy?: boolean; @@ -93,4 +93,5 @@ export interface FeatureToggles { alertStateHistoryLokiOnly?: boolean; unifiedRequestLog?: boolean; renderAuthJWT?: boolean; + pyroscopeFlameGraph?: boolean; } diff --git a/packages/grafana-data/src/types/panel.ts b/packages/grafana-data/src/types/panel.ts index 7e72b7680a7..99c580deeac 100644 --- a/packages/grafana-data/src/types/panel.ts +++ b/packages/grafana-data/src/types/panel.ts @@ -66,6 +66,9 @@ export interface PanelData { /** Contains the range from the request or a shifted time range if a request uses relative time */ timeRange: TimeRange; + + /** traceIds collected during the processing of the requests */ + traceIds?: string[]; } export interface PanelProps { diff --git a/packages/grafana-data/src/types/pluginExtensions.ts b/packages/grafana-data/src/types/pluginExtensions.ts index 796c4c6e24b..dcc312a9c9c 100644 --- a/packages/grafana-data/src/types/pluginExtensions.ts +++ b/packages/grafana-data/src/types/pluginExtensions.ts @@ -1,3 +1,5 @@ +import { DataQuery } from '@grafana/schema'; + import { RawTimeRange, TimeZone } from './time'; // Plugin Extensions types @@ -18,7 +20,7 @@ export type PluginExtension = { export type PluginExtensionLink = PluginExtension & { type: PluginExtensionTypes.link; path?: string; - onClick?: (event: React.MouseEvent) => void; + onClick?: (event?: React.MouseEvent) => void; }; // Objects used for registering extensions (in app plugins) @@ -43,7 +45,7 @@ export type PluginExtensionLinkConfig = PluginE Context, Pick & { type: PluginExtensionTypes.link; - onClick?: (event: React.MouseEvent, helpers: PluginExtensionEventHelpers) => void; + onClick?: (event: React.MouseEvent | undefined, helpers: PluginExtensionEventHelpers) => void; } >; @@ -73,7 +75,7 @@ export type PluginExtensionPanelContext = { timeRange: RawTimeRange; timeZone: TimeZone; dashboard: Dashboard; - targets: Target[]; + targets: DataQuery[]; }; type Dashboard = { @@ -81,8 +83,3 @@ type Dashboard = { title: string; tags: string[]; }; - -type Target = { - pluginId: string; - refId: string; -}; diff --git a/packages/grafana-e2e-selectors/package.json b/packages/grafana-e2e-selectors/package.json index 3035cfb0ba5..a3dbb13e104 100644 --- a/packages/grafana-e2e-selectors/package.json +++ b/packages/grafana-e2e-selectors/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/e2e-selectors", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "description": "Grafana End-to-End Test Selectors Library", "keywords": [ "cli", diff --git a/packages/grafana-e2e-selectors/src/selectors/components.ts b/packages/grafana-e2e-selectors/src/selectors/components.ts index 245ec1d342a..7ba3ebf6068 100644 --- a/packages/grafana-e2e-selectors/src/selectors/components.ts +++ b/packages/grafana-e2e-selectors/src/selectors/components.ts @@ -76,6 +76,7 @@ export const Components = { menu: (title: string) => `data-testid Panel menu ${title}`, containerByTitle: (title: string) => `${title} panel`, headerCornerInfo: (mode: string) => `Panel header ${mode}`, + loadingBar: () => `Panel loading bar`, }, Visualization: { Graph: { diff --git a/packages/grafana-e2e/package.json b/packages/grafana-e2e/package.json index b22bb34adec..0b85a93aa11 100644 --- a/packages/grafana-e2e/package.json +++ b/packages/grafana-e2e/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/e2e", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "description": "Grafana End-to-End Test Library", "keywords": [ "cli", @@ -63,7 +63,7 @@ "@babel/core": "7.20.5", "@babel/preset-env": "7.20.2", "@cypress/webpack-preprocessor": "5.17.0", - "@grafana/e2e-selectors": "9.5.0-pre", + "@grafana/e2e-selectors": "10.0.0-pre", "@grafana/tsconfig": "^1.2.0-rc1", "@mochajs/json-file-reporter": "^1.2.0", "babel-loader": "9.1.2", diff --git a/packages/grafana-e2e/src/flows/configurePanel.ts b/packages/grafana-e2e/src/flows/configurePanel.ts index 15d7abd8b2d..7181c06fa05 100644 --- a/packages/grafana-e2e/src/flows/configurePanel.ts +++ b/packages/grafana-e2e/src/flows/configurePanel.ts @@ -91,15 +91,15 @@ export const configurePanel = (config: PartialAddPanelConfig | PartialEditPanelC e2e.components.Panels.Panel.headerItems('Edit').click(); } else { try { - e2e.components.PageToolbar.item('Add panel').should('be.visible'); - e2e.components.PageToolbar.item('Add panel').click(); + e2e.components.PageToolbar.itemButton('Add panel button').should('be.visible'); + e2e.components.PageToolbar.itemButton('Add panel button').click(); } catch (e) { // Depending on the screen size, the "Add panel" button might be hidden e2e.components.PageToolbar.item('Show more items').click(); - e2e.components.PageToolbar.item('Add panel').last().click(); + e2e.components.PageToolbar.item('Add panel button').last().click(); } - e2e.pages.AddDashboard.addNewPanel().should('be.visible'); - e2e.pages.AddDashboard.addNewPanel().click(); + e2e.pages.AddDashboard.itemButton('Add new visualization menu item').should('be.visible'); + e2e.pages.AddDashboard.itemButton('Add new visualization menu item').click(); } if (timeRange) { diff --git a/packages/grafana-eslint-rules/package.json b/packages/grafana-eslint-rules/package.json index 22c00deb65c..45daca50272 100644 --- a/packages/grafana-eslint-rules/package.json +++ b/packages/grafana-eslint-rules/package.json @@ -1,7 +1,7 @@ { "name": "@grafana/eslint-plugin", "description": "ESLint rules for use within the Grafana repo. Not suitable (or supported) for external use.", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "main": "./index.cjs", "author": "Grafana Labs", "license": "Apache-2.0", diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index eb6e5f70c03..67798bf4475 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/runtime", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "description": "Grafana Runtime Library", "keywords": [ "grafana", @@ -37,10 +37,10 @@ "postpack": "mv package.json.bak package.json" }, "dependencies": { - "@grafana/data": "9.5.0-pre", - "@grafana/e2e-selectors": "9.5.0-pre", + "@grafana/data": "10.0.0-pre", + "@grafana/e2e-selectors": "10.0.0-pre", "@grafana/faro-web-sdk": "1.0.2", - "@grafana/ui": "9.5.0-pre", + "@grafana/ui": "10.0.0-pre", "@sentry/browser": "6.19.7", "history": "4.10.1", "lodash": "4.17.21", diff --git a/packages/grafana-runtime/src/services/backendSrv.ts b/packages/grafana-runtime/src/services/backendSrv.ts index 15671891069..341794835b9 100644 --- a/packages/grafana-runtime/src/services/backendSrv.ts +++ b/packages/grafana-runtime/src/services/backendSrv.ts @@ -96,6 +96,7 @@ export interface FetchResponse { readonly type: ResponseType; readonly url: string; readonly config: BackendSrvRequest; + readonly traceId?: string; } /** @@ -122,6 +123,7 @@ export interface FetchError { cancelled?: boolean; isHandled?: boolean; config: BackendSrvRequest; + traceId?: string; } export function isFetchError(e: unknown): e is FetchError { diff --git a/packages/grafana-runtime/src/utils/DataSourceWithBackend.test.ts b/packages/grafana-runtime/src/utils/DataSourceWithBackend.test.ts index f703528d10a..40b17f3fdb0 100644 --- a/packages/grafana-runtime/src/utils/DataSourceWithBackend.test.ts +++ b/packages/grafana-runtime/src/utils/DataSourceWithBackend.test.ts @@ -98,7 +98,7 @@ describe('DataSourceWithBackend', () => { "hideFromInspector": false, "method": "POST", "requestId": undefined, - "url": "/api/ds/query", + "url": "/api/ds/query?ds_type=dummy", } `); }); @@ -153,7 +153,7 @@ describe('DataSourceWithBackend', () => { "hideFromInspector": false, "method": "POST", "requestId": undefined, - "url": "/api/ds/query?expression=true", + "url": "/api/ds/query?ds_type=dummy&expression=true", } `); }); @@ -222,7 +222,7 @@ describe('DataSourceWithBackend', () => { "hideFromInspector": true, "method": "POST", "requestId": undefined, - "url": "/api/ds/query", + "url": "/api/ds/query?ds_type=dummy", } `); }); diff --git a/packages/grafana-runtime/src/utils/DataSourceWithBackend.ts b/packages/grafana-runtime/src/utils/DataSourceWithBackend.ts index 8b8b142948c..5b3793cfcbf 100644 --- a/packages/grafana-runtime/src/utils/DataSourceWithBackend.ts +++ b/packages/grafana-runtime/src/utils/DataSourceWithBackend.ts @@ -202,10 +202,16 @@ class DataSourceWithBackend< headers[PluginRequestHeaders.PluginID] = Array.from(pluginIDs).join(', '); headers[PluginRequestHeaders.DatasourceUID] = Array.from(dsUIDs).join(', '); - let url = '/api/ds/query'; + let url = '/api/ds/query?ds_type=' + this.type; + if (hasExpr) { headers[PluginRequestHeaders.FromExpression] = 'true'; - url += '?expression=true'; + url += '&expression=true'; + } + + // Appending request ID to url to facilitate client-side performance metrics. See #65244 for more context. + if (requestId) { + url += `&requestId=${requestId}`; } if (request.dashboardUID) { diff --git a/packages/grafana-runtime/src/utils/queryResponse.test.ts b/packages/grafana-runtime/src/utils/queryResponse.test.ts index 56be442fd27..adec09b9f9d 100644 --- a/packages/grafana-runtime/src/utils/queryResponse.test.ts +++ b/packages/grafana-runtime/src/utils/queryResponse.test.ts @@ -280,6 +280,82 @@ describe('Query Response parser', () => { expect(ids).toEqual(['A', 'B']); }); + test('should handle a success-response without traceIds', () => { + const input = { + data: { + results: { + A: { + frames: [], + }, + }, + }, + } as unknown as FetchResponse; + const res = toDataQueryResponse(input); + expect(res.traceIds).toBeUndefined(); + }); + + test('should handle a success-response with traceIds', () => { + const input = { + data: { + results: { + A: { + frames: [], + }, + }, + }, + traceId: 'traceId1', + } as unknown as FetchResponse; + const res = toDataQueryResponse(input); + expect(res.traceIds).toStrictEqual(['traceId1']); + }); + + test('should handle an error-response without traceIds', () => { + const input = { + data: { + results: { + A: { + error: 'error from A', + status: 400, + }, + B: { + error: 'error from B', + status: 400, + }, + }, + }, + } as unknown as FetchResponse; + const res = toDataQueryResponse(input); + expect(res.traceIds).toBeUndefined(); + expect(res.error?.traceId).toBeUndefined(); + expect(res.errors).toHaveLength(2); + expect(res.errors?.[0].traceId).toBeUndefined(); + expect(res.errors?.[1].traceId).toBeUndefined(); + }); + + test('should handle an error-response with traceIds', () => { + const input = { + data: { + results: { + A: { + error: 'error from A', + status: 400, + }, + B: { + error: 'error from B', + status: 400, + }, + }, + }, + traceId: 'traceId1', + } as unknown as FetchResponse; + const res = toDataQueryResponse(input); + expect(res.traceIds).toStrictEqual(['traceId1']); + expect(res.error?.traceId).toBe('traceId1'); + expect(res.errors).toHaveLength(2); + expect(res.errors?.[0].traceId).toBe('traceId1'); + expect(res.errors?.[1].traceId).toBe('traceId1'); + }); + describe('Cache notice', () => { let resp: FetchResponse; diff --git a/packages/grafana-runtime/src/utils/queryResponse.ts b/packages/grafana-runtime/src/utils/queryResponse.ts index 919c003ef03..707550f9909 100644 --- a/packages/grafana-runtime/src/utils/queryResponse.ts +++ b/packages/grafana-runtime/src/utils/queryResponse.ts @@ -65,6 +65,13 @@ export function toDataQueryResponse( queries?: DataQuery[] ): DataQueryResponse { const rsp: DataQueryResponse = { data: [], state: LoadingState.Done }; + + const traceId = 'traceId' in res ? res.traceId : undefined; + + if (traceId != null) { + rsp.traceIds = [traceId]; + } + // If the response isn't in a correct shape we just ignore the data and pass empty DataQueryResponse. if ((res as FetchResponse).data?.results) { const results = (res as FetchResponse).data.results; @@ -83,17 +90,21 @@ export function toDataQueryResponse( for (const dr of data) { if (dr.error) { + const errorObj: DataQueryError = { + refId: dr.refId, + message: dr.error, + status: dr.status, + }; + if (traceId != null) { + errorObj.traceId = traceId; + } if (!rsp.error) { - rsp.error = { - refId: dr.refId, - message: dr.error, - status: dr.status, - }; + rsp.error = { ...errorObj }; } if (rsp.errors) { - rsp.errors.push({ refId: dr.refId, message: dr.error, status: dr.status }); + rsp.errors.push({ ...errorObj }); } else { - rsp.errors = [{ refId: dr.refId, message: dr.error, status: dr.status }]; + rsp.errors = [{ ...errorObj }]; } rsp.state = LoadingState.Error; } diff --git a/packages/grafana-schema/package.json b/packages/grafana-schema/package.json index 542b6a1428a..0655787fd14 100644 --- a/packages/grafana-schema/package.json +++ b/packages/grafana-schema/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/schema", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "description": "Grafana Schema Library", "keywords": [ "typescript" diff --git a/packages/grafana-toolkit/package.json b/packages/grafana-toolkit/package.json index f0cefb49c9c..5637ed8f190 100644 --- a/packages/grafana-toolkit/package.json +++ b/packages/grafana-toolkit/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/toolkit", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "description": "Grafana Toolkit", "keywords": [ "grafana", @@ -51,10 +51,10 @@ "@babel/preset-env": "7.18.9", "@babel/preset-react": "7.18.6", "@babel/preset-typescript": "7.18.6", - "@grafana/data": "9.5.0-pre", + "@grafana/data": "10.0.0-pre", "@grafana/eslint-config": "5.1.0", "@grafana/tsconfig": "^1.2.0-rc1", - "@grafana/ui": "9.5.0-pre", + "@grafana/ui": "10.0.0-pre", "@jest/core": "27.5.1", "@types/command-exists": "^1.2.0", "@types/eslint": "8.4.1", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 570b58d2d7f..09febdfebd2 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/ui", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "description": "Grafana Components Library", "keywords": [ "grafana", @@ -49,10 +49,10 @@ "dependencies": { "@emotion/css": "11.10.6", "@emotion/react": "11.10.6", - "@grafana/data": "9.5.0-pre", - "@grafana/e2e-selectors": "9.5.0-pre", + "@grafana/data": "10.0.0-pre", + "@grafana/e2e-selectors": "10.0.0-pre", "@grafana/faro-web-sdk": "1.0.2", - "@grafana/schema": "9.5.0-pre", + "@grafana/schema": "10.0.0-pre", "@leeoniya/ufuzzy": "1.0.6", "@monaco-editor/react": "4.4.6", "@popperjs/core": "2.11.6", diff --git a/packages/grafana-ui/src/components/Badge/Badge.tsx b/packages/grafana-ui/src/components/Badge/Badge.tsx index d754a14b37e..e97bcd10526 100644 --- a/packages/grafana-ui/src/components/Badge/Badge.tsx +++ b/packages/grafana-ui/src/components/Badge/Badge.tsx @@ -7,7 +7,6 @@ import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '../../themes/ThemeContext'; import { IconName } from '../../types'; import { Icon } from '../Icon/Icon'; -import { HorizontalGroup } from '../Layout/Layout'; import { Tooltip } from '../Tooltip/Tooltip'; export type BadgeColor = 'blue' | 'red' | 'green' | 'orange' | 'purple'; @@ -23,10 +22,8 @@ export const Badge = React.memo(({ icon, color, text, tooltip, class const styles = useStyles2(useCallback((theme) => getStyles(theme, color), [color])); const badge = (
- - {icon && } - {text} - + {icon && } + {text}
); @@ -59,7 +56,6 @@ const getStyles = (theme: GrafanaTheme2, color: BadgeColor) => { return { wrapper: css` - font-size: ${theme.typography.size.sm}; display: inline-flex; padding: 1px 4px; border-radius: ${theme.shape.radius.default}; @@ -67,12 +63,10 @@ const getStyles = (theme: GrafanaTheme2, color: BadgeColor) => { border: 1px solid ${borderColor}; color: ${textColor}; font-weight: ${theme.typography.fontWeightRegular}; - - > span { - position: relative; - top: 1px; - margin-left: 2px; - } + gap: 2px; + font-size: ${theme.typography.bodySmall.fontSize}; + line-height: ${theme.typography.bodySmall.lineHeight}; + align-items: center; `, }; }; diff --git a/packages/grafana-ui/src/components/Dropdown/Dropdown.tsx b/packages/grafana-ui/src/components/Dropdown/Dropdown.tsx index 4bc664e75aa..21f1e28ed8c 100644 --- a/packages/grafana-ui/src/components/Dropdown/Dropdown.tsx +++ b/packages/grafana-ui/src/components/Dropdown/Dropdown.tsx @@ -11,7 +11,7 @@ import { TooltipPlacement } from '../Tooltip/types'; export interface Props { overlay: React.ReactElement | (() => React.ReactElement); placement?: TooltipPlacement; - children: React.ReactElement | ((isOpen: boolean) => React.ReactElement); + children: React.ReactElement; /** Amount in pixels to nudge the dropdown vertically and horizontally, respectively. */ offset?: [number, number]; onVisibleChange?: (state: boolean) => void; @@ -51,7 +51,7 @@ export const Dropdown = React.memo(({ children, overlay, placement, offset, onVi return ( <> - {React.cloneElement(typeof children === 'function' ? children(visible) : children, { + {React.cloneElement(children, { ref: setTriggerRef, })} {visible && ( diff --git a/packages/grafana-ui/src/components/Segment/Segment.tsx b/packages/grafana-ui/src/components/Segment/Segment.tsx index 5c7d2e1e881..fd8401c6c82 100644 --- a/packages/grafana-ui/src/components/Segment/Segment.tsx +++ b/packages/grafana-ui/src/components/Segment/Segment.tsx @@ -11,7 +11,7 @@ import { getSegmentStyles } from './styles'; import { SegmentSelect, useExpandableLabel, SegmentProps } from './'; -export interface SegmentSyncProps extends SegmentProps, Omit, 'value' | 'onChange'> { +export interface SegmentSyncProps extends SegmentProps, Omit, 'value' | 'onChange'> { value?: T | SelectableValue; onChange: (item: SelectableValue) => void; options: Array>; diff --git a/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx b/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx index 99e485027a3..5d9e90c8fbc 100644 --- a/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx +++ b/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx @@ -15,7 +15,7 @@ import { getSegmentStyles } from './styles'; import { useExpandableLabel, SegmentProps } from '.'; -export interface SegmentAsyncProps extends SegmentProps, Omit, 'value' | 'onChange'> { +export interface SegmentAsyncProps extends SegmentProps, Omit, 'value' | 'onChange'> { value?: T | SelectableValue; loadOptions: (query?: string) => Promise>>; /** diff --git a/packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx b/packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx index 68958c0e6cd..5f5516c86ad 100644 --- a/packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx +++ b/packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx @@ -100,12 +100,10 @@ export const InputWithAutoFocus = () => { ); }; -export const Basic: ComponentStory>> = ( - args: SegmentInputProps -) => { +export const Basic: ComponentStory> = (args: SegmentInputProps) => { const [value, setValue] = useState(args.value); - const props: SegmentInputProps = { + const props: SegmentInputProps = { ...args, value, onChange: (value) => { @@ -117,7 +115,7 @@ export const Basic: ComponentStory - {...props} /> + ); }; diff --git a/packages/grafana-ui/src/components/Segment/SegmentInput.tsx b/packages/grafana-ui/src/components/Segment/SegmentInput.tsx index acfaef89d9d..d4d3d581b00 100644 --- a/packages/grafana-ui/src/components/Segment/SegmentInput.tsx +++ b/packages/grafana-ui/src/components/Segment/SegmentInput.tsx @@ -10,8 +10,8 @@ import { getSegmentStyles } from './styles'; import { useExpandableLabel, SegmentProps } from '.'; -export interface SegmentInputProps - extends Omit, 'allowCustomValue' | 'allowEmptyValue'>, +export interface SegmentInputProps + extends Omit, Omit, 'value' | 'onChange'> { value: string | number; onChange: (text: string | number) => void; @@ -19,7 +19,7 @@ export interface SegmentInputProps const FONT_SIZE = 14; -export function SegmentInput({ +export function SegmentInput({ value: initialValue, onChange, Component, @@ -30,7 +30,7 @@ export function SegmentInput({ autofocus = false, onExpandedChange, ...rest -}: React.PropsWithChildren>) { +}: React.PropsWithChildren) { const ref = useRef(null); const [value, setValue] = useState(initialValue); const [inputWidth, setInputWidth] = useState(measureText((initialValue || '').toString(), FONT_SIZE).width); diff --git a/packages/grafana-ui/src/components/Segment/types.ts b/packages/grafana-ui/src/components/Segment/types.ts index 06cb23bef32..ec2d8756e82 100644 --- a/packages/grafana-ui/src/components/Segment/types.ts +++ b/packages/grafana-ui/src/components/Segment/types.ts @@ -1,6 +1,6 @@ import { ReactElement } from 'react'; -export interface SegmentProps { +export interface SegmentProps { Component?: ReactElement; className?: string; allowCustomValue?: boolean; diff --git a/packages/grafana-ui/src/components/VizLegend/SeriesIcon.tsx b/packages/grafana-ui/src/components/VizLegend/SeriesIcon.tsx index e65e8885687..937f61bf836 100644 --- a/packages/grafana-ui/src/components/VizLegend/SeriesIcon.tsx +++ b/packages/grafana-ui/src/components/VizLegend/SeriesIcon.tsx @@ -30,7 +30,7 @@ export const SeriesIcon = React.memo( background: cssColor, width: '14px', height: '4px', - borderRadius: theme.shape.radius.default, + borderRadius: theme.shape.radius.pill, display: 'inline-block', marginRight: '8px', }; diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts index dd7bb67e13c..f07a9c8c0cd 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts @@ -156,6 +156,11 @@ export class UPlotScaleBuilder extends PlotConfigBuilder { let minMax: uPlot.Range.MinMax = [dataMin, dataMax]; + // don't pad numeric x scales + if (scaleKey === 'x' && !isTime) { + return minMax; + } + // happens when all series on a scale are `show: false`, re-returning nulls will auto-disable axis if (!hasFixedRange && dataMin == null && dataMax == null) { return minMax; diff --git a/packages/grafana-ui/tsconfig.build.json b/packages/grafana-ui/tsconfig.build.json index 2ce1fd65c43..291f5a514af 100644 --- a/packages/grafana-ui/tsconfig.build.json +++ b/packages/grafana-ui/tsconfig.build.json @@ -5,6 +5,14 @@ "@grafana/ui": ["."] } }, - "exclude": ["**/*.story.tsx", "**/*.test.ts*", "**/*.tmpl.ts", "dist", "node_modules", "src/utils/storybook"], + "exclude": [ + "**/*.story.tsx", + "**/*.story.internal.tsx", + "**/*.test.ts*", + "**/*.tmpl.ts", + "dist", + "node_modules", + "src/utils/storybook" + ], "extends": "./tsconfig.json" } diff --git a/pkg/api/plugin_resource_test.go b/pkg/api/plugin_resource_test.go index cc37131b0a8..7c990f8a7e7 100644 --- a/pkg/api/plugin_resource_test.go +++ b/pkg/api/plugin_resource_test.go @@ -18,7 +18,6 @@ import ( "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin" "github.com/grafana/grafana/pkg/plugins/backendplugin/provider" - "github.com/grafana/grafana/pkg/plugins/config" pluginClient "github.com/grafana/grafana/pkg/plugins/manager/client" "github.com/grafana/grafana/pkg/plugins/manager/fakes" "github.com/grafana/grafana/pkg/plugins/manager/loader" @@ -34,6 +33,7 @@ import ( "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/oauthtoken/oauthtokentest" "github.com/grafana/grafana/pkg/services/pluginsintegration" + "github.com/grafana/grafana/pkg/services/pluginsintegration/config" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol" "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" pluginSettings "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service" @@ -59,13 +59,12 @@ func TestCallResource(t *testing.T) { coreRegistry := coreplugin.ProvideCoreRegistry(nil, &cloudwatch.CloudWatchService{}, nil, nil, nil, nil, nil, nil, nil, nil, testdatasource.ProvideService(cfg, featuremgmt.WithFeatures()), nil, nil, nil, nil, nil, nil) - var pCfg *config.Cfg - pCfg, err = config.ProvideConfig(setting.ProvideProvider(cfg), cfg) + pCfg, err := config.ProvideConfig(setting.ProvideProvider(cfg), cfg) require.NoError(t, err) reg := registry.ProvideService() - cdn := pluginscdn.ProvideService(pCfg) l := loader.ProvideService(pCfg, fakes.NewFakeLicensingService(), signature.NewUnsignedAuthorizer(pCfg), - reg, provider.ProvideService(coreRegistry), finder.NewLocalFinder(), fakes.NewFakeRoleRegistry(), cdn, assetpath.ProvideService(cdn)) + reg, provider.ProvideService(coreRegistry), finder.NewLocalFinder(), fakes.NewFakeRoleRegistry(), + assetpath.ProvideService(pluginscdn.ProvideService(pCfg))) srcs := sources.ProvideService(cfg, pCfg) ps, err := store.ProvideService(reg, srcs, l) require.NoError(t, err) diff --git a/pkg/build/packaging/grafana.go b/pkg/build/packaging/grafana.go index 4239af6f6f7..d752feed724 100644 --- a/pkg/build/packaging/grafana.go +++ b/pkg/build/packaging/grafana.go @@ -771,8 +771,7 @@ func realPackageVariant(ctx context.Context, v config.Variant, edition config.Ed defaultFileSrc: filepath.Join(grafanaDir, "packaging", "rpm", "sysconfig", "grafana-server"), systemdFileSrc: filepath.Join(grafanaDir, "packaging", "rpm", "systemd", "grafana-server.service"), wrapperFilePath: filepath.Join(grafanaDir, "packaging", "wrappers"), - // chkconfig is depended on since our systemd service wraps a SysV init script, and that requires chkconfig - depends: []string{"/sbin/service", "chkconfig", "fontconfig", "freetype", "urw-fonts"}, + depends: []string{"/sbin/service", "fontconfig", "freetype", "urw-fonts"}, }); err != nil { return err } diff --git a/pkg/infra/db/sqlbuilder.go b/pkg/infra/db/sqlbuilder.go index 1b3c8427879..8d55f41fa7c 100644 --- a/pkg/infra/db/sqlbuilder.go +++ b/pkg/infra/db/sqlbuilder.go @@ -5,20 +5,26 @@ import ( ac "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/services/sqlstore/permissions" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" ) -func NewSqlBuilder(cfg *setting.Cfg, dialect migrator.Dialect) SQLBuilder { - return SQLBuilder{cfg: cfg, dialect: dialect} +func NewSqlBuilder(cfg *setting.Cfg, features featuremgmt.FeatureToggles, dialect migrator.Dialect, recursiveQueriesAreSupported bool) SQLBuilder { + return SQLBuilder{cfg: cfg, features: features, dialect: dialect, recursiveQueriesAreSupported: recursiveQueriesAreSupported} } type SQLBuilder struct { - cfg *setting.Cfg - sql bytes.Buffer - params []interface{} + cfg *setting.Cfg + features featuremgmt.FeatureToggles + sql bytes.Buffer + params []interface{} + recQry string + recQryParams []interface{} + recursiveQueriesAreSupported bool + dialect migrator.Dialect } @@ -31,10 +37,22 @@ func (sb *SQLBuilder) Write(sql string, params ...interface{}) { } func (sb *SQLBuilder) GetSQLString() string { - return sb.sql.String() + if sb.recQry == "" { + return sb.sql.String() + } + + var bf bytes.Buffer + bf.WriteString(sb.recQry) + bf.WriteString(sb.sql.String()) + return bf.String() } func (sb *SQLBuilder) GetParams() []interface{} { + if len(sb.recQryParams) == 0 { + return sb.params + } + + sb.params = append(sb.recQryParams, sb.params...) return sb.params } @@ -44,11 +62,15 @@ func (sb *SQLBuilder) AddParams(params ...interface{}) { func (sb *SQLBuilder) WriteDashboardPermissionFilter(user *user.SignedInUser, permission dashboards.PermissionType) { var ( - sql string - params []interface{} + sql string + params []interface{} + recQry string + recQryParams []interface{} ) if !ac.IsDisabled(sb.cfg) { - sql, params = permissions.NewAccessControlDashboardPermissionFilter(user, permission, "").Where() + filterRBAC := permissions.NewAccessControlDashboardPermissionFilter(user, permission, "", sb.features, sb.recursiveQueriesAreSupported) + sql, params = filterRBAC.Where() + recQry, recQryParams = filterRBAC.With() } else { sql, params = permissions.DashboardPermissionFilter{ OrgRole: user.OrgRole, @@ -61,4 +83,6 @@ func (sb *SQLBuilder) WriteDashboardPermissionFilter(user *user.SignedInUser, pe sb.sql.WriteString(" AND " + sql) sb.params = append(sb.params, params...) + sb.recQry = recQry + sb.recQryParams = recQryParams } diff --git a/pkg/infra/db/sqlbuilder_test.go b/pkg/infra/db/sqlbuilder_test.go index ce88c870a56..0d1f3e45ba4 100644 --- a/pkg/infra/db/sqlbuilder_test.go +++ b/pkg/infra/db/sqlbuilder_test.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/services/dashboards" dashver "github.com/grafana/grafana/pkg/services/dashboardversion" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/user" @@ -24,6 +25,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } + t.Run("WriteDashboardPermissionFilter", func(t *testing.T) { t.Run("user ACL", func(t *testing.T) { test(t, @@ -31,6 +33,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW}, Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_VIEW}, shouldFind, + featuremgmt.WithFeatures(), ) test(t, @@ -38,6 +41,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW}, Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT}, shouldNotFind, + featuremgmt.WithFeatures(), ) test(t, @@ -45,6 +49,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{User: true, Permission: dashboards.PERMISSION_EDIT}, Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT}, shouldFind, + featuremgmt.WithFeatures(), ) test(t, @@ -52,6 +57,41 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW}, Search{RequiredPermission: dashboards.PERMISSION_VIEW}, shouldNotFind, + featuremgmt.WithFeatures(), + ) + }) + + t.Run("user ACL with nested folders", func(t *testing.T) { + test(t, + DashboardProps{}, + &DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW}, + Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_VIEW}, + shouldFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{}, + &DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW}, + Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT}, + shouldNotFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{}, + &DashboardPermission{User: true, Permission: dashboards.PERMISSION_EDIT}, + Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT}, + shouldFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{}, + &DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW}, + Search{RequiredPermission: dashboards.PERMISSION_VIEW}, + shouldNotFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), ) }) @@ -61,6 +101,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{Role: org.RoleViewer, Permission: dashboards.PERMISSION_VIEW}, Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, shouldFind, + featuremgmt.WithFeatures(), ) test(t, @@ -68,6 +109,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{Role: org.RoleViewer, Permission: dashboards.PERMISSION_VIEW}, Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_EDIT}, shouldNotFind, + featuremgmt.WithFeatures(), ) test(t, @@ -75,6 +117,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{Role: org.RoleEditor, Permission: dashboards.PERMISSION_VIEW}, Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, shouldNotFind, + featuremgmt.WithFeatures(), ) test(t, @@ -82,6 +125,41 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{Role: org.RoleEditor, Permission: dashboards.PERMISSION_VIEW}, Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, shouldNotFind, + featuremgmt.WithFeatures(), + ) + }) + + t.Run("role ACL with nested folders", func(t *testing.T) { + test(t, + DashboardProps{}, + &DashboardPermission{Role: org.RoleViewer, Permission: dashboards.PERMISSION_VIEW}, + Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, + shouldFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{}, + &DashboardPermission{Role: org.RoleViewer, Permission: dashboards.PERMISSION_VIEW}, + Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_EDIT}, + shouldNotFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{}, + &DashboardPermission{Role: org.RoleEditor, Permission: dashboards.PERMISSION_VIEW}, + Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, + shouldNotFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{}, + &DashboardPermission{Role: org.RoleEditor, Permission: dashboards.PERMISSION_VIEW}, + Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, + shouldNotFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), ) }) @@ -91,6 +169,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{Team: true, Permission: dashboards.PERMISSION_VIEW}, Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_VIEW}, shouldFind, + featuremgmt.WithFeatures(), ) test(t, @@ -98,6 +177,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{Team: true, Permission: dashboards.PERMISSION_VIEW}, Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT}, shouldNotFind, + featuremgmt.WithFeatures(), ) test(t, @@ -105,6 +185,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{Team: true, Permission: dashboards.PERMISSION_EDIT}, Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT}, shouldFind, + featuremgmt.WithFeatures(), ) test(t, @@ -112,6 +193,41 @@ func TestIntegrationSQLBuilder(t *testing.T) { &DashboardPermission{Team: true, Permission: dashboards.PERMISSION_EDIT}, Search{UserFromACL: false, RequiredPermission: dashboards.PERMISSION_EDIT}, shouldNotFind, + featuremgmt.WithFeatures(), + ) + }) + + t.Run("team ACL with nested folders", func(t *testing.T) { + test(t, + DashboardProps{}, + &DashboardPermission{Team: true, Permission: dashboards.PERMISSION_VIEW}, + Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_VIEW}, + shouldFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{}, + &DashboardPermission{Team: true, Permission: dashboards.PERMISSION_VIEW}, + Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT}, + shouldNotFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{}, + &DashboardPermission{Team: true, Permission: dashboards.PERMISSION_EDIT}, + Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT}, + shouldFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{}, + &DashboardPermission{Team: true, Permission: dashboards.PERMISSION_EDIT}, + Search{UserFromACL: false, RequiredPermission: dashboards.PERMISSION_EDIT}, + shouldNotFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), ) }) @@ -121,6 +237,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { nil, Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, shouldNotFind, + featuremgmt.WithFeatures(), ) test(t, @@ -128,6 +245,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { nil, Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, shouldFind, + featuremgmt.WithFeatures(), ) test(t, @@ -135,6 +253,7 @@ func TestIntegrationSQLBuilder(t *testing.T) { nil, Search{OrgId: -1, UsersOrgRole: org.RoleEditor, RequiredPermission: dashboards.PERMISSION_EDIT}, shouldFind, + featuremgmt.WithFeatures(), ) test(t, @@ -142,6 +261,41 @@ func TestIntegrationSQLBuilder(t *testing.T) { nil, Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_EDIT}, shouldNotFind, + featuremgmt.WithFeatures(), + ) + }) + + t.Run("defaults for user ACL with nested folders", func(t *testing.T) { + test(t, + DashboardProps{}, + nil, + Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, + shouldNotFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{OrgId: -1}, + nil, + Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW}, + shouldFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{OrgId: -1}, + nil, + Search{OrgId: -1, UsersOrgRole: org.RoleEditor, RequiredPermission: dashboards.PERMISSION_EDIT}, + shouldFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), + ) + + test(t, + DashboardProps{OrgId: -1}, + nil, + Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_EDIT}, + shouldNotFind, + featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)), ) }) }) @@ -172,7 +326,7 @@ type dashboardResponse struct { Id int64 } -func test(t *testing.T, dashboardProps DashboardProps, dashboardPermission *DashboardPermission, search Search, shouldFind bool) { +func test(t *testing.T, dashboardProps DashboardProps, dashboardPermission *DashboardPermission, search Search, shouldFind bool, features featuremgmt.FeatureToggles) { t.Helper() t.Run("", func(t *testing.T) { @@ -186,7 +340,7 @@ func test(t *testing.T, dashboardProps DashboardProps, dashboardPermission *Dash aclUserID = createDummyACL(t, sqlStore, dashboardPermission, search, dashboard.ID) t.Logf("Created ACL with user ID %d\n", aclUserID) } - dashboards := getDashboards(t, sqlStore, search, aclUserID) + dashboards := getDashboards(t, sqlStore, search, aclUserID, features) if shouldFind { require.Len(t, dashboards, 1, "Should return one dashboard") @@ -292,7 +446,7 @@ func createDummyACL(t *testing.T, sqlStore *sqlstore.SQLStore, dashboardPermissi return 0 } -func getDashboards(t *testing.T, sqlStore *sqlstore.SQLStore, search Search, aclUserID int64) []*dashboardResponse { +func getDashboards(t *testing.T, sqlStore *sqlstore.SQLStore, search Search, aclUserID int64, features featuremgmt.FeatureToggles) []*dashboardResponse { t.Helper() old := sqlStore.Cfg.RBACEnabled @@ -301,7 +455,10 @@ func getDashboards(t *testing.T, sqlStore *sqlstore.SQLStore, search Search, acl sqlStore.Cfg.RBACEnabled = old }() - builder := NewSqlBuilder(sqlStore.Cfg, sqlStore.GetDialect()) + recursiveQueriesAreSupported, err := sqlStore.RecursiveQueriesAreSupported() + require.NoError(t, err) + + builder := NewSqlBuilder(sqlStore.Cfg, features, sqlStore.GetDialect(), recursiveQueriesAreSupported) signedInUser := &user.SignedInUser{ UserID: 9999999999, } @@ -325,7 +482,7 @@ func getDashboards(t *testing.T, sqlStore *sqlstore.SQLStore, search Search, acl builder.Write("SELECT * FROM dashboard WHERE true") builder.WriteDashboardPermissionFilter(signedInUser, search.RequiredPermission) t.Logf("Searching for dashboards, SQL: %q\n", builder.GetSQLString()) - err := sqlStore.GetEngine().SQL(builder.GetSQLString(), builder.params...).Find(&res) + err = sqlStore.GetEngine().SQL(builder.GetSQLString(), builder.params...).Find(&res) require.NoError(t, err) return res } diff --git a/pkg/infra/remotecache/memcached_storage_integration_test.go b/pkg/infra/remotecache/memcached_storage_integration_test.go index 87fffe182eb..38bf6fc12ea 100644 --- a/pkg/infra/remotecache/memcached_storage_integration_test.go +++ b/pkg/infra/remotecache/memcached_storage_integration_test.go @@ -1,16 +1,23 @@ -//go:build memcached -// +build memcached - package remotecache import ( + "os" "testing" "github.com/grafana/grafana/pkg/setting" ) -func TestMemcachedCacheStorage(t *testing.T) { - opts := &setting.RemoteCacheOptions{Name: memcachedCacheType, ConnStr: "localhost:11211"} +func TestIntegrationMemcachedCacheStorage(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + u, ok := os.LookupEnv("MEMCACHED_HOSTS") + if !ok || u == "" { + t.Skip("No Memcached hosts provided") + } + + opts := &setting.RemoteCacheOptions{Name: memcachedCacheType, ConnStr: u} client := createTestClient(t, opts, nil) runTestsForClient(t, client) runCountTestsForClient(t, opts, nil) diff --git a/pkg/infra/remotecache/redis_storage_integration_test.go b/pkg/infra/remotecache/redis_storage_integration_test.go index d360feb3ce8..392d3bb8b44 100644 --- a/pkg/infra/remotecache/redis_storage_integration_test.go +++ b/pkg/infra/remotecache/redis_storage_integration_test.go @@ -1,17 +1,40 @@ -//go:build redis -// +build redis - package remotecache import ( + "fmt" + "os" + "strings" "testing" + "github.com/go-redis/redis/v8" "github.com/grafana/grafana/pkg/setting" ) -func TestRedisCacheStorage(t *testing.T) { +func TestIntegrationRedisCacheStorage(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } - opts := &setting.RemoteCacheOptions{Name: redisCacheType, ConnStr: "addr=localhost:6379"} + u, ok := os.LookupEnv("REDIS_URL") + if !ok || u == "" { + t.Skip("No redis URL supplied") + } + + addr := u + db := 0 + parsed, err := redis.ParseURL(u) + if err == nil { + addr = parsed.Addr + db = parsed.DB + } + + b := strings.Builder{} + b.WriteString(fmt.Sprintf("addr=%s", addr)) + if db != 0 { + b.WriteString(fmt.Sprintf(",db=%d", db)) + } + + opts := &setting.RemoteCacheOptions{Name: redisCacheType, ConnStr: b.String()} client := createTestClient(t, opts, nil) runTestsForClient(t, client) runCountTestsForClient(t, opts, nil) diff --git a/pkg/infra/remotecache/remotecache_test.go b/pkg/infra/remotecache/remotecache_test.go index 9ad5acbe7a8..9732e8474cd 100644 --- a/pkg/infra/remotecache/remotecache_test.go +++ b/pkg/infra/remotecache/remotecache_test.go @@ -95,7 +95,8 @@ func canPutGetAndDeleteCachedObjects(t *testing.T, client CacheStorage) { assert.Equal(t, err, nil) _, err = client.Get(context.Background(), "key1") - assert.Equal(t, err, ErrCacheItemNotFound) + // redis client returns redis.Nil error when key does not exist. + assert.Error(t, err) } func canNotFetchExpiredItems(t *testing.T, client CacheStorage) { @@ -109,7 +110,8 @@ func canNotFetchExpiredItems(t *testing.T, client CacheStorage) { // should not be able to read that value since its expired _, err = client.Get(context.Background(), "key1") - assert.Equal(t, err, ErrCacheItemNotFound) + // redis client returns redis.Nil error when key does not exist. + assert.Error(t, err) } func TestCollectUsageStats(t *testing.T) { diff --git a/pkg/infra/tracing/opentelemetry_tracing.go b/pkg/infra/tracing/opentelemetry_tracing.go index 17620b922a4..8535233b8eb 100644 --- a/pkg/infra/tracing/opentelemetry_tracing.go +++ b/pkg/infra/tracing/opentelemetry_tracing.go @@ -105,6 +105,10 @@ func (ots *Opentelemetry) parseSettingsOpentelemetry() error { return nil } +func (ots *Opentelemetry) OTelExporterEnabled() bool { + return ots.Enabled == otlpExporter +} + func splitCustomAttribs(s string) ([]attribute.KeyValue, error) { res := []attribute.KeyValue{} @@ -320,3 +324,15 @@ func (s OpentelemetrySpan) AddEvents(keys []string, values []EventValue) { } } } + +func (s OpentelemetrySpan) contextWithSpan(ctx context.Context) context.Context { + if s.span != nil { + ctx = trace.ContextWithSpan(ctx, s.span) + // Grafana also manages its own separate traceID in the context in addition to what opentracing handles. + // It's derived from the span. Ensure that we propagate this too. + if traceID := s.span.SpanContext().TraceID(); traceID.IsValid() { + ctx = context.WithValue(ctx, traceKey{}, traceValue{traceID.String(), s.span.SpanContext().IsSampled()}) + } + } + return ctx +} diff --git a/pkg/infra/tracing/test_helper.go b/pkg/infra/tracing/test_helper.go index c8e4a646409..19894f2adce 100644 --- a/pkg/infra/tracing/test_helper.go +++ b/pkg/infra/tracing/test_helper.go @@ -92,6 +92,10 @@ func (t *FakeSpan) AddEvents(keys []string, values []EventValue) { } } +func (t *FakeSpan) contextWithSpan(ctx context.Context) context.Context { + return ctx +} + type FakeTracer struct { Spans []*FakeSpan } diff --git a/pkg/infra/tracing/tracing.go b/pkg/infra/tracing/tracing.go index 7463931847e..145f540b1a4 100644 --- a/pkg/infra/tracing/tracing.go +++ b/pkg/infra/tracing/tracing.go @@ -76,6 +76,10 @@ type Span interface { // // Panics if the length of keys is shorter than the length of values. AddEvents(keys []string, values []EventValue) + + // contextWithSpan returns a context.Context that holds the parent + // context plus a reference to this span. + contextWithSpan(ctx context.Context) context.Context } func ProvideService(cfg *setting.Cfg) (Tracer, error) { @@ -146,6 +150,29 @@ func TraceIDFromContext(c context.Context, requireSampled bool) string { return "" } +// SpanFromContext returns the Span previously associated with ctx, or nil, if no such span could be found. +// It is the equivalent of opentracing.SpanFromContext and trace.SpanFromContext. +func SpanFromContext(ctx context.Context) Span { + // Look for both opentracing and opentelemetry spans. + if span := opentracing.SpanFromContext(ctx); span != nil { + return OpentracingSpan{span: span} + } + if span := trace.SpanFromContext(ctx); span != nil { + return OpentelemetrySpan{span: span} + } + return nil +} + +// ContextWithSpan returns a new context.Context that holds a reference to the given span. +// If span is nil, a new context without an active span is returned. +// It is the equivalent of opentracing.ContextWithSpan and trace.ContextWithSpan. +func ContextWithSpan(ctx context.Context, span Span) context.Context { + if span != nil { + return span.contextWithSpan(ctx) + } + return ctx +} + type Opentracing struct { enabled bool address string @@ -324,6 +351,18 @@ func (s OpentracingSpan) AddEvents(keys []string, values []EventValue) { s.span.LogFields(fields...) } +func (s OpentracingSpan) contextWithSpan(ctx context.Context) context.Context { + if s.span != nil { + ctx = opentracing.ContextWithSpan(ctx, s.span) + // Grafana also manages its own separate traceID in the context in addition to what opentracing handles. + // It's derived from the span. Ensure that we propagate this too. + if sctx, ok := s.span.Context().(jaeger.SpanContext); ok { + ctx = context.WithValue(ctx, traceKey{}, traceValue{sctx.TraceID().String(), sctx.IsSampled()}) + } + } + return ctx +} + func splitTagSettings(input string) map[string]string { res := map[string]string{} diff --git a/pkg/login/social/generic_oauth.go b/pkg/login/social/generic_oauth.go index 3eb9e76490e..637d0b6f765 100644 --- a/pkg/login/social/generic_oauth.go +++ b/pkg/login/social/generic_oauth.go @@ -76,6 +76,7 @@ func (s *SocialGenericOAuth) IsOrganizationMember(client *http.Client) bool { } type UserInfoJson struct { + Sub string `json:"sub"` Name string `json:"name"` DisplayName string `json:"display_name"` Login string `json:"login"` @@ -108,31 +109,16 @@ func (s *SocialGenericOAuth) UserInfo(client *http.Client, token *oauth2.Token) for _, data := range toCheck { s.log.Debug("Processing external user info", "source", data.source, "data", data) + if userInfo.Id == "" { + userInfo.Id = data.Sub + } + if userInfo.Name == "" { userInfo.Name = s.extractUserName(data) } if userInfo.Login == "" { - if data.Login != "" { - s.log.Debug("Setting user info login from login field", "login", data.Login) - userInfo.Login = data.Login - } else { - if s.loginAttributePath != "" { - s.log.Debug("Searching for login among JSON", "loginAttributePath", s.loginAttributePath) - login, err := s.searchJSONForStringAttr(s.loginAttributePath, data.rawJSON) - if err != nil { - s.log.Error("Failed to search JSON for login attribute", "error", err) - } else if login != "" { - userInfo.Login = login - s.log.Debug("Setting user info login from login field", "login", login) - } - } - - if userInfo.Login == "" && data.Username != "" { - s.log.Debug("Setting user info login from username field", "username", data.Username) - userInfo.Login = data.Username - } - } + userInfo.Login = s.extractLogin(data) } if userInfo.Email == "" { @@ -338,6 +324,32 @@ func (s *SocialGenericOAuth) extractEmail(data *UserInfoJson) string { return "" } +func (s *SocialGenericOAuth) extractLogin(data *UserInfoJson) string { + if data.Login != "" { + s.log.Debug("Setting user info login from login field", "login", data.Login) + return data.Login + } + + if s.loginAttributePath != "" { + s.log.Debug("Searching for login among JSON", "loginAttributePath", s.loginAttributePath) + login, err := s.searchJSONForStringAttr(s.loginAttributePath, data.rawJSON) + if err != nil { + s.log.Error("Failed to search JSON for login attribute", "error", err) + } + + if login != "" { + return login + } + } + + if data.Username != "" { + s.log.Debug("Setting user info login from username field", "username", data.Username) + return data.Username + } + + return "" +} + func (s *SocialGenericOAuth) extractUserName(data *UserInfoJson) string { if s.nameAttributePath != "" { name, err := s.searchJSONForStringAttr(s.nameAttributePath, data.rawJSON) diff --git a/pkg/middleware/middleware.go b/pkg/middleware/middleware.go index 4980d7cb2a4..eb4861dbbeb 100644 --- a/pkg/middleware/middleware.go +++ b/pkg/middleware/middleware.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/grafana/grafana/pkg/infra/tracing" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/setting" @@ -29,12 +30,18 @@ func AddDefaultResponseHeaders(cfg *setting.Cfg) web.Handler { t := web.NewTree() t.Add("/api/datasources/uid/:uid/resources/*", nil) t.Add("/api/datasources/:id/resources/*", nil) + return func(c *web.Context) { c.Resp.Before(func(w web.ResponseWriter) { // if response has already been written, skip. if w.Written() { return } + traceId := tracing.TraceIDFromContext(c.Req.Context(), false) + if traceId != "" { + w.Header().Set("grafana-trace-id", traceId) + } + _, _, resourceURLMatch := t.Match(c.Req.URL.Path) resourceCachable := resourceURLMatch && allowCacheControl(c.Resp) if !strings.HasPrefix(c.Req.URL.Path, "/public/plugins/") && diff --git a/pkg/plugins/config/config.go b/pkg/plugins/config/config.go index e2797f79e93..c1509453d47 100644 --- a/pkg/plugins/config/config.go +++ b/pkg/plugins/config/config.go @@ -1,9 +1,6 @@ package config import ( - "fmt" - "strings" - "github.com/grafana/grafana-azure-sdk-go/azsettings" "github.com/grafana/grafana/pkg/plugins/log" @@ -33,63 +30,24 @@ type Cfg struct { PluginsCDNURLTemplate string - Opentelemetry OpentelemetryCfg + Tracing Tracing } -func ProvideConfig(settingProvider setting.Provider, grafanaCfg *setting.Cfg) (*Cfg, error) { - return NewCfg(settingProvider, grafanaCfg) -} - -func NewCfg(settingProvider setting.Provider, grafanaCfg *setting.Cfg) (*Cfg, error) { - logger := log.New("plugin.cfg") - - aws := settingProvider.Section("aws") - plugins := settingProvider.Section("plugins") - - allowedUnsigned := grafanaCfg.PluginsAllowUnsigned - if len(plugins.KeyValue("allow_loading_unsigned_plugins").Value()) > 0 { - allowedUnsigned = strings.Split(plugins.KeyValue("allow_loading_unsigned_plugins").Value(), ",") - } - - allowedAuth := grafanaCfg.AWSAllowedAuthProviders - if len(aws.KeyValue("allowed_auth_providers").Value()) > 0 { - allowedUnsigned = strings.Split(settingProvider.KeyValue("plugins", "allow_loading_unsigned_plugins").Value(), ",") - } - - otelCfg, err := NewOpentelemetryCfg(grafanaCfg) - if err != nil { - return nil, fmt.Errorf("new opentelemetry cfg: %w", err) - } +func NewCfg(devMode bool, pluginsPath string, pluginSettings setting.PluginSettings, pluginsAllowUnsigned []string, + awsAllowedAuthProviders []string, awsAssumeRoleEnabled bool, azure *azsettings.AzureSettings, grafanaVersion string, + logDatasourceRequests bool, pluginsCDNURLTemplate string, tracing Tracing) *Cfg { return &Cfg{ - log: logger, - PluginsPath: grafanaCfg.PluginsPath, - BuildVersion: grafanaCfg.BuildVersion, - DevMode: settingProvider.KeyValue("", "app_mode").MustBool(grafanaCfg.Env == setting.Dev), - PluginSettings: extractPluginSettings(settingProvider), - PluginsAllowUnsigned: allowedUnsigned, - AWSAllowedAuthProviders: allowedAuth, - AWSAssumeRoleEnabled: aws.KeyValue("assume_role_enabled").MustBool(grafanaCfg.AWSAssumeRoleEnabled), - Azure: grafanaCfg.Azure, - LogDatasourceRequests: grafanaCfg.PluginLogBackendRequests, - PluginsCDNURLTemplate: grafanaCfg.PluginsCDNURLTemplate, - Opentelemetry: otelCfg, - }, nil -} - -func extractPluginSettings(settingProvider setting.Provider) setting.PluginSettings { - ps := setting.PluginSettings{} - for sectionName, sectionCopy := range settingProvider.Current() { - if !strings.HasPrefix(sectionName, "plugin.") { - continue - } - // Calling Current() returns a redacted version of section. We need to replace the map values with the unredacted values. - section := settingProvider.Section(sectionName) - for k := range sectionCopy { - sectionCopy[k] = section.KeyValue(k).MustString("") - } - pluginID := strings.Replace(sectionName, "plugin.", "", 1) - ps[pluginID] = sectionCopy + log: log.New("plugin.cfg"), + PluginsPath: pluginsPath, + BuildVersion: grafanaVersion, + DevMode: devMode, + PluginSettings: pluginSettings, + PluginsAllowUnsigned: pluginsAllowUnsigned, + AWSAllowedAuthProviders: awsAllowedAuthProviders, + AWSAssumeRoleEnabled: awsAssumeRoleEnabled, + Azure: azure, + LogDatasourceRequests: logDatasourceRequests, + PluginsCDNURLTemplate: pluginsCDNURLTemplate, + Tracing: tracing, } - - return ps } diff --git a/pkg/plugins/config/tracing.go b/pkg/plugins/config/tracing.go index 704ff0b6927..8ea7615d332 100644 --- a/pkg/plugins/config/tracing.go +++ b/pkg/plugins/config/tracing.go @@ -1,38 +1,17 @@ package config -import ( - "fmt" +type Tracing struct { + OpenTelemetry OpenTelemetryCfg +} - "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/setting" -) - -const otlpExporter string = "otlp" - -// OpentelemetryCfg contains the Opentelemetry address and propagation config values. -// This is used to export the Opentelemetry (OTLP) config without exposing the whole *setting.Cfg. -type OpentelemetryCfg struct { +// OpenTelemetryCfg contains the OpenTelemetry address and propagation config values. +// This is used to export the OpenTelemetry (OTLP) config without exposing the whole *setting.Cfg. +type OpenTelemetryCfg struct { Address string Propagation string } // IsEnabled returns true if OTLP tracing is enabled (address set) -func (c OpentelemetryCfg) IsEnabled() bool { - return c.Address != "" -} - -// NewOpentelemetryCfg creates a new OpentelemetryCfg based on the provided Grafana config. -// If Opentelemetry (OTLP) is disabled, a zero-value OpentelemetryCfg is returned. -func NewOpentelemetryCfg(grafanaCfg *setting.Cfg) (OpentelemetryCfg, error) { - ots, err := tracing.ParseSettingsOpentelemetry(grafanaCfg) - if err != nil { - return OpentelemetryCfg{}, fmt.Errorf("parse settings: %w", err) - } - if ots.Enabled != otlpExporter { - return OpentelemetryCfg{}, nil - } - return OpentelemetryCfg{ - Address: ots.Address, - Propagation: ots.Propagation, - }, nil +func (t Tracing) IsEnabled() bool { + return t.OpenTelemetry.Address != "" } diff --git a/pkg/plugins/manager/loader/initializer/initializer.go b/pkg/plugins/manager/loader/initializer/initializer.go index 1b7c8b7c795..39afb5be578 100644 --- a/pkg/plugins/manager/loader/initializer/initializer.go +++ b/pkg/plugins/manager/loader/initializer/initializer.go @@ -70,14 +70,14 @@ func (i *Initializer) envVars(plugin *plugins.Plugin) []string { if v, exists := i.cfg.PluginSettings[plugin.ID]["tracing"]; exists { pluginTracingEnabled = v == "true" } - if i.cfg.Opentelemetry.IsEnabled() && pluginTracingEnabled { + if i.cfg.Tracing.IsEnabled() && pluginTracingEnabled { if plugin.Info.Version != "" { hostEnv = append(hostEnv, fmt.Sprintf("GF_PLUGIN_VERSION=%s", plugin.Info.Version)) } hostEnv = append( hostEnv, - fmt.Sprintf("GF_INSTANCE_OTLP_ADDRESS=%s", i.cfg.Opentelemetry.Address), - fmt.Sprintf("GF_INSTANCE_OTLP_PROPAGATION=%s", i.cfg.Opentelemetry.Propagation), + fmt.Sprintf("GF_INSTANCE_OTLP_ADDRESS=%s", i.cfg.Tracing.OpenTelemetry.Address), + fmt.Sprintf("GF_INSTANCE_OTLP_PROPAGATION=%s", i.cfg.Tracing.OpenTelemetry.Propagation), ) } diff --git a/pkg/plugins/manager/loader/initializer/initializer_test.go b/pkg/plugins/manager/loader/initializer/initializer_test.go index d9d7a49692a..010998da890 100644 --- a/pkg/plugins/manager/loader/initializer/initializer_test.go +++ b/pkg/plugins/manager/loader/initializer/initializer_test.go @@ -185,7 +185,7 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { JSONData: plugins.JSONData{ID: pluginID}, } - defaultOtelCfg := config.OpentelemetryCfg{ + defaultOTelCfg := config.OpenTelemetryCfg{ Address: "127.0.0.1:4317", Propagation: "", } @@ -250,7 +250,7 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "otel not configured", cfg: &config.Cfg{ - Opentelemetry: config.OpentelemetryCfg{}, + Tracing: config.Tracing{}, }, plugin: defaultPlugin, exp: expNoTracing, @@ -258,7 +258,7 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "otel not configured but plugin-tracing enabled", cfg: &config.Cfg{ - Opentelemetry: config.OpentelemetryCfg{}, + Tracing: config.Tracing{}, PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, }, plugin: defaultPlugin, @@ -267,7 +267,9 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "otlp no propagation plugin enabled", cfg: &config.Cfg{ - Opentelemetry: defaultOtelCfg, + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, PluginSettings: map[string]map[string]string{ pluginID: {"tracing": "true"}, }, @@ -278,7 +280,9 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "otlp no propagation disabled by default", cfg: &config.Cfg{ - Opentelemetry: defaultOtelCfg, + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, }, plugin: defaultPlugin, exp: expNoTracing, @@ -286,9 +290,11 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "otlp propagation plugin enabled", cfg: &config.Cfg{ - Opentelemetry: config.OpentelemetryCfg{ - Address: "127.0.0.1:4317", - Propagation: "w3c", + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{ + Address: "127.0.0.1:4317", + Propagation: "w3c", + }, }, PluginSettings: map[string]map[string]string{ pluginID: {"tracing": "true"}, @@ -304,12 +310,37 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { assert.Equal(t, "GF_INSTANCE_OTLP_PROPAGATION=w3c", envVars[4]) }, }, + { + name: "otlp enabled composite propagation", + cfg: &config.Cfg{ + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{ + Address: "127.0.0.1:4317", + Propagation: "w3c,jaeger", + }, + }, + PluginSettings: map[string]map[string]string{ + pluginID: {"tracing": "true"}, + }, + }, + plugin: defaultPlugin, + exp: func(t *testing.T, envVars []string) { + assert.Len(t, envVars, 5) + assert.Equal(t, "GF_PLUGIN_TRACING=true", envVars[0]) + assert.Equal(t, "GF_VERSION=", envVars[1]) + assert.Equal(t, "GF_PLUGIN_VERSION=1.0.0", envVars[2]) + assert.Equal(t, "GF_INSTANCE_OTLP_ADDRESS=127.0.0.1:4317", envVars[3]) + assert.Equal(t, "GF_INSTANCE_OTLP_PROPAGATION=w3c,jaeger", envVars[4]) + }, + }, { name: "otlp no propagation disabled by default", cfg: &config.Cfg{ - Opentelemetry: config.OpentelemetryCfg{ - Address: "127.0.0.1:4317", - Propagation: "w3c", + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{ + Address: "127.0.0.1:4317", + Propagation: "w3c", + }, }, }, plugin: defaultPlugin, @@ -318,7 +349,9 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "disabled on plugin", cfg: &config.Cfg{ - Opentelemetry: defaultOtelCfg, + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, PluginSettings: setting.PluginSettings{ pluginID: map[string]string{"tracing": "false"}, }, @@ -329,7 +362,9 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "disabled on plugin with other plugin settings", cfg: &config.Cfg{ - Opentelemetry: defaultOtelCfg, + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, PluginSettings: map[string]map[string]string{ pluginID: {"some_other_option": "true"}, }, @@ -340,7 +375,9 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "enabled on plugin with other plugin settings", cfg: &config.Cfg{ - Opentelemetry: defaultOtelCfg, + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, PluginSettings: map[string]map[string]string{ pluginID: {"some_other_option": "true", "tracing": "true"}, }, @@ -351,7 +388,9 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "GF_PLUGIN_VERSION is not present if tracing is disabled", cfg: &config.Cfg{ - Opentelemetry: config.OpentelemetryCfg{}, // no OTEL config + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{}, + }, PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, }, plugin: defaultPlugin, @@ -360,7 +399,9 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "GF_PLUGIN_VERSION is present if tracing is enabled and plugin has version", cfg: &config.Cfg{ - Opentelemetry: defaultOtelCfg, + Tracing: config.Tracing{ + OpenTelemetry: defaultOTelCfg, + }, PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, }, plugin: defaultPlugin, @@ -369,7 +410,9 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) { { name: "GF_PLUGIN_VERSION is not present if tracing is enabled but plugin doesn't have a version", cfg: &config.Cfg{ - Opentelemetry: config.OpentelemetryCfg{}, + Tracing: config.Tracing{ + OpenTelemetry: config.OpenTelemetryCfg{}, + }, PluginSettings: map[string]map[string]string{pluginID: {"tracing": "true"}}, }, plugin: pluginWithoutVersion, diff --git a/pkg/plugins/manager/loader/loader.go b/pkg/plugins/manager/loader/loader.go index adfa11d1742..2349b4d255e 100644 --- a/pkg/plugins/manager/loader/loader.go +++ b/pkg/plugins/manager/loader/loader.go @@ -18,7 +18,6 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/process" "github.com/grafana/grafana/pkg/plugins/manager/registry" "github.com/grafana/grafana/pkg/plugins/manager/signature" - "github.com/grafana/grafana/pkg/plugins/pluginscdn" "github.com/grafana/grafana/pkg/plugins/storage" "github.com/grafana/grafana/pkg/util" ) @@ -33,7 +32,6 @@ type Loader struct { pluginInitializer initializer.Initializer signatureValidator signature.Validator pluginStorage storage.Manager - pluginsCDN *pluginscdn.Service assetPath *assetpath.Service log log.Logger cfg *config.Cfg @@ -43,16 +41,16 @@ type Loader struct { func ProvideService(cfg *config.Cfg, license plugins.Licensing, authorizer plugins.PluginLoaderAuthorizer, pluginRegistry registry.Service, backendProvider plugins.BackendFactoryProvider, pluginFinder finder.Finder, - roleRegistry plugins.RoleRegistry, pluginsCDNService *pluginscdn.Service, assetPath *assetpath.Service) *Loader { + roleRegistry plugins.RoleRegistry, assetPath *assetpath.Service) *Loader { return New(cfg, license, authorizer, pluginRegistry, backendProvider, process.NewManager(pluginRegistry), - storage.FileSystem(log.NewPrettyLogger("loader.fs"), cfg.PluginsPath), roleRegistry, pluginsCDNService, - assetPath, pluginFinder) + storage.FileSystem(log.NewPrettyLogger("loader.fs"), cfg.PluginsPath), roleRegistry, assetPath, + pluginFinder) } func New(cfg *config.Cfg, license plugins.Licensing, authorizer plugins.PluginLoaderAuthorizer, pluginRegistry registry.Service, backendProvider plugins.BackendFactoryProvider, processManager process.Service, pluginStorage storage.Manager, roleRegistry plugins.RoleRegistry, - pluginsCDNService *pluginscdn.Service, assetPath *assetpath.Service, pluginFinder finder.Finder) *Loader { + assetPath *assetpath.Service, pluginFinder finder.Finder) *Loader { return &Loader{ pluginFinder: pluginFinder, pluginRegistry: pluginRegistry, @@ -64,7 +62,6 @@ func New(cfg *config.Cfg, license plugins.Licensing, authorizer plugins.PluginLo log: log.New("plugin.loader"), roleRegistry: roleRegistry, cfg: cfg, - pluginsCDN: pluginsCDNService, assetPath: assetPath, } } @@ -86,20 +83,12 @@ func (l *Loader) loadPlugins(ctx context.Context, src plugins.PluginSource, foun continue } - var sig plugins.Signature - if l.pluginsCDN.PluginSupported(p.Primary.JSONData.ID) { - // CDN plugins have no signature checks for now. - sig = plugins.Signature{Status: plugins.SignatureValid} - } else { - var err error - sig, err = signature.Calculate(ctx, l.log, src, p.Primary) - if err != nil { - l.log.Warn("Could not calculate plugin signature state", "pluginID", p.Primary.JSONData.ID, "err", err) - continue - } + sig, err := signature.Calculate(ctx, l.log, src, p.Primary) + if err != nil { + l.log.Warn("Could not calculate plugin signature state", "pluginID", p.Primary.JSONData.ID, "err", err) + continue } - class := src.PluginClass(ctx) - plugin, err := l.createPluginBase(p.Primary.JSONData, class, p.Primary.FS) + plugin, err := l.createPluginBase(p.Primary.JSONData, src.PluginClass(ctx), p.Primary.FS) if err != nil { l.log.Error("Could not create primary plugin base", "pluginID", p.Primary.JSONData.ID, "err", err) continue @@ -117,7 +106,7 @@ func (l *Loader) loadPlugins(ctx context.Context, src plugins.PluginSource, foun continue } - cp, err := l.createPluginBase(c.JSONData, class, c.FS) + cp, err := l.createPluginBase(c.JSONData, plugin.Class, c.FS) if err != nil { l.log.Error("Could not create child plugin base", "pluginID", p.Primary.JSONData.ID, "err", err) continue @@ -154,7 +143,7 @@ func (l *Loader) loadPlugins(ctx context.Context, src plugins.PluginSource, foun if !plugin.IsRenderer() && !plugin.IsCorePlugin() { _, err := plugin.FS.Open("module.js") if err != nil { - if errors.Is(err, plugins.ErrFileNotExist) && !l.pluginsCDN.PluginSupported(plugin.ID) { + if errors.Is(err, plugins.ErrFileNotExist) { l.log.Warn("Plugin missing module.js", "pluginID", plugin.ID, "warning", "Missing module.js, If you loaded this plugin from git, make sure to compile it.") } @@ -177,8 +166,6 @@ func (l *Loader) loadPlugins(ctx context.Context, src plugins.PluginSource, foun if err != nil { return nil, err } - metrics.SetPluginBuildInformation(p.ID, string(p.Type), p.Info.Version, string(p.Signature)) - if errDeclareRoles := l.roleRegistry.DeclarePluginRoles(ctx, p.ID, p.Name, p.Roles); errDeclareRoles != nil { l.log.Warn("Declare plugin roles failed.", "pluginID", p.ID, "err", errDeclareRoles) } @@ -188,6 +175,10 @@ func (l *Loader) loadPlugins(ctx context.Context, src plugins.PluginSource, foun if err := l.load(ctx, p); err != nil { l.log.Error("Could not start plugin", "pluginId", p.ID, "err", err) } + + if !p.IsCorePlugin() && !p.IsBundledPlugin() { + metrics.SetPluginBuildInformation(p.ID, string(p.Type), p.Info.Version, string(p.Signature)) + } } return verifiedPlugins, nil diff --git a/pkg/plugins/manager/loader/loader_test.go b/pkg/plugins/manager/loader/loader_test.go index 9fbaf13f295..81e09f76813 100644 --- a/pkg/plugins/manager/loader/loader_test.go +++ b/pkg/plugins/manager/loader/loader_test.go @@ -447,63 +447,6 @@ func TestLoader_Load(t *testing.T) { }, }, }, - { - name: "Load CDN plugin", - class: plugins.External, - cfg: &config.Cfg{ - PluginsCDNURLTemplate: "https://cdn.example.com", - PluginSettings: setting.PluginSettings{ - "grafana-worldmap-panel": {"cdn": "true"}, - }, - }, - pluginPaths: []string{"../testdata/cdn"}, - want: []*plugins.Plugin{ - { - JSONData: plugins.JSONData{ - ID: "grafana-worldmap-panel", - Type: "panel", - Name: "Worldmap Panel", - Info: plugins.Info{ - Version: "0.3.3", - Links: []plugins.InfoLink{ - {Name: "Project site", URL: "https://github.com/grafana/worldmap-panel"}, - {Name: "MIT License", URL: "https://github.com/grafana/worldmap-panel/blob/master/LICENSE"}, - }, - Logos: plugins.Logos{ - // Path substitution - Small: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap_logo.svg", - Large: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap_logo.svg", - }, - Screenshots: []plugins.Screenshots{ - { - Name: "World", - Path: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap-world.png", - }, - { - Name: "USA", - Path: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap-usa.png", - }, - { - Name: "Light Theme", - Path: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap-light-theme.png", - }, - }, - }, - Dependencies: plugins.Dependencies{ - GrafanaVersion: "3.x.x", - Plugins: []plugins.Dependency{}, - }, - }, - FS: plugins.NewLocalFS(map[string]struct{}{ - filepath.Join(parentDir, "testdata/cdn/plugin", "plugin.json"): {}, - }, filepath.Join(parentDir, "testdata/cdn/plugin")), - Class: plugins.External, - Signature: plugins.SignatureValid, - BaseURL: "plugin-cdn/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel", - Module: "plugin-cdn/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/module", - }, - }, - }, } for _, tt := range tests { reg := fakes.NewFakePluginRegistry() @@ -535,6 +478,89 @@ func TestLoader_Load(t *testing.T) { } } +func TestLoader_Load_CustomSource(t *testing.T) { + t.Run("Load a plugin", func(t *testing.T) { + parentDir, err := filepath.Abs("../") + if err != nil { + t.Errorf("could not construct absolute path of current dir") + return + } + + cfg := &config.Cfg{ + PluginsCDNURLTemplate: "https://cdn.example.com", + PluginSettings: setting.PluginSettings{ + "grafana-worldmap-panel": {"cdn": "true"}, + }, + } + + pluginPaths := []string{"../testdata/cdn"} + expected := []*plugins.Plugin{{ + JSONData: plugins.JSONData{ + ID: "grafana-worldmap-panel", + Type: "panel", + Name: "Worldmap Panel", + Info: plugins.Info{ + Version: "0.3.3", + Links: []plugins.InfoLink{ + {Name: "Project site", URL: "https://github.com/grafana/worldmap-panel"}, + {Name: "MIT License", URL: "https://github.com/grafana/worldmap-panel/blob/master/LICENSE"}, + }, + Logos: plugins.Logos{ + // Path substitution + Small: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap_logo.svg", + Large: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap_logo.svg", + }, + Screenshots: []plugins.Screenshots{ + { + Name: "World", + Path: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap-world.png", + }, + { + Name: "USA", + Path: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap-usa.png", + }, + { + Name: "Light Theme", + Path: "https://cdn.example.com/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/images/worldmap-light-theme.png", + }, + }, + }, + Dependencies: plugins.Dependencies{ + GrafanaVersion: "3.x.x", + Plugins: []plugins.Dependency{}, + }, + }, + FS: plugins.NewLocalFS(map[string]struct{}{ + filepath.Join(parentDir, "testdata/cdn/plugin", "plugin.json"): {}, + }, filepath.Join(parentDir, "testdata/cdn/plugin")), + Class: plugins.Bundled, + Signature: plugins.SignatureValid, + BaseURL: "plugin-cdn/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel", + Module: "plugin-cdn/grafana-worldmap-panel/0.3.3/public/plugins/grafana-worldmap-panel/module", + }} + + l := newLoader(cfg) + got, err := l.Load(context.Background(), &fakes.FakePluginSource{ + PluginClassFunc: func(ctx context.Context) plugins.Class { + return plugins.Bundled + }, + PluginURIsFunc: func(ctx context.Context) []string { + return pluginPaths + }, + DefaultSignatureFunc: func(ctx context.Context) (plugins.Signature, bool) { + return plugins.Signature{ + Status: plugins.SignatureValid, + }, true + }, + }) + + require.NoError(t, err) + if !cmp.Equal(got, expected, compareOpts...) { + t.Fatalf("Result mismatch (-want +got):\n%s", cmp.Diff(got, expected, compareOpts...)) + } + }) +} + func TestLoader_setDefaultNavURL(t *testing.T) { t.Run("When including a dashboard with DefaultNav: true", func(t *testing.T) { pluginWithDashboard := &plugins.Plugin{ @@ -1304,10 +1330,9 @@ func Test_setPathsBasedOnApp(t *testing.T) { } func newLoader(cfg *config.Cfg, cbs ...func(loader *Loader)) *Loader { - cdn := pluginscdn.ProvideService(cfg) l := New(cfg, &fakes.FakeLicensingService{}, signature.NewUnsignedAuthorizer(cfg), fakes.NewFakePluginRegistry(), fakes.NewFakeBackendProcessProvider(), fakes.NewFakeProcessManager(), fakes.NewFakePluginStorage(), - fakes.NewFakeRoleRegistry(), cdn, assetpath.ProvideService(cdn), finder.NewLocalFinder()) + fakes.NewFakeRoleRegistry(), assetpath.ProvideService(pluginscdn.ProvideService(cfg)), finder.NewLocalFinder()) for _, cb := range cbs { cb(l) diff --git a/pkg/plugins/manager/manager_integration_test.go b/pkg/plugins/manager/manager_integration_test.go index 2e8c9c56cec..56899d80ec4 100644 --- a/pkg/plugins/manager/manager_integration_test.go +++ b/pkg/plugins/manager/manager_integration_test.go @@ -18,7 +18,6 @@ import ( "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin" "github.com/grafana/grafana/pkg/plugins/backendplugin/provider" - "github.com/grafana/grafana/pkg/plugins/config" "github.com/grafana/grafana/pkg/plugins/manager/client" "github.com/grafana/grafana/pkg/plugins/manager/fakes" "github.com/grafana/grafana/pkg/plugins/manager/loader" @@ -31,6 +30,7 @@ import ( "github.com/grafana/grafana/pkg/plugins/pluginscdn" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/licensing" + "github.com/grafana/grafana/pkg/services/pluginsintegration/config" plicensing "github.com/grafana/grafana/pkg/services/pluginsintegration/licensing" "github.com/grafana/grafana/pkg/services/searchV2" "github.com/grafana/grafana/pkg/setting" @@ -114,12 +114,10 @@ func TestIntegrationPluginManager(t *testing.T) { pCfg, err := config.ProvideConfig(setting.ProvideProvider(cfg), cfg) require.NoError(t, err) reg := registry.ProvideService() - cdn := pluginscdn.ProvideService(pCfg) - lic := plicensing.ProvideLicensing(cfg, &licensing.OSSLicensingService{Cfg: cfg}) l := loader.ProvideService(pCfg, lic, signature.NewUnsignedAuthorizer(pCfg), reg, provider.ProvideService(coreRegistry), finder.NewLocalFinder(), fakes.NewFakeRoleRegistry(), - cdn, assetpath.ProvideService(cdn)) + assetpath.ProvideService(pluginscdn.ProvideService(pCfg))) srcs := sources.ProvideService(cfg, pCfg) ps, err := store.ProvideService(reg, srcs, l) require.NoError(t, err) @@ -191,6 +189,7 @@ func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *store.Serv "table-old": {}, "text": {}, "timeseries": {}, + "trend": {}, "welcome": {}, "xychart": {}, } diff --git a/pkg/plugins/pfs/corelist/corelist_load_gen.go b/pkg/plugins/pfs/corelist/corelist_load_gen.go index e9f631cec22..6215b3177b1 100644 --- a/pkg/plugins/pfs/corelist/corelist_load_gen.go +++ b/pkg/plugins/pfs/corelist/corelist_load_gen.go @@ -79,6 +79,7 @@ func corePlugins(rt *thema.Runtime) []pfs.ParsedPlugin { parsePluginOrPanic("public/app/plugins/panel/text", "text", rt), parsePluginOrPanic("public/app/plugins/panel/timeseries", "timeseries", rt), parsePluginOrPanic("public/app/plugins/panel/traces", "traces", rt), + parsePluginOrPanic("public/app/plugins/panel/trend", "trend", rt), parsePluginOrPanic("public/app/plugins/panel/welcome", "welcome", rt), parsePluginOrPanic("public/app/plugins/panel/xychart", "xychart", rt), } diff --git a/pkg/plugins/plugindef/plugindef.cue b/pkg/plugins/plugindef/plugindef.cue index 69c53b9a1c2..75f75f5d94d 100644 --- a/pkg/plugins/plugindef/plugindef.cue +++ b/pkg/plugins/plugindef/plugindef.cue @@ -17,7 +17,7 @@ seqs: [ // grafana.com, then the plugin `id` has to follow the naming // conventions. id: string & strings.MinRunes(1) - id: =~"^([0-9a-z]+\\-([0-9a-z]+\\-)?(\(strings.Join([ for t in _types {t}], "|"))))|(alertGroups|alertlist|annolist|barchart|bargauge|candlestick|canvas|dashlist|debug|gauge|geomap|gettingstarted|graph|heatmap|histogram|icon|live|logs|news|nodeGraph|piechart|pluginlist|stat|state-timeline|status-history|table|table-old|text|timeseries|traces|welcome|xychart|alertmanager|cloudwatch|dashboard|elasticsearch|grafana|grafana-azure-monitor-datasource|graphite|influxdb|jaeger|loki|mixed|mssql|mysql|opentsdb|postgres|prometheus|stackdriver|tempo|testdata|zipkin|phlare|parca)$" + id: =~"^([0-9a-z]+\\-([0-9a-z]+\\-)?(\(strings.Join([ for t in _types {t}], "|"))))|(alertGroups|alertlist|annolist|barchart|bargauge|candlestick|canvas|dashlist|debug|gauge|geomap|gettingstarted|graph|heatmap|histogram|icon|live|logs|news|nodeGraph|piechart|pluginlist|stat|state-timeline|status-history|table|table-old|text|timeseries|trend|traces|welcome|xychart|alertmanager|cloudwatch|dashboard|elasticsearch|grafana|grafana-azure-monitor-datasource|graphite|influxdb|jaeger|loki|mixed|mssql|mysql|opentsdb|postgres|prometheus|stackdriver|tempo|testdata|zipkin|phlare|parca)$" // Human-readable name of the plugin that is shown to the user in // the UI. diff --git a/pkg/services/alerting/conditions/query_interval_test.go b/pkg/services/alerting/conditions/query_interval_test.go index 289a769ebde..443b0f74d83 100644 --- a/pkg/services/alerting/conditions/query_interval_test.go +++ b/pkg/services/alerting/conditions/query_interval_test.go @@ -12,6 +12,7 @@ import ( "github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/datasources" fd "github.com/grafana/grafana/pkg/services/datasources/fakes" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/validations" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tsdb/intervalv2" @@ -141,7 +142,7 @@ func (rh fakeIntervalTestReqHandler) HandleRequest(ctx context.Context, dsInfo * func applyScenario(t *testing.T, timeRange string, dataSourceJsonData *simplejson.Json, queryModel string, verifier func(query legacydata.DataSubQuery)) { t.Run("desc", func(t *testing.T) { db := dbtest.NewFakeDB() - store := alerting.ProvideAlertStore(db, localcache.ProvideService(), &setting.Cfg{}, nil) + store := alerting.ProvideAlertStore(db, localcache.ProvideService(), &setting.Cfg{}, nil, featuremgmt.WithFeatures()) ctx := &queryIntervalTestContext{} ctx.result = &alerting.EvalContext{ diff --git a/pkg/services/alerting/conditions/query_test.go b/pkg/services/alerting/conditions/query_test.go index d3dcea599d6..11e98da1aca 100644 --- a/pkg/services/alerting/conditions/query_test.go +++ b/pkg/services/alerting/conditions/query_test.go @@ -18,6 +18,7 @@ import ( "github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/datasources" fd "github.com/grafana/grafana/pkg/services/datasources/fakes" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/validations" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tsdb/legacydata" @@ -38,7 +39,7 @@ func TestQueryCondition(t *testing.T) { setup := func() *queryConditionTestContext { ctx := &queryConditionTestContext{} db := dbtest.NewFakeDB() - store := alerting.ProvideAlertStore(db, localcache.ProvideService(), &setting.Cfg{}, nil) + store := alerting.ProvideAlertStore(db, localcache.ProvideService(), &setting.Cfg{}, nil, featuremgmt.WithFeatures()) ctx.reducer = `{"type":"avg"}` ctx.evaluator = `{"type":"gt","params":[100]}` ctx.result = &alerting.EvalContext{ diff --git a/pkg/services/alerting/extractor_test.go b/pkg/services/alerting/extractor_test.go index 9e2db68b0bc..fa15c9190c3 100644 --- a/pkg/services/alerting/extractor_test.go +++ b/pkg/services/alerting/extractor_test.go @@ -17,6 +17,7 @@ import ( "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources/permissions" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" ) @@ -42,7 +43,8 @@ func TestAlertRuleExtraction(t *testing.T) { dsService := &fakeDatasourceService{ExpectedDatasource: defaultDs} db := dbtest.NewFakeDB() - store := ProvideAlertStore(db, localcache.ProvideService(), &setting.Cfg{}, nil) + cfg := &setting.Cfg{} + store := ProvideAlertStore(db, localcache.ProvideService(), cfg, nil, featuremgmt.WithFeatures()) extractor := ProvideDashAlertExtractorService(dsPermissions, dsService, store) t.Run("Parsing alert rules from dashboard json", func(t *testing.T) { diff --git a/pkg/services/alerting/store.go b/pkg/services/alerting/store.go index 5f764131dfd..26613090fb4 100644 --- a/pkg/services/alerting/store.go +++ b/pkg/services/alerting/store.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/infra/log" alertmodels "github.com/grafana/grafana/pkg/services/alerting/models" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/setting" @@ -39,17 +40,19 @@ type sqlStore struct { log *log.ConcreteLogger cfg *setting.Cfg tagService tag.Service + features featuremgmt.FeatureToggles } func ProvideAlertStore( db db.DB, - cacheService *localcache.CacheService, cfg *setting.Cfg, tagService tag.Service) AlertStore { + cacheService *localcache.CacheService, cfg *setting.Cfg, tagService tag.Service, features featuremgmt.FeatureToggles) AlertStore { return &sqlStore{ db: db, cache: cacheService, log: log.New("alerting.store"), cfg: cfg, tagService: tagService, + features: features, } } @@ -107,8 +110,13 @@ func deleteAlertByIdInternal(alertId int64, reason string, sess *db.Session, log } func (ss *sqlStore) HandleAlertsQuery(ctx context.Context, query *alertmodels.GetAlertsQuery) (res []*alertmodels.AlertListItemDTO, err error) { + recursiveQueriesAreSupported, err := ss.db.RecursiveQueriesAreSupported() + if err != nil { + return res, err + } + err = ss.db.WithDbSession(ctx, func(sess *db.Session) error { - builder := db.NewSqlBuilder(ss.cfg, ss.db.GetDialect()) + builder := db.NewSqlBuilder(ss.cfg, ss.features, ss.db.GetDialect(), recursiveQueriesAreSupported) builder.Write(`SELECT alert.id, diff --git a/pkg/services/annotations/annotationsimpl/annotations.go b/pkg/services/annotations/annotationsimpl/annotations.go index fd1bfa4e8f6..9929984db1f 100644 --- a/pkg/services/annotations/annotationsimpl/annotations.go +++ b/pkg/services/annotations/annotationsimpl/annotations.go @@ -6,6 +6,7 @@ import ( "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/annotations" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/tag" "github.com/grafana/grafana/pkg/setting" ) @@ -14,10 +15,11 @@ type RepositoryImpl struct { store store } -func ProvideService(db db.DB, cfg *setting.Cfg, tagService tag.Service) *RepositoryImpl { +func ProvideService(db db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles, tagService tag.Service) *RepositoryImpl { return &RepositoryImpl{ store: &xormRepositoryImpl{ cfg: cfg, + features: features, db: db, log: log.New("annotations"), tagService: tagService, diff --git a/pkg/services/annotations/annotationsimpl/cleanup.go b/pkg/services/annotations/annotationsimpl/cleanup.go index af275c97314..a3380d9b4df 100644 --- a/pkg/services/annotations/annotationsimpl/cleanup.go +++ b/pkg/services/annotations/annotationsimpl/cleanup.go @@ -5,6 +5,7 @@ import ( "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/setting" ) @@ -13,12 +14,13 @@ type CleanupServiceImpl struct { store store } -func ProvideCleanupService(db db.DB, cfg *setting.Cfg) *CleanupServiceImpl { +func ProvideCleanupService(db db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles) *CleanupServiceImpl { return &CleanupServiceImpl{ store: &xormRepositoryImpl{ - cfg: cfg, - db: db, - log: log.New("annotations"), + cfg: cfg, + features: features, + db: db, + log: log.New("annotations"), }, } } diff --git a/pkg/services/annotations/annotationsimpl/cleanup_test.go b/pkg/services/annotations/annotationsimpl/cleanup_test.go index feb11585914..b072224d446 100644 --- a/pkg/services/annotations/annotationsimpl/cleanup_test.go +++ b/pkg/services/annotations/annotationsimpl/cleanup_test.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/annotations" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/setting" ) @@ -91,7 +92,7 @@ func TestAnnotationCleanUp(t *testing.T) { t.Run(test.name, func(t *testing.T) { cfg := setting.NewCfg() cfg.AnnotationCleanupJobBatchSize = 1 - cleaner := ProvideCleanupService(fakeSQL, cfg) + cleaner := ProvideCleanupService(fakeSQL, cfg, featuremgmt.WithFeatures()) affectedAnnotations, affectedAnnotationTags, err := cleaner.Run(context.Background(), test.cfg) require.NoError(t, err) @@ -146,7 +147,7 @@ func TestOldAnnotationsAreDeletedFirst(t *testing.T) { // run the clean up task to keep one annotation. cfg := setting.NewCfg() cfg.AnnotationCleanupJobBatchSize = 1 - cleaner := &xormRepositoryImpl{cfg: cfg, log: log.New("test-logger"), db: fakeSQL} + cleaner := &xormRepositoryImpl{cfg: cfg, log: log.New("test-logger"), db: fakeSQL, features: featuremgmt.WithFeatures()} _, err = cleaner.CleanAnnotations(context.Background(), setting.AnnotationCleanupSettings{MaxCount: 1}, alertAnnotationType) require.NoError(t, err) diff --git a/pkg/services/annotations/annotationsimpl/xorm_store.go b/pkg/services/annotations/annotationsimpl/xorm_store.go index 7d74fd529f8..a78584f07a2 100644 --- a/pkg/services/annotations/annotationsimpl/xorm_store.go +++ b/pkg/services/annotations/annotationsimpl/xorm_store.go @@ -13,6 +13,7 @@ import ( ac "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/annotations" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/permissions" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" @@ -42,6 +43,7 @@ func validateTimeRange(item *annotations.Item) error { type xormRepositoryImpl struct { cfg *setting.Cfg + features featuremgmt.FeatureToggles db db.DB log log.Logger maximumTagsLength int64 @@ -299,13 +301,15 @@ func (r *xormRepositoryImpl) Get(ctx context.Context, query *annotations.ItemQue } } + var acFilter acFilter if !ac.IsDisabled(r.cfg) { - acFilter, acArgs, err := getAccessControlFilter(query.SignedInUser) + var err error + acFilter, err = r.getAccessControlFilter(query.SignedInUser) if err != nil { return err } - sql.WriteString(fmt.Sprintf(" AND (%s)", acFilter)) - params = append(params, acArgs...) + sql.WriteString(fmt.Sprintf(" AND (%s)", acFilter.where)) + params = append(params, acFilter.whereParams...) } if query.Limit == 0 { @@ -314,6 +318,14 @@ func (r *xormRepositoryImpl) Get(ctx context.Context, query *annotations.ItemQue // order of ORDER BY arguments match the order of a sql index for performance sql.WriteString(" ORDER BY a.org_id, a.epoch_end DESC, a.epoch DESC" + r.db.GetDialect().Limit(query.Limit) + " ) dt on dt.id = annotation.id") + if acFilter.recQueries != "" { + var sb bytes.Buffer + sb.WriteString(acFilter.recQueries) + sb.WriteString(sql.String()) + sql = sb + params = append(acFilter.recParams, params...) + } + if err := sess.SQL(sql.String(), params...).Find(&items); err != nil { items = nil return err @@ -325,13 +337,23 @@ func (r *xormRepositoryImpl) Get(ctx context.Context, query *annotations.ItemQue return items, err } -func getAccessControlFilter(user *user.SignedInUser) (string, []interface{}, error) { +type acFilter struct { + where string + whereParams []interface{} + recQueries string + recParams []interface{} +} + +func (r *xormRepositoryImpl) getAccessControlFilter(user *user.SignedInUser) (acFilter, error) { + var recQueries string + var recQueriesParams []interface{} + if user == nil || user.Permissions[user.OrgID] == nil { - return "", nil, errors.New("missing permissions") + return acFilter{}, errors.New("missing permissions") } scopes, has := user.Permissions[user.OrgID][ac.ActionAnnotationsRead] if !has { - return "", nil, errors.New("missing permissions") + return acFilter{}, errors.New("missing permissions") } types, hasWildcardScope := ac.ParseScopes(ac.ScopeAnnotationsProvider.GetResourceScopeType(""), scopes) if hasWildcardScope { @@ -347,13 +369,27 @@ func getAccessControlFilter(user *user.SignedInUser) (string, []interface{}, err } // annotation read permission with scope annotations:type:dashboard allows listing annotations from dashboards which the user can view if t == annotations.Dashboard.String() { - dashboardFilter, dashboardParams := permissions.NewAccessControlDashboardPermissionFilter(user, dashboards.PERMISSION_VIEW, searchstore.TypeDashboard).Where() + recursiveQueriesAreSupported, err := r.db.RecursiveQueriesAreSupported() + if err != nil { + return acFilter{}, err + } + + filterRBAC := permissions.NewAccessControlDashboardPermissionFilter(user, dashboards.PERMISSION_VIEW, searchstore.TypeDashboard, r.features, recursiveQueriesAreSupported) + dashboardFilter, dashboardParams := filterRBAC.Where() + recQueries, recQueriesParams = filterRBAC.With() filter := fmt.Sprintf("a.dashboard_id IN(SELECT id FROM dashboard WHERE %s)", dashboardFilter) filters = append(filters, filter) params = dashboardParams } } - return strings.Join(filters, " OR "), params, nil + + f := acFilter{ + where: strings.Join(filters, " OR "), + whereParams: params, + recQueries: recQueries, + recParams: recQueriesParams, + } + return f, nil } func (r *xormRepositoryImpl) Delete(ctx context.Context, params *annotations.DeleteParams) error { diff --git a/pkg/services/annotations/annotationsimpl/xorm_store_test.go b/pkg/services/annotations/annotationsimpl/xorm_store_test.go index 3f949efb763..630e266911e 100644 --- a/pkg/services/annotations/annotationsimpl/xorm_store_test.go +++ b/pkg/services/annotations/annotationsimpl/xorm_store_test.go @@ -2,6 +2,7 @@ package annotationsimpl import ( "context" + "errors" "fmt" "strings" "testing" @@ -10,14 +11,20 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/accesscontrol" + "github.com/grafana/grafana/pkg/services/accesscontrol/mock" "github.com/grafana/grafana/pkg/services/annotations" "github.com/grafana/grafana/pkg/services/dashboards" dashboardstore "github.com/grafana/grafana/pkg/services/dashboards/database" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/folder" + "github.com/grafana/grafana/pkg/services/folder/folderimpl" + "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/tag/tagimpl" @@ -495,7 +502,7 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) { sql := db.InitTestDB(t) var maximumTagsLength int64 = 60 - repo := xormRepositoryImpl{db: sql, cfg: setting.NewCfg(), log: log.New("annotation.test"), tagService: tagimpl.ProvideService(sql, sql.Cfg), maximumTagsLength: maximumTagsLength} + repo := xormRepositoryImpl{db: sql, cfg: setting.NewCfg(), log: log.New("annotation.test"), tagService: tagimpl.ProvideService(sql, sql.Cfg), maximumTagsLength: maximumTagsLength, features: featuremgmt.WithFeatures()} quotaService := quotatest.New(false, nil) dashboardStore, err := dashboardstore.ProvideDashboardStore(sql, sql.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sql, sql.Cfg), quotaService) require.NoError(t, err) @@ -550,7 +557,7 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) { UserID: 1, OrgID: 1, } - role := setupRBACRole(t, repo, user) + role := setupRBACRole(t, sql, user) type testStruct struct { description string @@ -611,7 +618,7 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { user.Permissions = map[int64]map[string][]string{1: tc.permissions} - setupRBACPermission(t, repo, role, user) + setupRBACPermission(t, sql, role, user) results, err := repo.Get(context.Background(), &annotations.ItemQuery{ OrgID: 1, @@ -630,10 +637,163 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) { } } -func setupRBACRole(t *testing.T, repo xormRepositoryImpl, user *user.SignedInUser) *accesscontrol.Role { +func TestIntegrationAnnotationListingWithInheritedRBAC(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + orgID := int64(1) + permissions := []accesscontrol.Permission{ + { + Action: dashboards.ActionFoldersCreate, + }, { + Action: dashboards.ActionFoldersWrite, + Scope: dashboards.ScopeFoldersAll, + }, + } + usr := &user.SignedInUser{ + UserID: 1, + OrgID: orgID, + Permissions: map[int64]map[string][]string{orgID: accesscontrol.GroupScopesByAction(permissions)}, + } + + var role *accesscontrol.Role + + dashboardIDs := make([]int64, 0, folder.MaxNestedFolderDepth+1) + annotationsTexts := make([]string, 0, folder.MaxNestedFolderDepth+1) + + setupFolderStructure := func() *sqlstore.SQLStore { + db := db.InitTestDB(t) + + // enable nested folders so that the folder table is populated for all the tests + features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders) + + origNewGuardian := guardian.New + guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true, CanSaveValue: true}) + t.Cleanup(func() { + guardian.New = origNewGuardian + }) + + // dashboard store commands that should be called. + dashStore, err := dashboardstore.ProvideDashboardStore(db, db.Cfg, features, tagimpl.ProvideService(db, db.Cfg), quotatest.New(false, nil)) + require.NoError(t, err) + + folderSvc := folderimpl.ProvideService(mock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), db.Cfg, dashStore, folderimpl.ProvideDashboardFolderStore(db), db, features) + + var maximumTagsLength int64 = 60 + repo := xormRepositoryImpl{db: db, cfg: setting.NewCfg(), log: log.New("annotation.test"), tagService: tagimpl.ProvideService(db, db.Cfg), maximumTagsLength: maximumTagsLength, features: features} + + parentUID := "" + for i := 0; ; i++ { + uid := fmt.Sprintf("f%d", i) + f, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{ + UID: uid, + OrgID: orgID, + Title: uid, + SignedInUser: usr, + ParentUID: parentUID, + }) + if err != nil { + if errors.Is(err, folder.ErrMaximumDepthReached) { + break + } + + t.Log("unexpected error", "error", err) + t.Fail() + } + + dashInFolder := dashboards.SaveDashboardCommand{ + UserID: usr.UserID, + OrgID: orgID, + IsFolder: false, + Dashboard: simplejson.NewFromAny(map[string]interface{}{ + "title": fmt.Sprintf("Dashboard under %s", f.UID), + }), + FolderID: f.ID, + FolderUID: f.UID, + } + dashboard, err := dashStore.SaveDashboard(context.Background(), dashInFolder) + require.NoError(t, err) + + dashboardIDs = append(dashboardIDs, dashboard.ID) + + parentUID = f.UID + + annotationTxt := fmt.Sprintf("annotation %d", i) + dash1Annotation := &annotations.Item{ + OrgID: orgID, + DashboardID: dashboard.ID, + Epoch: 10, + Text: annotationTxt, + } + err = repo.Add(context.Background(), dash1Annotation) + require.NoError(t, err) + + annotationsTexts = append(annotationsTexts, annotationTxt) + } + + role = setupRBACRole(t, db, usr) + return db + } + + db := setupFolderStructure() + + testCases := []struct { + desc string + features featuremgmt.FeatureToggles + permissions map[string][]string + expectedAnnotationText []string + expectedError bool + }{ + { + desc: "Should find only annotations from dashboards under folders that user can read", + features: featuremgmt.WithFeatures(), + permissions: map[string][]string{ + accesscontrol.ActionAnnotationsRead: {accesscontrol.ScopeAnnotationsTypeDashboard}, + dashboards.ActionDashboardsRead: {"folders:uid:f0"}, + }, + expectedAnnotationText: annotationsTexts[:1], + }, + { + desc: "Should find only annotations from dashboards under inherited folders if nested folder are enabled", + features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders), + permissions: map[string][]string{ + accesscontrol.ActionAnnotationsRead: {accesscontrol.ScopeAnnotationsTypeDashboard}, + dashboards.ActionDashboardsRead: {"folders:uid:f0"}, + }, + expectedAnnotationText: annotationsTexts[:], + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + var maximumTagsLength int64 = 60 + repo := xormRepositoryImpl{db: db, cfg: setting.NewCfg(), log: log.New("annotation.test"), tagService: tagimpl.ProvideService(db, db.Cfg), maximumTagsLength: maximumTagsLength, features: tc.features} + + usr.Permissions = map[int64]map[string][]string{1: tc.permissions} + setupRBACPermission(t, db, role, usr) + + results, err := repo.Get(context.Background(), &annotations.ItemQuery{ + OrgID: 1, + SignedInUser: usr, + }) + if tc.expectedError { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Len(t, results, len(tc.expectedAnnotationText)) + for _, r := range results { + assert.Contains(t, tc.expectedAnnotationText, r.Text) + } + }) + } +} + +func setupRBACRole(t *testing.T, db *sqlstore.SQLStore, user *user.SignedInUser) *accesscontrol.Role { t.Helper() var role *accesscontrol.Role - err := repo.db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + err := db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { role = &accesscontrol.Role{ OrgID: user.OrgID, UID: "test_role", @@ -662,9 +822,9 @@ func setupRBACRole(t *testing.T, repo xormRepositoryImpl, user *user.SignedInUse return role } -func setupRBACPermission(t *testing.T, repo xormRepositoryImpl, role *accesscontrol.Role, user *user.SignedInUser) { +func setupRBACPermission(t *testing.T, db *sqlstore.SQLStore, role *accesscontrol.Role, user *user.SignedInUser) { t.Helper() - err := repo.db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + err := db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { if _, err := sess.Exec("DELETE FROM permission WHERE role_id = ?", role.ID); err != nil { return err } diff --git a/pkg/services/dashboards/database/acl.go b/pkg/services/dashboards/database/acl.go index 66408182727..f5b29c069a6 100644 --- a/pkg/services/dashboards/database/acl.go +++ b/pkg/services/dashboards/database/acl.go @@ -5,6 +5,7 @@ import ( "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/org" ) @@ -103,8 +104,14 @@ func (d *dashboardStore) HasEditPermissionInFolders(ctx context.Context, query * queryResult = true return queryResult, nil } - err := d.store.WithDbSession(ctx, func(dbSession *db.Session) error { - builder := db.NewSqlBuilder(d.cfg, d.store.GetDialect()) + + recursiveQueriesAreSupported, err := d.store.RecursiveQueriesAreSupported() + if err != nil { + return queryResult, err + } + + err = d.store.WithDbSession(ctx, func(dbSession *db.Session) error { + builder := db.NewSqlBuilder(d.cfg, featuremgmt.WithFeatures(), d.store.GetDialect(), recursiveQueriesAreSupported) builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ? AND dashboard.is_folder = ?", query.SignedInUser.OrgID, d.store.GetDialect().BooleanStr(true)) builder.WriteDashboardPermissionFilter(query.SignedInUser, dashboards.PERMISSION_EDIT) @@ -131,13 +138,18 @@ func (d *dashboardStore) HasEditPermissionInFolders(ctx context.Context, query * func (d *dashboardStore) HasAdminPermissionInDashboardsOrFolders(ctx context.Context, query *folder.HasAdminPermissionInDashboardsOrFoldersQuery) (bool, error) { var queryResult bool - err := d.store.WithDbSession(ctx, func(dbSession *db.Session) error { + recursiveQueriesAreSupported, err := d.store.RecursiveQueriesAreSupported() + if err != nil { + return queryResult, err + } + + err = d.store.WithDbSession(ctx, func(dbSession *db.Session) error { if query.SignedInUser.HasRole(org.RoleAdmin) { queryResult = true return nil } - builder := db.NewSqlBuilder(d.cfg, d.store.GetDialect()) + builder := db.NewSqlBuilder(d.cfg, featuremgmt.WithFeatures(), d.store.GetDialect(), recursiveQueriesAreSupported) builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ?", query.SignedInUser.OrgID) builder.WriteDashboardPermissionFilter(query.SignedInUser, dashboards.PERMISSION_ADMIN) diff --git a/pkg/services/dashboards/database/database.go b/pkg/services/dashboards/database/database.go index a6b5725f68b..979de85fe25 100644 --- a/pkg/services/dashboards/database/database.go +++ b/pkg/services/dashboards/database/database.go @@ -934,9 +934,14 @@ func (d *dashboardStore) FindDashboards(ctx context.Context, query *dashboards.F } if !ac.IsDisabled(d.cfg) { + recursiveQueriesAreSupported, err := d.store.RecursiveQueriesAreSupported() + if err != nil { + return nil, err + } + // if access control is enabled, overwrite the filters so far filters = []interface{}{ - permissions.NewAccessControlDashboardPermissionFilter(query.SignedInUser, query.Permission, query.Type), + permissions.NewAccessControlDashboardPermissionFilter(query.SignedInUser, query.Permission, query.Type, d.features, recursiveQueriesAreSupported), } } diff --git a/pkg/services/dashboards/database/database_folder_test.go b/pkg/services/dashboards/database/database_folder_test.go index efb4785899e..615f87e6694 100644 --- a/pkg/services/dashboards/database/database_folder_test.go +++ b/pkg/services/dashboards/database/database_folder_test.go @@ -2,21 +2,33 @@ package database import ( "context" + "errors" + "fmt" "testing" + "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/db" + "github.com/grafana/grafana/pkg/infra/tracing" + "github.com/grafana/grafana/pkg/services/accesscontrol" + "github.com/grafana/grafana/pkg/services/accesscontrol/mock" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder" + "github.com/grafana/grafana/pkg/services/folder/folderimpl" + "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/org" + "github.com/grafana/grafana/pkg/services/org/orgimpl" "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest" "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" - "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/services/user/userimpl" ) var testFeatureToggles = featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch) @@ -36,7 +48,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { sqlStore.Cfg.RBACEnabled = false quotaService := quotatest.New(false, nil) var err error - dashboardStore, err = ProvideDashboardStore(sqlStore, &setting.Cfg{}, testFeatureToggles, tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService) + dashboardStore, err = ProvideDashboardStore(sqlStore, sqlStore.Cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService) require.NoError(t, err) flder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod", "webapp") dashInRoot = insertTestDashboard(t, dashboardStore, "test dash 67", 1, 0, false, "prod", "webapp") @@ -477,6 +489,216 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) { }) } +func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + // the maximux nested folder hierarchy starting from parent down to subfolders + nestedFolders := make([]*folder.Folder, 0, folder.MaxNestedFolderDepth+1) + + var sqlStore *sqlstore.SQLStore + const ( + dashInRootTitle = "dashboard in root" + dashInParentTitle = "dashboard in parent" + dashInSubfolderTitle = "dashboard in subfolder" + ) + var viewer user.SignedInUser + var role *accesscontrol.Role + + setup := func() { + sqlStore = db.InitTestDB(t) + sqlStore.Cfg.RBACEnabled = true + quotaService := quotatest.New(false, nil) + + // enable nested folders so that the folder table is populated for all the tests + features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders) + + var err error + dashboardWriteStore, err := ProvideDashboardStore(sqlStore, sqlStore.Cfg, features, tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService) + require.NoError(t, err) + + usr := createUser(t, sqlStore, "viewer", "Viewer", false) + viewer = user.SignedInUser{ + UserID: usr.ID, + OrgID: usr.OrgID, + OrgRole: org.RoleViewer, + } + + orgService, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService) + require.NoError(t, err) + usrSvc, err := userimpl.ProvideService(sqlStore, orgService, sqlStore.Cfg, nil, nil, quotaService, supportbundlestest.NewFakeBundleService()) + require.NoError(t, err) + + // create admin user in the same org + currentUserCmd := user.CreateUserCommand{Login: "admin", Email: "admin@test.com", Name: "an admin", IsAdmin: false, OrgID: viewer.OrgID} + u, err := usrSvc.Create(context.Background(), ¤tUserCmd) + require.NoError(t, err) + admin := user.SignedInUser{ + UserID: u.ID, + OrgID: u.OrgID, + OrgRole: org.RoleAdmin, + Permissions: map[int64]map[string][]string{u.OrgID: accesscontrol.GroupScopesByAction([]accesscontrol.Permission{ + { + Action: dashboards.ActionFoldersCreate, + }, { + Action: dashboards.ActionFoldersWrite, + Scope: dashboards.ScopeFoldersAll, + }}), + }, + } + require.NotEqual(t, viewer.UserID, admin.UserID) + + origNewGuardian := guardian.New + guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true, CanSaveValue: true}) + t.Cleanup(func() { + guardian.New = origNewGuardian + }) + + folderSvc := folderimpl.ProvideService(mock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), sqlStore.Cfg, dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(sqlStore), sqlStore, features) + + parentUID := "" + for i := 0; ; i++ { + uid := fmt.Sprintf("f%d", i) + f, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{ + UID: uid, + OrgID: admin.OrgID, + Title: uid, + SignedInUser: &admin, + ParentUID: parentUID, + }) + if err != nil { + if errors.Is(err, folder.ErrMaximumDepthReached) { + break + } + + t.Log("unexpected error", "error", err) + t.Fail() + } + + nestedFolders = append(nestedFolders, f) + + parentUID = f.UID + } + require.LessOrEqual(t, 2, len(nestedFolders)) + + saveDashboardCmd := dashboards.SaveDashboardCommand{ + UserID: admin.UserID, + OrgID: admin.OrgID, + IsFolder: false, + Dashboard: simplejson.NewFromAny(map[string]interface{}{ + "title": dashInRootTitle, + }), + } + _, err = dashboardWriteStore.SaveDashboard(context.Background(), saveDashboardCmd) + require.NoError(t, err) + + saveDashboardCmd = dashboards.SaveDashboardCommand{ + UserID: admin.UserID, + OrgID: admin.OrgID, + IsFolder: false, + Dashboard: simplejson.NewFromAny(map[string]interface{}{ + "title": dashInParentTitle, + }), + FolderID: nestedFolders[0].ID, + FolderUID: nestedFolders[0].UID, + } + _, err = dashboardWriteStore.SaveDashboard(context.Background(), saveDashboardCmd) + require.NoError(t, err) + + saveDashboardCmd = dashboards.SaveDashboardCommand{ + UserID: admin.UserID, + OrgID: admin.OrgID, + IsFolder: false, + Dashboard: simplejson.NewFromAny(map[string]interface{}{ + "title": dashInSubfolderTitle, + }), + FolderID: nestedFolders[1].ID, + FolderUID: nestedFolders[1].UID, + } + _, err = dashboardWriteStore.SaveDashboard(context.Background(), saveDashboardCmd) + require.NoError(t, err) + + role = setupRBACRole(t, *sqlStore, &viewer) + } + + setup() + + nestedFolderTitles := make([]string, 0, len(nestedFolders)) + for _, f := range nestedFolders { + nestedFolderTitles = append(nestedFolderTitles, f.Title) + } + + testCases := []struct { + desc string + features featuremgmt.FeatureToggles + permissions map[string][]string + expectedTitles []string + }{ + { + desc: "it should not return folder if ACL is not set for parent folder", + features: featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch), + permissions: nil, + expectedTitles: nil, + }, + { + desc: "it should not return dashboard in subfolder if nested folders are disabled and the user has permission to read dashboards under parent folder", + features: featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch), + permissions: map[string][]string{ + dashboards.ActionDashboardsRead: {fmt.Sprintf("folders:uid:%s", nestedFolders[0].UID)}, + }, + expectedTitles: []string{dashInParentTitle}, + }, + { + desc: "it should return dashboard in subfolder if nested folders are enabled and the user has permission to read dashboards under parent folder", + features: featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch, featuremgmt.FlagNestedFolders), + permissions: map[string][]string{ + dashboards.ActionDashboardsRead: {fmt.Sprintf("folders:uid:%s", nestedFolders[0].UID)}, + }, + expectedTitles: []string{dashInParentTitle, dashInSubfolderTitle}, + }, + { + desc: "it should not return subfolder if nested folders are disabled and the user has permission to read folders under parent folder", + features: featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch), + permissions: map[string][]string{ + dashboards.ActionFoldersRead: {fmt.Sprintf("folders:uid:%s", nestedFolders[0].UID)}, + }, + expectedTitles: []string{nestedFolders[0].Title}, + }, + { + desc: "it should return subfolder if nested folders are enabled and the user has permission to read folders under parent folder", + features: featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch, featuremgmt.FlagNestedFolders), + permissions: map[string][]string{ + dashboards.ActionFoldersRead: {fmt.Sprintf("folders:uid:%s", nestedFolders[0].UID)}, + }, + expectedTitles: nestedFolderTitles, + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + dashboardReadStore, err := ProvideDashboardStore(sqlStore, sqlStore.Cfg, tc.features, tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotatest.New(false, nil)) + require.NoError(t, err) + + viewer.Permissions = map[int64]map[string][]string{viewer.OrgID: tc.permissions} + setupRBACPermission(t, *sqlStore, role, &viewer) + + query := &dashboards.FindPersistedDashboardsQuery{ + SignedInUser: &viewer, + OrgId: viewer.OrgID, + } + + res, err := testSearchDashboards(dashboardReadStore, query) + require.NoError(t, err) + + require.Equal(t, len(tc.expectedTitles), len(res)) + for i, tlt := range tc.expectedTitles { + assert.Equal(t, tlt, res[i].Title) + } + }) + } +} + func moveDashboard(t *testing.T, dashboardStore dashboards.Store, orgId int64, dashboard *simplejson.Json, newFolderId int64) *dashboards.Dashboard { t.Helper() @@ -492,3 +714,61 @@ func moveDashboard(t *testing.T, dashboardStore dashboards.Store, orgId int64, d return dash } + +func setupRBACRole(t *testing.T, db sqlstore.SQLStore, user *user.SignedInUser) *accesscontrol.Role { + t.Helper() + var role *accesscontrol.Role + err := db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + role = &accesscontrol.Role{ + OrgID: user.OrgID, + UID: "test_role", + Name: "test:role", + Updated: time.Now(), + Created: time.Now(), + } + _, err := sess.Insert(role) + if err != nil { + return err + } + + _, err = sess.Insert(accesscontrol.UserRole{ + OrgID: role.OrgID, + RoleID: role.ID, + UserID: user.UserID, + Created: time.Now(), + }) + if err != nil { + return err + } + return nil + }) + + require.NoError(t, err) + return role +} + +func setupRBACPermission(t *testing.T, db sqlstore.SQLStore, role *accesscontrol.Role, user *user.SignedInUser) { + t.Helper() + err := db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + if _, err := sess.Exec("DELETE FROM permission WHERE role_id = ?", role.ID); err != nil { + return err + } + + var acPermission []accesscontrol.Permission + for action, scopes := range user.Permissions[user.OrgID] { + for _, scope := range scopes { + acPermission = append(acPermission, accesscontrol.Permission{ + RoleID: role.ID, Action: action, Scope: scope, Created: time.Now(), Updated: time.Now(), + }) + } + } + + if _, err := sess.InsertMulti(&acPermission); err != nil { + return err + } + + return nil + }) + + require.NoError(t, err) +} diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index b4b8e57d68d..dd8d6e5241f 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -9,12 +9,6 @@ package featuremgmt var ( // Register each toggle here standardFeatureFlags = []FeatureFlag{ - { - Name: "alertingBigTransactions", - Description: "Use big transactions for alerting database writes", - State: FeatureStateAlpha, - Owner: grafanaAlertingSquad, - }, { Name: "trimDefaults", Description: "Use cue schema to remove values that will be applied automatically", @@ -237,11 +231,10 @@ var ( Owner: grafanaUserEssentialsSquad, }, { - Name: "grpcServer", - Description: "Run GRPC server", - State: FeatureStateAlpha, - RequiresDevMode: true, - Owner: grafanaAppPlatformSquad, + Name: "grpcServer", + Description: "Run the GRPC server", + State: FeatureStateBeta, + Owner: grafanaAppPlatformSquad, }, { Name: "entityStore", @@ -316,6 +309,12 @@ var ( State: FeatureStateAlpha, Owner: grafanaObservabilityLogsSquad, }, + { + Name: "showTraceId", + Description: "Show trace ids for requests", + State: FeatureStateAlpha, + Owner: grafanaObservabilityLogsSquad, + }, { Name: "datasourceOnboarding", Description: "Enable data source onboarding page", @@ -500,5 +499,11 @@ var ( State: FeatureStateBeta, Owner: grafanaAsCodeSquad, }, + { + Name: "pyroscopeFlameGraph", + Description: "Changes flame graph to pyroscope one", + State: FeatureStateAlpha, + Owner: grafanaObservabilityTracesAndProfilingSquad, + }, } ) diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index 576b6897651..43e42e059e5 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -1,5 +1,4 @@ Name,State,Owner,requiresDevMode,RequiresLicense,RequiresRestart,FrontendOnly -alertingBigTransactions,alpha,@grafana/alerting-squad,false,false,false,false trimDefaults,beta,@grafana/grafana-as-code,false,false,false,false disableEnvelopeEncryption,stable,@grafana/grafana-as-code,false,false,false,false database_metrics,stable,@grafana/hosted-grafana-team,false,false,false,false @@ -34,7 +33,7 @@ logRequestsInstrumentedAsUnknown,alpha,@grafana/hosted-grafana-team,false,false, dataConnectionsConsole,stable,@grafana/plugins-platform-backend,false,false,false,false internationalization,stable,@grafana/user-essentials,false,false,false,false topnav,stable,@grafana/user-essentials,false,false,false,false -grpcServer,alpha,@grafana/grafana-app-platform-squad,true,false,false,false +grpcServer,beta,@grafana/grafana-app-platform-squad,false,false,false,false entityStore,alpha,@grafana/grafana-app-platform-squad,true,false,false,false cloudWatchCrossAccountQuerying,stable,@grafana/aws-plugins,false,false,false,false redshiftAsyncQueryDataSupport,alpha,@grafana/aws-plugins,false,false,false,true @@ -46,6 +45,7 @@ accessControlOnCall,beta,@grafana/grafana-authnz-team,false,false,false,false nestedFolders,alpha,@grafana/backend-platform,true,false,false,false accessTokenExpirationCheck,stable,@grafana/grafana-authnz-team,false,false,false,false elasticsearchBackendMigration,alpha,@grafana/observability-logs,false,false,false,false +showTraceId,alpha,@grafana/observability-logs,false,false,false,false datasourceOnboarding,alpha,@grafana/dashboards-squad,false,false,false,false emptyDashboardPage,stable,@grafana/dashboards-squad,false,false,false,true secureSocksDatasourceProxy,alpha,@grafana/hosted-grafana-team,false,false,false,false @@ -74,3 +74,4 @@ alertStateHistoryLokiPrimary,alpha,@grafana/alerting-squad,false,false,false,fal alertStateHistoryLokiOnly,alpha,@grafana/alerting-squad,false,false,false,false unifiedRequestLog,alpha,@grafana/backend-platform,false,false,false,false renderAuthJWT,beta,@grafana/grafana-as-code,false,false,false,false +pyroscopeFlameGraph,alpha,@grafana/observability-traces-and-profiling,false,false,false,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index a18c1c22196..90fad46a56f 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -7,10 +7,6 @@ package featuremgmt const ( - // FlagAlertingBigTransactions - // Use big transactions for alerting database writes - FlagAlertingBigTransactions = "alertingBigTransactions" - // FlagTrimDefaults // Use cue schema to remove values that will be applied automatically FlagTrimDefaults = "trimDefaults" @@ -148,7 +144,7 @@ const ( FlagTopnav = "topnav" // FlagGrpcServer - // Run GRPC server + // Run the GRPC server FlagGrpcServer = "grpcServer" // FlagEntityStore @@ -195,6 +191,10 @@ const ( // Use Elasticsearch as backend data source FlagElasticsearchBackendMigration = "elasticsearchBackendMigration" + // FlagShowTraceId + // Show trace ids for requests + FlagShowTraceId = "showTraceId" + // FlagDatasourceOnboarding // Enable data source onboarding page FlagDatasourceOnboarding = "datasourceOnboarding" @@ -306,4 +306,8 @@ const ( // FlagRenderAuthJWT // Uses JWT-based auth for rendering instead of relying on remote cache FlagRenderAuthJWT = "renderAuthJWT" + + // FlagPyroscopeFlameGraph + // Changes flame graph to pyroscope one + FlagPyroscopeFlameGraph = "pyroscopeFlameGraph" ) diff --git a/pkg/services/libraryelements/database.go b/pkg/services/libraryelements/database.go index 15fe4406a33..79262251670 100644 --- a/pkg/services/libraryelements/database.go +++ b/pkg/services/libraryelements/database.go @@ -12,6 +12,7 @@ import ( "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/kinds/librarypanel" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/libraryelements/model" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/search" @@ -227,10 +228,16 @@ func (l *LibraryElementService) deleteLibraryElement(c context.Context, signedIn } // getLibraryElements gets a Library Element where param == value -func getLibraryElements(c context.Context, store db.DB, cfg *setting.Cfg, signedInUser *user.SignedInUser, params []Pair) ([]model.LibraryElementDTO, error) { +func getLibraryElements(c context.Context, store db.DB, cfg *setting.Cfg, signedInUser *user.SignedInUser, params []Pair, features featuremgmt.FeatureToggles) ([]model.LibraryElementDTO, error) { libraryElements := make([]model.LibraryElementWithMeta, 0) - err := store.WithDbSession(c, func(session *db.Session) error { - builder := db.NewSqlBuilder(cfg, store.GetDialect()) + + recursiveQueriesAreSupported, err := store.RecursiveQueriesAreSupported() + if err != nil { + return nil, err + } + + err = store.WithDbSession(c, func(session *db.Session) error { + builder := db.NewSqlBuilder(cfg, features, store.GetDialect(), recursiveQueriesAreSupported) builder.Write(selectLibraryElementDTOWithMeta) builder.Write(", 'General' as folder_name ") builder.Write(", '' as folder_uid ") @@ -299,7 +306,7 @@ func getLibraryElements(c context.Context, store db.DB, cfg *setting.Cfg, signed // getLibraryElementByUid gets a Library Element by uid. func (l *LibraryElementService) getLibraryElementByUid(c context.Context, signedInUser *user.SignedInUser, UID string) (model.LibraryElementDTO, error) { - libraryElements, err := getLibraryElements(c, l.SQLStore, l.Cfg, signedInUser, []Pair{{key: "org_id", value: signedInUser.OrgID}, {key: "uid", value: UID}}) + libraryElements, err := getLibraryElements(c, l.SQLStore, l.Cfg, signedInUser, []Pair{{key: "org_id", value: signedInUser.OrgID}, {key: "uid", value: UID}}, l.features) if err != nil { return model.LibraryElementDTO{}, err } @@ -312,13 +319,19 @@ func (l *LibraryElementService) getLibraryElementByUid(c context.Context, signed // getLibraryElementByName gets a Library Element by name. func (l *LibraryElementService) getLibraryElementsByName(c context.Context, signedInUser *user.SignedInUser, name string) ([]model.LibraryElementDTO, error) { - return getLibraryElements(c, l.SQLStore, l.Cfg, signedInUser, []Pair{{"org_id", signedInUser.OrgID}, {"name", name}}) + return getLibraryElements(c, l.SQLStore, l.Cfg, signedInUser, []Pair{{"org_id", signedInUser.OrgID}, {"name", name}}, l.features) } // getAllLibraryElements gets all Library Elements. func (l *LibraryElementService) getAllLibraryElements(c context.Context, signedInUser *user.SignedInUser, query model.SearchLibraryElementsQuery) (model.LibraryElementSearchResult, error) { elements := make([]model.LibraryElementWithMeta, 0) result := model.LibraryElementSearchResult{} + + recursiveQueriesAreSupported, err := l.SQLStore.RecursiveQueriesAreSupported() + if err != nil { + return result, err + } + if query.PerPage <= 0 { query.PerPage = 100 } @@ -333,8 +346,8 @@ func (l *LibraryElementService) getAllLibraryElements(c context.Context, signedI if folderFilter.parseError != nil { return model.LibraryElementSearchResult{}, folderFilter.parseError } - err := l.SQLStore.WithDbSession(c, func(session *db.Session) error { - builder := db.NewSqlBuilder(l.Cfg, l.SQLStore.GetDialect()) + err = l.SQLStore.WithDbSession(c, func(session *db.Session) error { + builder := db.NewSqlBuilder(l.Cfg, l.features, l.SQLStore.GetDialect(), recursiveQueriesAreSupported) if folderFilter.includeGeneralFolder { builder.Write(selectLibraryElementDTOWithMeta) builder.Write(", 'General' as folder_name ") @@ -563,13 +576,18 @@ func (l *LibraryElementService) patchLibraryElement(c context.Context, signedInU // getConnections gets all connections for a Library Element. func (l *LibraryElementService) getConnections(c context.Context, signedInUser *user.SignedInUser, uid string) ([]model.LibraryElementConnectionDTO, error) { connections := make([]model.LibraryElementConnectionDTO, 0) - err := l.SQLStore.WithDbSession(c, func(session *db.Session) error { + recursiveQueriesAreSupported, err := l.SQLStore.RecursiveQueriesAreSupported() + if err != nil { + return nil, err + } + + err = l.SQLStore.WithDbSession(c, func(session *db.Session) error { element, err := getLibraryElement(l.SQLStore.GetDialect(), session, uid, signedInUser.OrgID) if err != nil { return err } var libraryElementConnections []model.LibraryElementConnectionWithMeta - builder := db.NewSqlBuilder(l.Cfg, l.SQLStore.GetDialect()) + builder := db.NewSqlBuilder(l.Cfg, l.features, l.SQLStore.GetDialect(), recursiveQueriesAreSupported) builder.Write("SELECT lec.*, u1.login AS created_by_name, u1.email AS created_by_email, dashboard.uid AS connection_uid") builder.Write(" FROM " + model.LibraryElementConnectionTableName + " AS lec") builder.Write(" LEFT JOIN " + l.SQLStore.GetDialect().Quote("user") + " AS u1 ON lec.created_by = u1.id") diff --git a/pkg/services/libraryelements/libraryelements.go b/pkg/services/libraryelements/libraryelements.go index 53a3998a41a..562bc4b2160 100644 --- a/pkg/services/libraryelements/libraryelements.go +++ b/pkg/services/libraryelements/libraryelements.go @@ -6,19 +6,21 @@ import ( "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/libraryelements/model" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" ) -func ProvideService(cfg *setting.Cfg, sqlStore db.DB, routeRegister routing.RouteRegister, folderService folder.Service) *LibraryElementService { +func ProvideService(cfg *setting.Cfg, sqlStore db.DB, routeRegister routing.RouteRegister, folderService folder.Service, features featuremgmt.FeatureToggles) *LibraryElementService { l := &LibraryElementService{ Cfg: cfg, SQLStore: sqlStore, RouteRegister: routeRegister, folderService: folderService, log: log.New("library-elements"), + features: features, } l.registerAPIEndpoints() return l @@ -41,6 +43,7 @@ type LibraryElementService struct { RouteRegister routing.RouteRegister folderService folder.Service log log.Logger + features featuremgmt.FeatureToggles } // CreateElement creates a Library Element. diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index 4c5c07e9f37..8c3f363e3f7 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -843,7 +843,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, folderStore, nil, features) - elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService) + elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService, featuremgmt.WithFeatures()) service := LibraryPanelService{ Cfg: cfg, SQLStore: sqlStore, diff --git a/pkg/services/live/managedstream/cache_redis_test.go b/pkg/services/live/managedstream/cache_redis_test.go index df650ded044..d7c3f9fddbb 100644 --- a/pkg/services/live/managedstream/cache_redis_test.go +++ b/pkg/services/live/managedstream/cache_redis_test.go @@ -1,18 +1,34 @@ -//go:build redis -// +build redis - package managedstream import ( + "os" "testing" "github.com/go-redis/redis/v8" "github.com/stretchr/testify/require" ) -func TestRedisCacheStorage(t *testing.T) { +func TestIntegrationRedisCacheStorage(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + u, ok := os.LookupEnv("REDIS_URL") + if !ok || u == "" { + t.Skip("No redis URL supplied") + } + + addr := u + db := 0 + parsed, err := redis.ParseURL(u) + if err == nil { + addr = parsed.Addr + db = parsed.DB + } + redisClient := redis.NewClient(&redis.Options{ - Addr: "localhost:6379", + Addr: addr, + DB: db, }) c := NewRedisFrameCache(redisClient) require.NotNil(t, c) diff --git a/pkg/services/ngalert/api/api_alertmanager.go b/pkg/services/ngalert/api/api_alertmanager.go index 663a6c38f50..2884433551a 100644 --- a/pkg/services/ngalert/api/api_alertmanager.go +++ b/pkg/services/ngalert/api/api_alertmanager.go @@ -228,6 +228,38 @@ func (srv AlertmanagerSrv) RouteGetSilences(c *contextmodel.ReqContext) response return response.JSON(http.StatusOK, gettableSilences) } +func (srv AlertmanagerSrv) RoutePostGrafanaAlertingConfigHistoryActivate(c *contextmodel.ReqContext, id string) response.Response { + confId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + return ErrResp(http.StatusBadRequest, err, "failed to parse config id") + } + + err = srv.mam.ActivateHistoricalConfiguration(c.Req.Context(), c.OrgID, confId) + if err != nil { + var unknownReceiverError notifier.UnknownReceiverError + if errors.As(err, &unknownReceiverError) { + return ErrResp(http.StatusBadRequest, unknownReceiverError, "") + } + var configRejectedError notifier.AlertmanagerConfigRejectedError + if errors.As(err, &configRejectedError) { + return ErrResp(http.StatusBadRequest, configRejectedError, "") + } + if errors.Is(err, store.ErrNoAlertmanagerConfiguration) { + return response.Error(http.StatusNotFound, err.Error(), err) + } + if errors.Is(err, notifier.ErrNoAlertmanagerForOrg) { + return response.Error(http.StatusNotFound, err.Error(), err) + } + if errors.Is(err, notifier.ErrAlertmanagerNotReady) { + return response.Error(http.StatusConflict, err.Error(), err) + } + + return ErrResp(http.StatusInternalServerError, err, "") + } + + return response.JSON(http.StatusAccepted, util.DynMap{"message": "configuration activated"}) +} + func (srv AlertmanagerSrv) RoutePostAlertingConfig(c *contextmodel.ReqContext, body apimodels.PostableUserConfig) response.Response { currentConfig, err := srv.mam.GetAlertmanagerConfiguration(c.Req.Context(), c.OrgID) // If a config is present and valid we proceed with the guard, otherwise we diff --git a/pkg/services/ngalert/api/api_alertmanager_test.go b/pkg/services/ngalert/api/api_alertmanager_test.go index e5e3b6f2160..8cbe6168bb4 100644 --- a/pkg/services/ngalert/api/api_alertmanager_test.go +++ b/pkg/services/ngalert/api/api_alertmanager_test.go @@ -381,6 +381,46 @@ func TestRouteGetAlertingConfigHistory(t *testing.T) { }) } +func TestRoutePostGrafanaAlertingConfigHistoryActivate(t *testing.T) { + sut := createSut(t, nil) + + t.Run("assert 404 when no historical configurations are found", func(tt *testing.T) { + req, err := http.NewRequest(http.MethodGet, "https://grafana.net", nil) + require.NoError(tt, err) + q := req.URL.Query() + req.URL.RawQuery = q.Encode() + + rc := createRequestCtxInOrg(10) + + response := sut.RoutePostGrafanaAlertingConfigHistoryActivate(rc, "0") + require.Equal(tt, 404, response.Status()) + }) + + t.Run("assert 202 for a valid org and id", func(tt *testing.T) { + req, err := http.NewRequest(http.MethodGet, "https://grafana.net", nil) + require.NoError(tt, err) + q := req.URL.Query() + req.URL.RawQuery = q.Encode() + + rc := createRequestCtxInOrg(1) + + response := sut.RoutePostGrafanaAlertingConfigHistoryActivate(rc, "0") + require.Equal(tt, 202, response.Status()) + }) + + t.Run("assert 400 when id is not parseable", func(tt *testing.T) { + req, err := http.NewRequest(http.MethodGet, "https://grafana.net", nil) + require.NoError(tt, err) + q := req.URL.Query() + req.URL.RawQuery = q.Encode() + + rc := createRequestCtxInOrg(1) + + response := sut.RoutePostGrafanaAlertingConfigHistoryActivate(rc, "abc") + require.Equal(tt, 400, response.Status()) + }) +} + func TestSilenceCreate(t *testing.T) { makeSilence := func(comment string, createdBy string, startsAt, endsAt strfmt.DateTime, matchers amv2.Matchers) amv2.Silence { diff --git a/pkg/services/ngalert/api/api_ruler.go b/pkg/services/ngalert/api/api_ruler.go index ca9aa225a34..fd82c004a57 100644 --- a/pkg/services/ngalert/api/api_ruler.go +++ b/pkg/services/ngalert/api/api_ruler.go @@ -303,7 +303,7 @@ func (srv RulerSrv) RoutePostNameRulesConfig(c *contextmodel.ReqContext, ruleGro } rules, err := validateRuleGroup(&ruleGroupConfig, c.SignedInUser.OrgID, namespace, func(condition ngmodels.Condition) error { - return srv.conditionValidator.Validate(eval.Context(c.Req.Context(), c.SignedInUser), condition) + return srv.conditionValidator.Validate(eval.NewContext(c.Req.Context(), c.SignedInUser), condition) }, srv.cfg) if err != nil { return ErrResp(http.StatusBadRequest, err, "") diff --git a/pkg/services/ngalert/api/api_testing.go b/pkg/services/ngalert/api/api_testing.go index 83728417e80..f5dd34c03b2 100644 --- a/pkg/services/ngalert/api/api_testing.go +++ b/pkg/services/ngalert/api/api_testing.go @@ -52,7 +52,7 @@ func (srv TestingApiSrv) RouteTestGrafanaRuleConfig(c *contextmodel.ReqContext, Condition: body.GrafanaManagedCondition.Condition, Data: queries, } - ctx := eval.Context(c.Req.Context(), c.SignedInUser) + ctx := eval.NewContext(c.Req.Context(), c.SignedInUser) conditionEval, err := srv.evaluator.Create(ctx, evalCond) if err != nil { @@ -128,7 +128,7 @@ func (srv TestingApiSrv) RouteEvalQueries(c *contextmodel.ReqContext, cmd apimod if len(cmd.Data) > 0 { cond.Condition = cmd.Data[0].RefID } - evaluator, err := srv.evaluator.Create(eval.Context(c.Req.Context(), c.SignedInUser), cond) + evaluator, err := srv.evaluator.Create(eval.NewContext(c.Req.Context(), c.SignedInUser), cond) if err != nil { return ErrResp(http.StatusBadRequest, err, "Failed to build evaluator for queries and expressions") diff --git a/pkg/services/ngalert/api/authorization.go b/pkg/services/ngalert/api/authorization.go index 8157ea0ebf1..418b5692634 100644 --- a/pkg/services/ngalert/api/authorization.go +++ b/pkg/services/ngalert/api/authorization.go @@ -166,6 +166,8 @@ func (api *API) authorize(method, path string) web.Handler { case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/alerts": // additional authorization is done in the request handler eval = ac.EvalAny(ac.EvalPermission(ac.ActionAlertingNotificationsWrite)) + case http.MethodPost + "/api/alertmanager/grafana/config/history/{id}/_activate": + eval = ac.EvalAny(ac.EvalPermission(ac.ActionAlertingNotificationsWrite)) case http.MethodGet + "/api/alertmanager/grafana/config/api/v1/receivers": eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/receivers/test": diff --git a/pkg/services/ngalert/api/authorization_test.go b/pkg/services/ngalert/api/authorization_test.go index e9cdab1a24a..528644021af 100644 --- a/pkg/services/ngalert/api/authorization_test.go +++ b/pkg/services/ngalert/api/authorization_test.go @@ -49,7 +49,7 @@ func TestAuthorize(t *testing.T) { } paths[p] = methods } - require.Len(t, paths, 46) + require.Len(t, paths, 47) ac := acmock.New() api := &API{AccessControl: ac} diff --git a/pkg/services/ngalert/api/forking_alertmanager.go b/pkg/services/ngalert/api/forking_alertmanager.go index a1762ee64fb..78b87ded9a0 100644 --- a/pkg/services/ngalert/api/forking_alertmanager.go +++ b/pkg/services/ngalert/api/forking_alertmanager.go @@ -163,6 +163,10 @@ func (f *AlertmanagerApiHandler) handleRouteGetGrafanaAlertingConfigHistory(ctx return f.GrafanaSvc.RouteGetAlertingConfigHistory(ctx) } +func (f *AlertmanagerApiHandler) handleRoutePostGrafanaAlertingConfigHistoryActivate(ctx *contextmodel.ReqContext, id string) response.Response { + return f.GrafanaSvc.RoutePostGrafanaAlertingConfigHistoryActivate(ctx, id) +} + func (f *AlertmanagerApiHandler) handleRouteGetGrafanaSilence(ctx *contextmodel.ReqContext, id string) response.Response { return f.GrafanaSvc.RouteGetSilence(ctx, id) } diff --git a/pkg/services/ngalert/api/generated_base_api_alertmanager.go b/pkg/services/ngalert/api/generated_base_api_alertmanager.go index d474837b9ec..c4fff9c3238 100644 --- a/pkg/services/ngalert/api/generated_base_api_alertmanager.go +++ b/pkg/services/ngalert/api/generated_base_api_alertmanager.go @@ -42,6 +42,7 @@ type AlertmanagerApi interface { RoutePostAMAlerts(*contextmodel.ReqContext) response.Response RoutePostAlertingConfig(*contextmodel.ReqContext) response.Response RoutePostGrafanaAlertingConfig(*contextmodel.ReqContext) response.Response + RoutePostGrafanaAlertingConfigHistoryActivate(*contextmodel.ReqContext) response.Response RoutePostTestGrafanaReceivers(*contextmodel.ReqContext) response.Response } @@ -167,6 +168,11 @@ func (f *AlertmanagerApiHandler) RoutePostGrafanaAlertingConfig(ctx *contextmode } return f.handleRoutePostGrafanaAlertingConfig(ctx, conf) } +func (f *AlertmanagerApiHandler) RoutePostGrafanaAlertingConfigHistoryActivate(ctx *contextmodel.ReqContext) response.Response { + // Parse Path Parameters + idParam := web.Params(ctx.Req)[":id"] + return f.handleRoutePostGrafanaAlertingConfigHistoryActivate(ctx, idParam) +} func (f *AlertmanagerApiHandler) RoutePostTestGrafanaReceivers(ctx *contextmodel.ReqContext) response.Response { // Parse Request Body conf := apimodels.TestReceiversConfigBodyParams{} @@ -408,6 +414,16 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics m, ), ) + group.Post( + toMacaronPath("/api/alertmanager/grafana/config/history/{id}/_activate"), + api.authorize(http.MethodPost, "/api/alertmanager/grafana/config/history/{id}/_activate"), + metrics.Instrument( + http.MethodPost, + "/api/alertmanager/grafana/config/history/{id}/_activate", + srv.RoutePostGrafanaAlertingConfigHistoryActivate, + m, + ), + ) group.Post( toMacaronPath("/api/alertmanager/grafana/config/api/v1/receivers/test"), api.authorize(http.MethodPost, "/api/alertmanager/grafana/config/api/v1/receivers/test"), diff --git a/pkg/services/ngalert/api/tooling/api.json b/pkg/services/ngalert/api/tooling/api.json index 4f5222b196c..d989685b0b8 100644 --- a/pkg/services/ngalert/api/tooling/api.json +++ b/pkg/services/ngalert/api/tooling/api.json @@ -3644,6 +3644,7 @@ "type": "object" }, "alertGroup": { + "description": "AlertGroup alert group", "properties": { "alerts": { "description": "alerts", @@ -3667,6 +3668,7 @@ "type": "object" }, "alertGroups": { + "description": "AlertGroups alert groups", "items": { "$ref": "#/definitions/alertGroup" }, @@ -3771,6 +3773,7 @@ "type": "object" }, "gettableAlert": { + "description": "GettableAlert gettable alert", "properties": { "annotations": { "$ref": "#/definitions/labelSet" @@ -3826,13 +3829,13 @@ "type": "object" }, "gettableAlerts": { - "description": "GettableAlerts gettable alerts", "items": { "$ref": "#/definitions/gettableAlert" }, "type": "array" }, "gettableSilence": { + "description": "GettableSilence gettable silence", "properties": { "comment": { "description": "comment", @@ -3881,12 +3884,14 @@ "type": "object" }, "gettableSilences": { + "description": "GettableSilences gettable silences", "items": { "$ref": "#/definitions/gettableSilence" }, "type": "array" }, "integration": { + "description": "Integration integration", "properties": { "lastNotifyAttempt": { "description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time", @@ -4068,7 +4073,6 @@ "type": "object" }, "receiver": { - "description": "Receiver receiver", "properties": { "active": { "description": "active", diff --git a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go index da55966efdd..720eb99cf4c 100644 --- a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go +++ b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go @@ -61,6 +61,15 @@ import ( // Responses: // 200: GettableHistoricUserConfigs +// swagger:route POST /api/alertmanager/grafana/config/history/{id}/_activate alertmanager RoutePostGrafanaAlertingConfigHistoryActivate +// +// revert Alerting configuration to the historical configuration specified by the given id +// +// Responses: +// 202: Ack +// 400: ValidationError +// 404: NotFound + // swagger:route DELETE /api/alertmanager/grafana/config/api/v1/alerts alertmanager RouteDeleteGrafanaAlertingConfig // // deletes the Alerting config for a tenant @@ -458,6 +467,13 @@ type BodyAlertingConfig struct { Body PostableUserConfig } +// swagger:parameters RoutePostGrafanaAlertingConfigHistoryActivate +type HistoricalConfigId struct { + // Id should be the id of the GettableHistoricUserConfig + // in:path + Id int64 `json:"id"` +} + // alertmanager routes // swagger:parameters RoutePostAlertingConfig RouteGetAlertingConfig RouteDeleteAlertingConfig RouteGetAMStatus RouteGetAMAlerts RoutePostAMAlerts RouteGetAMAlertGroups RouteGetSilences RouteCreateSilence RouteGetSilence RouteDeleteSilence RoutePostAlertingConfig // testing routes diff --git a/pkg/services/ngalert/api/tooling/post.json b/pkg/services/ngalert/api/tooling/post.json index 206e5e4e113..a4f647fe6b0 100644 --- a/pkg/services/ngalert/api/tooling/post.json +++ b/pkg/services/ngalert/api/tooling/post.json @@ -3432,7 +3432,6 @@ "type": "object" }, "URL": { - "description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use the EscapedPath method, which preserves\nthe original encoding of Path.\n\nThe RawPath field is an optional field which is only set when the default\nencoding of Path is different from the escaped path. See the EscapedPath method\nfor more details.\n\nURL's String method uses the EscapedPath method to obtain the path.", "properties": { "ForceQuery": { "type": "boolean" @@ -3468,7 +3467,7 @@ "$ref": "#/definitions/Userinfo" } }, - "title": "A URL represents a parsed URL (technically, a URI reference).", + "title": "URL is a custom URL type that allows validation at configuration load time.", "type": "object" }, "Userinfo": { @@ -3882,6 +3881,7 @@ "type": "object" }, "gettableSilences": { + "description": "GettableSilences gettable silences", "items": { "$ref": "#/definitions/gettableSilence" }, @@ -4629,6 +4629,45 @@ ] } }, + "/api/alertmanager/grafana/config/history/{id}/_activate": { + "post": { + "description": "revert Alerting configuration to the historical configuration specified by the given id", + "operationId": "RoutePostGrafanaAlertingConfigHistoryActivate", + "parameters": [ + { + "description": "Id should be the id of the GettableHistoricUserConfig", + "format": "int64", + "in": "path", + "name": "id", + "required": true, + "type": "integer" + } + ], + "responses": { + "202": { + "description": "Ack", + "schema": { + "$ref": "#/definitions/Ack" + } + }, + "400": { + "description": "ValidationError", + "schema": { + "$ref": "#/definitions/ValidationError" + } + }, + "404": { + "description": "NotFound", + "schema": { + "$ref": "#/definitions/NotFound" + } + } + }, + "tags": [ + "alertmanager" + ] + } + }, "/api/alertmanager/{DatasourceUID}/api/v2/alerts": { "get": { "description": "get alertmanager alerts", diff --git a/pkg/services/ngalert/api/tooling/spec.json b/pkg/services/ngalert/api/tooling/spec.json index aebd5a0bf1c..65794ac1b02 100644 --- a/pkg/services/ngalert/api/tooling/spec.json +++ b/pkg/services/ngalert/api/tooling/spec.json @@ -458,6 +458,45 @@ } } }, + "/api/alertmanager/grafana/config/history/{id}/_activate": { + "post": { + "description": "revert Alerting configuration to the historical configuration specified by the given id", + "tags": [ + "alertmanager" + ], + "operationId": "RoutePostGrafanaAlertingConfigHistoryActivate", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "Id should be the id of the GettableHistoricUserConfig", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "202": { + "description": "Ack", + "schema": { + "$ref": "#/definitions/Ack" + } + }, + "400": { + "description": "ValidationError", + "schema": { + "$ref": "#/definitions/ValidationError" + } + }, + "404": { + "description": "NotFound", + "schema": { + "$ref": "#/definitions/NotFound" + } + } + } + } + }, "/api/alertmanager/{DatasourceUID}/api/v2/alerts": { "get": { "description": "get alertmanager alerts", @@ -6107,9 +6146,8 @@ } }, "URL": { - "description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use the EscapedPath method, which preserves\nthe original encoding of Path.\n\nThe RawPath field is an optional field which is only set when the default\nencoding of Path is different from the escaped path. See the EscapedPath method\nfor more details.\n\nURL's String method uses the EscapedPath method to obtain the path.", "type": "object", - "title": "A URL represents a parsed URL (technically, a URI reference).", + "title": "URL is a custom URL type that allows validation at configuration load time.", "properties": { "ForceQuery": { "type": "boolean" @@ -6562,6 +6600,7 @@ "$ref": "#/definitions/gettableSilence" }, "gettableSilences": { + "description": "GettableSilences gettable silences", "type": "array", "items": { "$ref": "#/definitions/gettableSilence" diff --git a/pkg/services/ngalert/eval/context.go b/pkg/services/ngalert/eval/context.go index f84a0e607f6..3cdaefceb22 100644 --- a/pkg/services/ngalert/eval/context.go +++ b/pkg/services/ngalert/eval/context.go @@ -12,7 +12,7 @@ type EvaluationContext struct { User *user.SignedInUser } -func Context(ctx context.Context, user *user.SignedInUser) EvaluationContext { +func NewContext(ctx context.Context, user *user.SignedInUser) EvaluationContext { return EvaluationContext{ Ctx: ctx, User: user, diff --git a/pkg/services/ngalert/eval/eval.go b/pkg/services/ngalert/eval/eval.go index c08bbec75e0..fd9f4b6084b 100644 --- a/pkg/services/ngalert/eval/eval.go +++ b/pkg/services/ngalert/eval/eval.go @@ -220,7 +220,7 @@ func (s State) String() string { return [...]string{"Normal", "Alerting", "Pending", "NoData", "Error"}[s] } -func buildDatasourceHeaders(ctx EvaluationContext) map[string]string { +func buildDatasourceHeaders(ctx context.Context) map[string]string { headers := map[string]string{ // Many data sources check this in query method as sometimes alerting needs special considerations. // Several existing systems also compare against the value of this header. Altering this constitutes a breaking change. @@ -233,7 +233,7 @@ func buildDatasourceHeaders(ctx EvaluationContext) map[string]string { models.CacheSkipHeaderName: "true", } - key, ok := models.RuleKeyFromContext(ctx.Ctx) + key, ok := models.RuleKeyFromContext(ctx) if ok { headers["X-Rule-Uid"] = key.UID headers["X-Grafana-Org-Id"] = strconv.FormatInt(key.OrgID, 10) @@ -246,7 +246,7 @@ func buildDatasourceHeaders(ctx EvaluationContext) map[string]string { func getExprRequest(ctx EvaluationContext, data []models.AlertQuery, dsCacheService datasources.CacheService) (*expr.Request, error) { req := &expr.Request{ OrgId: ctx.User.OrgID, - Headers: buildDatasourceHeaders(ctx), + Headers: buildDatasourceHeaders(ctx.Ctx), } datasources := make(map[string]*datasources.DataSource, len(data)) @@ -295,7 +295,8 @@ func getExprRequest(ctx EvaluationContext, data []models.AlertQuery, dsCacheServ type NumberValueCapture struct { Var string // RefID Labels data.Labels - Value *float64 + + Value *float64 } func queryDataResponseToExecutionResults(c models.Condition, execResp *backend.QueryDataResponse) ExecutionResults { diff --git a/pkg/services/ngalert/eval/eval_test.go b/pkg/services/ngalert/eval/eval_test.go index 14fdd65cb54..a69c54e31e7 100644 --- a/pkg/services/ngalert/eval/eval_test.go +++ b/pkg/services/ngalert/eval/eval_test.go @@ -533,7 +533,7 @@ func TestValidate(t *testing.T) { }) evaluator := NewEvaluatorFactory(setting.UnifiedAlertingSettings{}, cacheService, expr.ProvideService(&setting.Cfg{ExpressionsEnabled: true}, nil, nil), store) - evalCtx := Context(context.Background(), u) + evalCtx := NewContext(context.Background(), u) err := evaluator.Validate(evalCtx, condition) if testCase.error { diff --git a/pkg/services/ngalert/models/alert_query.go b/pkg/services/ngalert/models/alert_query.go index 0d4d1410a9f..6f6c437e72a 100644 --- a/pkg/services/ngalert/models/alert_query.go +++ b/pkg/services/ngalert/models/alert_query.go @@ -97,6 +97,10 @@ type AlertQuery struct { modelProps map[string]interface{} } +func (aq *AlertQuery) String() string { + return fmt.Sprintf("refID: %s, queryType: %s, datasourceUID: %s", aq.RefID, aq.QueryType, aq.DatasourceUID) +} + func (aq *AlertQuery) setModelProps() error { aq.modelProps = make(map[string]interface{}) err := json.Unmarshal(aq.Model, &aq.modelProps) diff --git a/pkg/services/ngalert/notifier/alertmanager_config.go b/pkg/services/ngalert/notifier/alertmanager_config.go index 09c02081b54..2f900d9d7c6 100644 --- a/pkg/services/ngalert/notifier/alertmanager_config.go +++ b/pkg/services/ngalert/notifier/alertmanager_config.go @@ -43,6 +43,36 @@ func (moa *MultiOrgAlertmanager) GetAlertmanagerConfiguration(ctx context.Contex return moa.gettableUserConfigFromAMConfigString(ctx, org, amConfig.AlertmanagerConfiguration) } +// ActivateHistoricalConfiguration will set the current alertmanager configuration to a previous value based on the provided +// alert_configuration_history id. +func (moa *MultiOrgAlertmanager) ActivateHistoricalConfiguration(ctx context.Context, orgId int64, id int64) error { + config, err := moa.configStore.GetHistoricalConfiguration(ctx, orgId, id) + if err != nil { + return fmt.Errorf("failed to get historical alertmanager configuration: %w", err) + } + + cfg, err := Load([]byte(config.AlertmanagerConfiguration)) + if err != nil { + return fmt.Errorf("failed to unmarshal historical alertmanager configuration: %w", err) + } + + am, err := moa.AlertmanagerFor(orgId) + if err != nil { + // It's okay if the alertmanager isn't ready yet, we're changing its config anyway. + if !errors.Is(err, ErrAlertmanagerNotReady) { + return err + } + } + + if err := am.SaveAndApplyConfig(ctx, cfg); err != nil { + moa.logger.Error("unable to save and apply historical alertmanager configuration", "error", err, "org", orgId, "id", id) + return AlertmanagerConfigRejectedError{err} + } + moa.logger.Info("applied historical alertmanager configuration", "org", orgId, "id", id) + + return nil +} + // GetAppliedAlertmanagerConfigurations returns the last n configurations marked as applied for a given org. func (moa *MultiOrgAlertmanager) GetAppliedAlertmanagerConfigurations(ctx context.Context, org int64, limit int) ([]*definitions.GettableHistoricUserConfig, error) { configs, err := moa.configStore.GetAppliedConfigurations(ctx, org, limit) diff --git a/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go b/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go index a9153587a88..7710a0783d1 100644 --- a/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go +++ b/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go @@ -18,6 +18,7 @@ import ( "github.com/grafana/grafana/pkg/services/ngalert/metrics" "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/ngalert/provisioning" + "github.com/grafana/grafana/pkg/services/ngalert/store" "github.com/grafana/grafana/pkg/services/secrets/fakes" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" "github.com/grafana/grafana/pkg/setting" @@ -298,6 +299,76 @@ func TestMultiOrgAlertmanager_AlertmanagerFor(t *testing.T) { } } +func TestMultiOrgAlertmanager_ActivateHistoricalConfiguration(t *testing.T) { + configStore := NewFakeConfigStore(t, map[int64]*models.AlertConfiguration{}) + orgStore := &FakeOrgStore{ + orgs: []int64{1, 2, 3}, + } + tmpDir := t.TempDir() + defaultConfig := `{"template_files":null,"alertmanager_config":{"route":{"receiver":"grafana-default-email","group_by":["grafana_folder","alertname"]},"templates":null,"receivers":[{"name":"grafana-default-email","grafana_managed_receiver_configs":[{"uid":"","name":"email receiver","type":"email","disableResolveMessage":false,"settings":{"addresses":"\u003cexample@email.com\u003e"},"secureSettings":null}]}]}}` + cfg := &setting.Cfg{ + DataPath: tmpDir, + UnifiedAlerting: setting.UnifiedAlertingSettings{AlertmanagerConfigPollInterval: 3 * time.Minute, DefaultConfiguration: defaultConfig}, // do not poll in tests. + } + kvStore := NewFakeKVStore(t) + provStore := provisioning.NewFakeProvisioningStore() + secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore()) + decryptFn := secretsService.GetDecryptedValue + reg := prometheus.NewPedanticRegistry() + m := metrics.NewNGAlert(reg) + mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, provStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService) + require.NoError(t, err) + ctx := context.Background() + + // Ensure that one Alertmanager is created per org. + { + require.NoError(t, mam.LoadAndSyncAlertmanagersForOrgs(ctx)) + require.Len(t, mam.alertmanagers, 3) + } + + // First, let's confirm the default configs are active. + cfgs, err := mam.getLatestConfigs(ctx) + require.NoError(t, err) + require.Equal(t, defaultConfig, cfgs[1].AlertmanagerConfiguration) + require.Equal(t, defaultConfig, cfgs[2].AlertmanagerConfiguration) + // Store id for later use. + originalId := cfgs[2].ID + require.Equal(t, defaultConfig, cfgs[3].AlertmanagerConfiguration) + + // Now let's save a new config for org 2. + newConfig := `{"template_files":null,"alertmanager_config":{"route":{"receiver":"grafana-default-email","group_by":["grafana_folder","alertname"]},"templates":null,"receivers":[{"name":"grafana-default-email","grafana_managed_receiver_configs":[{"uid":"","name":"some other name","type":"email","disableResolveMessage":false,"settings":{"addresses":"\u003cexample@email.com\u003e"},"secureSettings":null}]}]}}` + am, err := mam.AlertmanagerFor(2) + require.NoError(t, err) + + postable, err := Load([]byte(newConfig)) + require.NoError(t, err) + + err = am.SaveAndApplyConfig(ctx, postable) + require.NoError(t, err) + + // Verify that the org has the new config. + cfgs, err = mam.getLatestConfigs(ctx) + require.NoError(t, err) + require.Equal(t, newConfig, cfgs[2].AlertmanagerConfiguration) + + // First, let's try to activate a historical alertmanager config that doesn't exist. + { + err := mam.ActivateHistoricalConfiguration(ctx, 1, 42) + require.Error(t, err, store.ErrNoAlertmanagerConfiguration) + } + + // Finally, we activate the default config for org 2. + { + err := mam.ActivateHistoricalConfiguration(ctx, 2, originalId) + require.NoError(t, err) + } + + // Verify that the org has the old default config. + cfgs, err = mam.getLatestConfigs(ctx) + require.NoError(t, err) + require.Equal(t, defaultConfig, cfgs[2].AlertmanagerConfiguration) +} + var brokenConfig = ` "alertmanager_config": { "route": { diff --git a/pkg/services/ngalert/notifier/testing.go b/pkg/services/ngalert/notifier/testing.go index 22e1cef7c52..8dd7e111765 100644 --- a/pkg/services/ngalert/notifier/testing.go +++ b/pkg/services/ngalert/notifier/testing.go @@ -154,6 +154,21 @@ func (f *fakeConfigStore) GetAppliedConfigurations(_ context.Context, orgID int6 return configs, nil } +func (f *fakeConfigStore) GetHistoricalConfiguration(_ context.Context, orgID int64, id int64) (*models.HistoricAlertConfiguration, error) { + configsByOrg, ok := f.historicConfigs[orgID] + if !ok { + return &models.HistoricAlertConfiguration{}, store.ErrNoAlertmanagerConfiguration + } + + for _, conf := range configsByOrg { + if conf.ID == id && conf.OrgID == orgID { + return conf, nil + } + } + + return &models.HistoricAlertConfiguration{}, store.ErrNoAlertmanagerConfiguration +} + type FakeOrgStore struct { orgs []int64 } diff --git a/pkg/services/ngalert/schedule/schedule.go b/pkg/services/ngalert/schedule/schedule.go index a57bf6c133d..eefed6e9a4c 100644 --- a/pkg/services/ngalert/schedule/schedule.go +++ b/pkg/services/ngalert/schedule/schedule.go @@ -373,21 +373,7 @@ func (sch *schedule) ruleRoutine(grafanaCtx context.Context, key ngmodels.AlertR logger := logger.New("version", e.rule.Version, "attempt", attempt, "now", e.scheduledAt) start := sch.clock.Now() - schedulerUser := &user.SignedInUser{ - UserID: -1, - IsServiceAccount: true, - Login: "grafana_scheduler", - OrgID: e.rule.OrgID, - OrgRole: org.RoleAdmin, - Permissions: map[int64]map[string][]string{ - e.rule.OrgID: { - datasources.ActionQuery: []string{ - datasources.ScopeAll, - }, - }, - }, - } - evalCtx := eval.Context(ctx, schedulerUser) + evalCtx := eval.NewContext(ctx, SchedulerUserFor(e.rule.OrgID)) ruleEval, err := sch.evaluatorFactory.Create(evalCtx, e.rule.GetEvalCondition()) var results eval.Results var dur time.Duration @@ -580,3 +566,20 @@ func (sch *schedule) getRuleExtraLabels(evalCtx *evaluation) map[string]string { } return extraLabels } + +func SchedulerUserFor(orgID int64) *user.SignedInUser { + return &user.SignedInUser{ + UserID: -1, + IsServiceAccount: true, + Login: "grafana_scheduler", + OrgID: orgID, + OrgRole: org.RoleAdmin, + Permissions: map[int64]map[string][]string{ + orgID: { + datasources.ActionQuery: []string{ + datasources.ScopeAll, + }, + }, + }, + } +} diff --git a/pkg/services/ngalert/state/historian/annotation.go b/pkg/services/ngalert/state/historian/annotation.go index d4c45ca7418..12a3a15ea03 100644 --- a/pkg/services/ngalert/state/historian/annotation.go +++ b/pkg/services/ngalert/state/historian/annotation.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/annotations" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/ngalert/eval" @@ -67,10 +68,23 @@ func (h *AnnotationBackend) Record(ctx context.Context, rule history_model.RuleM return errCh } - go func() { + // This is a new background job, so let's create a brand new context for it. + // We want it to be isolated, i.e. we don't want grafana shutdowns to interrupt this work + // immediately but rather try to flush writes. + // This also prevents timeouts or other lingering objects (like transactions) from being + // incorrectly propagated here from other areas. + writeCtx := context.Background() + writeCtx, cancel := context.WithTimeout(writeCtx, StateHistoryWriteTimeout) + writeCtx = history_model.WithRuleData(writeCtx, rule) + writeCtx = tracing.ContextWithSpan(writeCtx, tracing.SpanFromContext(ctx)) + + go func(ctx context.Context) { + defer cancel() defer close(errCh) + logger := h.log.FromContext(ctx) + errCh <- h.recordAnnotations(ctx, panel, annotations, rule.OrgID, logger) - }() + }(writeCtx) return errCh } diff --git a/pkg/services/ngalert/state/historian/core.go b/pkg/services/ngalert/state/historian/core.go index 35b9e3ba40a..5fff26fdfd8 100644 --- a/pkg/services/ngalert/state/historian/core.go +++ b/pkg/services/ngalert/state/historian/core.go @@ -2,6 +2,7 @@ package historian import ( "strings" + "time" "github.com/grafana/grafana-plugin-sdk-go/data" @@ -12,6 +13,8 @@ import ( history_model "github.com/grafana/grafana/pkg/services/ngalert/state/historian/model" ) +const StateHistoryWriteTimeout = time.Minute + func shouldRecord(transition state.StateTransition) bool { if !transition.Changed() { return false diff --git a/pkg/services/ngalert/state/historian/loki.go b/pkg/services/ngalert/state/historian/loki.go index 0223010475b..99364a788ad 100644 --- a/pkg/services/ngalert/state/historian/loki.go +++ b/pkg/services/ngalert/state/historian/loki.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/ngalert/eval" "github.com/grafana/grafana/pkg/services/ngalert/metrics" "github.com/grafana/grafana/pkg/services/ngalert/models" @@ -80,8 +81,20 @@ func (h *RemoteLokiBackend) Record(ctx context.Context, rule history_model.RuleM return errCh } - go func() { + // This is a new background job, so let's create a brand new context for it. + // We want it to be isolated, i.e. we don't want grafana shutdowns to interrupt this work + // immediately but rather try to flush writes. + // This also prevents timeouts or other lingering objects (like transactions) from being + // incorrectly propagated here from other areas. + writeCtx := context.Background() + writeCtx, cancel := context.WithTimeout(writeCtx, StateHistoryWriteTimeout) + writeCtx = history_model.WithRuleData(writeCtx, rule) + writeCtx = tracing.ContextWithSpan(writeCtx, tracing.SpanFromContext(ctx)) + + go func(ctx context.Context) { + defer cancel() defer close(errCh) + logger := h.log.FromContext(ctx) org := fmt.Sprint(rule.OrgID) h.metrics.WritesTotal.WithLabelValues(org, "loki").Inc() @@ -93,7 +106,7 @@ func (h *RemoteLokiBackend) Record(ctx context.Context, rule history_model.RuleM h.metrics.TransitionsFailed.WithLabelValues(org).Add(float64(len(logStream.Values))) errCh <- fmt.Errorf("failed to save alert state history batch: %w", err) } - }() + }(writeCtx) return errCh } diff --git a/pkg/services/ngalert/state/historian/loki_http.go b/pkg/services/ngalert/state/historian/loki_http.go index 67ecdca2477..ff482397154 100644 --- a/pkg/services/ngalert/state/historian/loki_http.go +++ b/pkg/services/ngalert/state/historian/loki_http.go @@ -17,12 +17,8 @@ import ( "github.com/weaveworks/common/http/client" ) -const defaultClientTimeout = 30 * time.Second - func NewRequester() client.Requester { - return &http.Client{ - Timeout: defaultClientTimeout, - } + return &http.Client{} } // encoder serializes log streams to some byte format. diff --git a/pkg/services/ngalert/state/historian/model/rule.go b/pkg/services/ngalert/state/historian/model/rule.go index a63656c7560..5a76d60c9ce 100644 --- a/pkg/services/ngalert/state/historian/model/rule.go +++ b/pkg/services/ngalert/state/historian/model/rule.go @@ -1,6 +1,7 @@ package model import ( + "context" "strconv" "github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" @@ -44,3 +45,7 @@ func NewRuleMeta(r *models.AlertRule, log log.Logger) RuleMeta { PanelID: panelID, } } + +func WithRuleData(ctx context.Context, rule RuleMeta) context.Context { + return models.WithRuleKey(ctx, models.AlertRuleKey{OrgID: rule.OrgID, UID: rule.UID}) +} diff --git a/pkg/services/ngalert/state/manager.go b/pkg/services/ngalert/state/manager.go index 8b523828cb6..5161ba957cf 100644 --- a/pkg/services/ngalert/state/manager.go +++ b/pkg/services/ngalert/state/manager.go @@ -351,8 +351,6 @@ func (st *Manager) saveAlertStates(ctx context.Context, logger log.Logger, state } logger.Debug("Saving alert states", "count", len(states)) - instances := make([]ngModels.AlertInstance, 0, len(states)) - for _, s := range states { // Do not save normal state to database and remove transition to Normal state but keep mapped states if st.doNotSaveNormalState && IsNormalStateWithNoReason(s.State) && !s.Changed() { @@ -364,7 +362,7 @@ func (st *Manager) saveAlertStates(ctx context.Context, logger log.Logger, state logger.Error("Failed to create a key for alert state to save it to database. The state will be ignored ", "cacheID", s.CacheID, "error", err, "labels", s.Labels.String()) continue } - fields := ngModels.AlertInstance{ + instance := ngModels.AlertInstance{ AlertInstanceKey: key, Labels: ngModels.InstanceLabels(s.Labels), CurrentState: ngModels.InstanceStateType(s.State.State.String()), @@ -373,23 +371,11 @@ func (st *Manager) saveAlertStates(ctx context.Context, logger log.Logger, state CurrentStateSince: s.StartsAt, CurrentStateEnd: s.EndsAt, } - instances = append(instances, fields) - } - if len(instances) == 0 { - return - } - - if err := st.instanceStore.SaveAlertInstances(ctx, instances...); err != nil { - type debugInfo struct { - State string - Labels string + err = st.instanceStore.SaveAlertInstance(ctx, instance) + if err != nil { + logger.Error("Failed to save alert state", "labels", s.Labels.String(), "state", s.State, "error", err) } - debug := make([]debugInfo, 0) - for _, inst := range instances { - debug = append(debug, debugInfo{string(inst.CurrentState), data.Labels(inst.Labels).String()}) - } - logger.Error("Failed to save alert states", "states", debug, "error", err) } } diff --git a/pkg/services/ngalert/state/manager_test.go b/pkg/services/ngalert/state/manager_test.go index 67b82976d1a..b4abfee70f1 100644 --- a/pkg/services/ngalert/state/manager_test.go +++ b/pkg/services/ngalert/state/manager_test.go @@ -113,9 +113,11 @@ func TestWarmStateCache(t *testing.T) { }, } + instances := make([]models.AlertInstance, 0) + labels := models.InstanceLabels{"test1": "testValue1"} _, hash, _ := labels.StringAndHash() - instance1 := models.AlertInstance{ + instances = append(instances, models.AlertInstance{ AlertInstanceKey: models.AlertInstanceKey{ RuleOrgID: rule.OrgID, RuleUID: rule.UID, @@ -126,11 +128,11 @@ func TestWarmStateCache(t *testing.T) { CurrentStateSince: evaluationTime.Add(-1 * time.Minute), CurrentStateEnd: evaluationTime.Add(1 * time.Minute), Labels: labels, - } + }) labels = models.InstanceLabels{"test2": "testValue2"} _, hash, _ = labels.StringAndHash() - instance2 := models.AlertInstance{ + instances = append(instances, models.AlertInstance{ AlertInstanceKey: models.AlertInstanceKey{ RuleOrgID: rule.OrgID, RuleUID: rule.UID, @@ -141,11 +143,11 @@ func TestWarmStateCache(t *testing.T) { CurrentStateSince: evaluationTime.Add(-1 * time.Minute), CurrentStateEnd: evaluationTime.Add(1 * time.Minute), Labels: labels, - } + }) labels = models.InstanceLabels{"test3": "testValue3"} _, hash, _ = labels.StringAndHash() - instance3 := models.AlertInstance{ + instances = append(instances, models.AlertInstance{ AlertInstanceKey: models.AlertInstanceKey{ RuleOrgID: rule.OrgID, RuleUID: rule.UID, @@ -156,11 +158,11 @@ func TestWarmStateCache(t *testing.T) { CurrentStateSince: evaluationTime.Add(-1 * time.Minute), CurrentStateEnd: evaluationTime.Add(1 * time.Minute), Labels: labels, - } + }) labels = models.InstanceLabels{"test4": "testValue4"} _, hash, _ = labels.StringAndHash() - instance4 := models.AlertInstance{ + instances = append(instances, models.AlertInstance{ AlertInstanceKey: models.AlertInstanceKey{ RuleOrgID: rule.OrgID, RuleUID: rule.UID, @@ -171,11 +173,11 @@ func TestWarmStateCache(t *testing.T) { CurrentStateSince: evaluationTime.Add(-1 * time.Minute), CurrentStateEnd: evaluationTime.Add(1 * time.Minute), Labels: labels, - } + }) labels = models.InstanceLabels{"test5": "testValue5"} _, hash, _ = labels.StringAndHash() - instance5 := models.AlertInstance{ + instances = append(instances, models.AlertInstance{ AlertInstanceKey: models.AlertInstanceKey{ RuleOrgID: rule.OrgID, RuleUID: rule.UID, @@ -186,8 +188,10 @@ func TestWarmStateCache(t *testing.T) { CurrentStateSince: evaluationTime.Add(-1 * time.Minute), CurrentStateEnd: evaluationTime.Add(1 * time.Minute), Labels: labels, + }) + for _, instance := range instances { + _ = dbstore.SaveAlertInstance(ctx, instance) } - _ = dbstore.SaveAlertInstances(ctx, instance1, instance2, instance3, instance4, instance5) cfg := state.ManagerCfg{ Metrics: testMetrics.GetStateMetrics(), @@ -2370,7 +2374,9 @@ func TestStaleResultsHandler(t *testing.T) { }, } - _ = dbstore.SaveAlertInstances(ctx, instances...) + for _, instance := range instances { + _ = dbstore.SaveAlertInstance(ctx, instance) + } testCases := []struct { desc string @@ -2621,7 +2627,9 @@ func TestDeleteStateByRuleUID(t *testing.T) { }, } - _ = dbstore.SaveAlertInstances(ctx, instances...) + for _, instance := range instances { + _ = dbstore.SaveAlertInstance(ctx, instance) + } testCases := []struct { desc string @@ -2755,7 +2763,9 @@ func TestResetStateByRuleUID(t *testing.T) { }, } - _ = dbstore.SaveAlertInstances(ctx, instances...) + for _, instance := range instances { + _ = dbstore.SaveAlertInstance(ctx, instance) + } testCases := []struct { desc string diff --git a/pkg/services/ngalert/state/persist.go b/pkg/services/ngalert/state/persist.go index c6a23980fbc..b12deba5af6 100644 --- a/pkg/services/ngalert/state/persist.go +++ b/pkg/services/ngalert/state/persist.go @@ -11,7 +11,7 @@ import ( type InstanceStore interface { FetchOrgIds(ctx context.Context) ([]int64, error) ListAlertInstances(ctx context.Context, cmd *models.ListAlertInstancesQuery) ([]*models.AlertInstance, error) - SaveAlertInstances(ctx context.Context, cmd ...models.AlertInstance) error + SaveAlertInstance(ctx context.Context, instance models.AlertInstance) error DeleteAlertInstances(ctx context.Context, keys ...models.AlertInstanceKey) error DeleteAlertInstancesByRule(ctx context.Context, key models.AlertRuleKey) error } diff --git a/pkg/services/ngalert/state/testing.go b/pkg/services/ngalert/state/testing.go index e14b8e88d78..1b9a6fa694c 100644 --- a/pkg/services/ngalert/state/testing.go +++ b/pkg/services/ngalert/state/testing.go @@ -28,12 +28,10 @@ func (f *FakeInstanceStore) ListAlertInstances(_ context.Context, q *models.List return nil, nil } -func (f *FakeInstanceStore) SaveAlertInstances(_ context.Context, q ...models.AlertInstance) error { +func (f *FakeInstanceStore) SaveAlertInstance(_ context.Context, q models.AlertInstance) error { f.mtx.Lock() defer f.mtx.Unlock() - for _, inst := range q { - f.RecordedOps = append(f.RecordedOps, inst) - } + f.RecordedOps = append(f.RecordedOps, q) return nil } diff --git a/pkg/services/ngalert/store/alertmanager.go b/pkg/services/ngalert/store/alertmanager.go index 99552442ee9..b4d3ee81735 100644 --- a/pkg/services/ngalert/store/alertmanager.go +++ b/pkg/services/ngalert/store/alertmanager.go @@ -189,6 +189,26 @@ func (st *DBstore) GetAppliedConfigurations(ctx context.Context, orgID int64, li return configs, nil } +// GetHistoricalConfiguration returns a single historical configuration based on provided org and id. +func (st *DBstore) GetHistoricalConfiguration(ctx context.Context, orgID int64, id int64) (*models.HistoricAlertConfiguration, error) { + var config models.HistoricAlertConfiguration + if err := st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { + ok, err := sess.Table("alert_configuration_history"). + Where("id = ? AND org_id = ?", id, orgID). + Get(&config) + if err != nil { + return err + } + if !ok { + return ErrNoAlertmanagerConfiguration + } + return nil + }); err != nil { + return nil, err + } + return &config, nil +} + func (st *DBstore) deleteOldConfigurations(ctx context.Context, orgID int64, limit int) (int64, error) { if limit < 1 { return 0, fmt.Errorf("failed to delete old configurations: limit is set to '%d' but needs to be > 0", limit) @@ -219,11 +239,11 @@ func (st *DBstore) deleteOldConfigurations(ctx context.Context, orgID int64, lim } res, err := sess.Exec(` - DELETE FROM + DELETE FROM alert_configuration_history WHERE org_id = ? - AND + AND id < ? `, orgID, threshold) if err != nil { diff --git a/pkg/services/ngalert/store/alertmanager_test.go b/pkg/services/ngalert/store/alertmanager_test.go index 150adc9104d..306bbbc243f 100644 --- a/pkg/services/ngalert/store/alertmanager_test.go +++ b/pkg/services/ngalert/store/alertmanager_test.go @@ -425,6 +425,61 @@ func TestIntegrationGetAppliedConfigurations(t *testing.T) { }) } +func TestIntegrationGetHistoricalConfiguration(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + sqlStore := db.InitTestDB(t) + store := &DBstore{ + SQLStore: sqlStore, + Logger: log.NewNopLogger(), + } + + // Tracks the autogenerated PK for the history table. + var historyTablePK int64 = 0 + + t.Run("no configurations = error", func(tt *testing.T) { + _, err := store.GetHistoricalConfiguration(context.Background(), 10, 10) + require.Error(tt, err) + }) + + t.Run("correct configurations should be returned", func(tt *testing.T) { + ctx := context.Background() + var org int64 = 1 + setupConfigInOrg(t, "testa", org, store) + historyTablePK += 1 + setupConfigInOrg(t, "testb", org, store) + historyTablePK += 1 + + cfg, err := store.GetHistoricalConfiguration(ctx, org, historyTablePK) + require.NoError(tt, err) + + // Check that the returned configuration is the one that we're expecting. + require.Equal(tt, "testb", cfg.AlertmanagerConfiguration) + }) + + t.Run("configurations from other orgs should not be retrievable by id", func(tt *testing.T) { + ctx := context.Background() + var org int64 = 1 + setupConfigInOrg(t, "test1", org, store) + historyTablePK += 1 + + // Create a config in a different org. + var otherOrg int64 = 2 + setupConfigInOrg(t, "test2", otherOrg, store) + historyTablePK += 1 + + // Sanity check that config is retrievable with correct org and id. + cfg, err := store.GetHistoricalConfiguration(ctx, otherOrg, historyTablePK) + require.NoError(tt, err) + require.Equal(tt, "test2", cfg.AlertmanagerConfiguration) + + // Verify that we cannot retrieve the config from org=2 when passing in org=1. + _, err = store.GetHistoricalConfiguration(ctx, org, historyTablePK) + require.Error(tt, err, ErrNoAlertmanagerConfiguration) + }) +} + func setupConfig(t *testing.T, config string, store *DBstore) (string, string) { t.Helper() return setupConfigInOrg(t, config, 1, store) diff --git a/pkg/services/ngalert/store/database.go b/pkg/services/ngalert/store/database.go index f91ac4788f7..16a170ae23e 100644 --- a/pkg/services/ngalert/store/database.go +++ b/pkg/services/ngalert/store/database.go @@ -29,6 +29,7 @@ type AlertingStore interface { UpdateAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error MarkConfigurationAsApplied(ctx context.Context, cmd *models.MarkConfigurationAsAppliedCmd) error GetAppliedConfigurations(ctx context.Context, orgID int64, limit int) ([]*models.HistoricAlertConfiguration, error) + GetHistoricalConfiguration(ctx context.Context, orgID int64, id int64) (*models.HistoricAlertConfiguration, error) } // DBstore stores the alert definitions and instances in the database. diff --git a/pkg/services/ngalert/store/instance_database.go b/pkg/services/ngalert/store/instance_database.go index 8583a40e474..0c31bc620fe 100644 --- a/pkg/services/ngalert/store/instance_database.go +++ b/pkg/services/ngalert/store/instance_database.go @@ -43,99 +43,6 @@ func (st DBstore) ListAlertInstances(ctx context.Context, cmd *models.ListAlertI return result, err } -// SaveAlertInstances saves all the provided alert instances to the store. -func (st DBstore) SaveAlertInstances(ctx context.Context, cmd ...models.AlertInstance) error { - if !st.FeatureToggles.IsEnabled(featuremgmt.FlagAlertingBigTransactions) { - // This mimics the replace code-path by calling SaveAlertInstance in a loop, with a transaction per call. - for _, c := range cmd { - err := st.SaveAlertInstance(ctx, c) - if err != nil { - return err - } - } - return nil - } else { - // Batches write into statements with `maxRows` instances per statements. - // This makes sure we don't create statements that are too long for some - // databases to process. For example, SQLite has a limit of 999 variables - // per write. - keyNames := []string{"rule_org_id", "rule_uid", "labels_hash"} - fieldNames := []string{ - "rule_org_id", "rule_uid", "labels", "labels_hash", "current_state", - "current_reason", "current_state_since", "current_state_end", "last_eval_time", - } - fieldsPerRow := len(fieldNames) - maxRows := 20 - maxArgs := maxRows * fieldsPerRow - - bigUpsertSQL, err := st.SQLStore.GetDialect().UpsertMultipleSQL( - "alert_instance", keyNames, fieldNames, maxRows) - if err != nil { - return err - } - - // Args contains the SQL statement, and the values to fill into the SQL statement. - args := make([]interface{}, 0, maxArgs) - args = append(args, bigUpsertSQL) - values := func(a []interface{}) int { - return len(a) - 1 - } - - // Generate batches of `maxRows` and write the statements when full. - for _, alertInstance := range cmd { - labelTupleJSON, err := alertInstance.Labels.StringKey() - if err != nil { - return err - } - - if err := models.ValidateAlertInstance(alertInstance); err != nil { - return err - } - - args = append(args, - alertInstance.RuleOrgID, alertInstance.RuleUID, labelTupleJSON, alertInstance.LabelsHash, - alertInstance.CurrentState, alertInstance.CurrentReason, alertInstance.CurrentStateSince.Unix(), - alertInstance.CurrentStateEnd.Unix(), alertInstance.LastEvalTime.Unix()) - - // If we've reached the maximum batch size, write to the database. - if values(args) >= maxArgs { - err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { - _, err := sess.Exec(args...) - return err - }) - if err != nil { - return fmt.Errorf("failed to save alert instances: %w", err) - } - - // Reset args so we can re-use the allocated interface pointers. - args = args[:1] - } - } - - // Write the final batch of up to maxRows in size. - if values(args) != 0 && values(args)%fieldsPerRow == 0 { - upsertSQL, err := st.SQLStore.GetDialect().UpsertMultipleSQL( - "alert_instance", keyNames, fieldNames, values(args)/fieldsPerRow) - if err != nil { - return err - } - - args[0] = upsertSQL - err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { - _, err := sess.Exec(args...) - return err - }) - if err != nil { - return fmt.Errorf("failed to save alert instances: %w", err) - } - } else if values(args) != 0 { - return fmt.Errorf("failed to upsert alert instances. Last statements had %v fields, which is not a multiple of the number of fields, %v", len(args), fieldsPerRow) - } - - return nil - } -} - // SaveAlertInstance is a handler for saving a new alert instance. func (st DBstore) SaveAlertInstance(ctx context.Context, alertInstance models.AlertInstance) error { return st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { diff --git a/pkg/services/ngalert/store/instance_database_test.go b/pkg/services/ngalert/store/instance_database_test.go index 5cb8088bcf9..3a055dab3cc 100644 --- a/pkg/services/ngalert/store/instance_database_test.go +++ b/pkg/services/ngalert/store/instance_database_test.go @@ -19,7 +19,6 @@ func BenchmarkAlertInstanceOperations(b *testing.B) { b.StopTimer() ctx := context.Background() _, dbstore := tests.SetupTestEnv(b, baseIntervalSeconds) - dbstore.FeatureToggles = featuremgmt.WithFeatures(featuremgmt.FlagAlertingBigTransactions) const mainOrgID int64 = 1 @@ -48,78 +47,13 @@ func BenchmarkAlertInstanceOperations(b *testing.B) { b.StartTimer() for i := 0; i < b.N; i++ { - _ = dbstore.SaveAlertInstances(ctx, instances...) + for _, instance := range instances { + _ = dbstore.SaveAlertInstance(ctx, instance) + } _ = dbstore.DeleteAlertInstances(ctx, keys...) } } -func TestIntegrationAlertInstanceBulkWrite(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } - ctx := context.Background() - _, dbstore := tests.SetupTestEnv(t, baseIntervalSeconds) - - orgIDs := []int64{1, 2, 3, 4, 5} - counts := []int{10_000, 200, 503, 0, 1256} - instances := make([]models.AlertInstance, 0, 10_000+200+503+0+1256) - keys := make([]models.AlertInstanceKey, 0, 10_000+200+503+0+1256) - - for i, id := range orgIDs { - alertRule := tests.CreateTestAlertRule(t, ctx, dbstore, 60, id) - - // Create some instances to write down and then delete. - for j := 0; j < counts[i]; j++ { - labels := models.InstanceLabels{"test": fmt.Sprint(j)} - _, labelsHash, _ := labels.StringAndHash() - instance := models.AlertInstance{ - AlertInstanceKey: models.AlertInstanceKey{ - RuleOrgID: alertRule.OrgID, - RuleUID: alertRule.UID, - LabelsHash: labelsHash, - }, - CurrentState: models.InstanceStateFiring, - CurrentReason: string(models.InstanceStateError), - Labels: labels, - } - instances = append(instances, instance) - keys = append(keys, instance.AlertInstanceKey) - } - } - - for _, bigStmts := range []bool{false, true} { - dbstore.FeatureToggles = featuremgmt.WithFeatures([]interface{}{featuremgmt.FlagAlertingBigTransactions, bigStmts}) - t.Log("Saving") - err := dbstore.SaveAlertInstances(ctx, instances...) - require.NoError(t, err) - t.Log("Finished database write") - - // List our instances. Make sure we have the right count. - for i, id := range orgIDs { - q := &models.ListAlertInstancesQuery{ - RuleOrgID: id, - } - alerts, err := dbstore.ListAlertInstances(ctx, q) - require.NoError(t, err) - require.Equal(t, counts[i], len(alerts), "Org %v: Expected %v instances but got %v", id, counts[i], len(alerts)) - } - t.Log("Finished database read") - - err = dbstore.DeleteAlertInstances(ctx, keys...) - require.NoError(t, err) - t.Log("Finished database delete") - - for _, id := range orgIDs { - q := &models.ListAlertInstancesQuery{ - RuleOrgID: id, - } - alerts, err := dbstore.ListAlertInstances(ctx, q) - require.NoError(t, err) - require.Zero(t, len(alerts), "Org %v: Deleted instances but still had %v", id, len(alerts)) - } - } -} - func TestIntegrationAlertInstanceOperations(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") @@ -164,7 +98,7 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) { CurrentReason: string(models.InstanceStateError), Labels: labels, } - err := dbstore.SaveAlertInstances(ctx, instance) + err := dbstore.SaveAlertInstance(ctx, instance) require.NoError(t, err) listCmd := &models.ListAlertInstancesQuery{ @@ -193,7 +127,7 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) { CurrentState: models.InstanceStateNormal, Labels: labels, } - err := dbstore.SaveAlertInstances(ctx, instance) + err := dbstore.SaveAlertInstance(ctx, instance) require.NoError(t, err) listCmd := &models.ListAlertInstancesQuery{ @@ -223,7 +157,7 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) { Labels: labels, } - err := dbstore.SaveAlertInstances(ctx, instance1) + err := dbstore.SaveAlertInstance(ctx, instance1) require.NoError(t, err) labels = models.InstanceLabels{"test": "testValue2"} @@ -237,7 +171,7 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) { CurrentState: models.InstanceStateFiring, Labels: labels, } - err = dbstore.SaveAlertInstances(ctx, instance2) + err = dbstore.SaveAlertInstance(ctx, instance2) require.NoError(t, err) listQuery := &models.ListAlertInstancesQuery{ @@ -284,7 +218,9 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) { CurrentReason: models.StateReasonError, Labels: labels, } - err := dbstore.SaveAlertInstances(ctx, instance1, instance2) + err := dbstore.SaveAlertInstance(ctx, instance1) + require.NoError(t, err) + err = dbstore.SaveAlertInstance(ctx, instance2) require.NoError(t, err) listQuery := &models.ListAlertInstancesQuery{ @@ -327,7 +263,7 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) { Labels: labels, } - err := dbstore.SaveAlertInstances(ctx, instance1) + err := dbstore.SaveAlertInstance(ctx, instance1) require.NoError(t, err) instance2 := models.AlertInstance{ @@ -339,7 +275,7 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) { CurrentState: models.InstanceStateNormal, Labels: instance1.Labels, } - err = dbstore.SaveAlertInstances(ctx, instance2) + err = dbstore.SaveAlertInstance(ctx, instance2) require.NoError(t, err) listQuery := &models.ListAlertInstancesQuery{ diff --git a/pkg/services/pluginsintegration/config/config.go b/pkg/services/pluginsintegration/config/config.go new file mode 100644 index 00000000000..24d1e5c2f03 --- /dev/null +++ b/pkg/services/pluginsintegration/config/config.go @@ -0,0 +1,59 @@ +package config + +import ( + "fmt" + "strings" + + pCfg "github.com/grafana/grafana/pkg/plugins/config" + "github.com/grafana/grafana/pkg/setting" +) + +func ProvideConfig(settingProvider setting.Provider, grafanaCfg *setting.Cfg) (*pCfg.Cfg, error) { + plugins := settingProvider.Section("plugins") + allowedUnsigned := grafanaCfg.PluginsAllowUnsigned + if len(plugins.KeyValue("allow_loading_unsigned_plugins").Value()) > 0 { + allowedUnsigned = strings.Split(plugins.KeyValue("allow_loading_unsigned_plugins").Value(), ",") + } + + aws := settingProvider.Section("aws") + allowedAuth := grafanaCfg.AWSAllowedAuthProviders + if len(aws.KeyValue("allowed_auth_providers").Value()) > 0 { + allowedUnsigned = strings.Split(settingProvider.KeyValue("plugins", "allow_loading_unsigned_plugins").Value(), ",") + } + + tracingCfg, err := newTracingCfg(grafanaCfg) + if err != nil { + return nil, fmt.Errorf("new opentelemetry cfg: %w", err) + } + return pCfg.NewCfg( + settingProvider.KeyValue("", "app_mode").MustBool(grafanaCfg.Env == setting.Dev), + grafanaCfg.PluginsPath, + extractPluginSettings(settingProvider), + allowedUnsigned, + allowedAuth, + aws.KeyValue("assume_role_enabled").MustBool(grafanaCfg.AWSAssumeRoleEnabled), + grafanaCfg.Azure, + grafanaCfg.BuildVersion, + grafanaCfg.PluginLogBackendRequests, + grafanaCfg.PluginsCDNURLTemplate, + tracingCfg, + ), nil +} + +func extractPluginSettings(settingProvider setting.Provider) setting.PluginSettings { + ps := setting.PluginSettings{} + for sectionName, sectionCopy := range settingProvider.Current() { + if !strings.HasPrefix(sectionName, "plugin.") { + continue + } + // Calling Current() returns a redacted version of section. We need to replace the map values with the unredacted values. + section := settingProvider.Section(sectionName) + for k := range sectionCopy { + sectionCopy[k] = section.KeyValue(k).MustString("") + } + pluginID := strings.Replace(sectionName, "plugin.", "", 1) + ps[pluginID] = sectionCopy + } + + return ps +} diff --git a/pkg/plugins/config/config_test.go b/pkg/services/pluginsintegration/config/config_test.go similarity index 100% rename from pkg/plugins/config/config_test.go rename to pkg/services/pluginsintegration/config/config_test.go diff --git a/pkg/services/pluginsintegration/config/tracing.go b/pkg/services/pluginsintegration/config/tracing.go new file mode 100644 index 00000000000..1f5ad963a83 --- /dev/null +++ b/pkg/services/pluginsintegration/config/tracing.go @@ -0,0 +1,27 @@ +package config + +import ( + "fmt" + + "github.com/grafana/grafana/pkg/infra/tracing" + pCfg "github.com/grafana/grafana/pkg/plugins/config" + "github.com/grafana/grafana/pkg/setting" +) + +// newTracingCfg creates a plugins tracing configuration based on the provided Grafana tracing config. +// If OpenTelemetry (OTLP) is disabled, a zero-value OpenTelemetryCfg is returned. +func newTracingCfg(grafanaCfg *setting.Cfg) (pCfg.Tracing, error) { + ots, err := tracing.ParseSettingsOpentelemetry(grafanaCfg) + if err != nil { + return pCfg.Tracing{}, fmt.Errorf("parse settings: %w", err) + } + if !ots.OTelExporterEnabled() { + return pCfg.Tracing{}, nil + } + return pCfg.Tracing{ + OpenTelemetry: pCfg.OpenTelemetryCfg{ + Address: ots.Address, + Propagation: ots.Propagation, + }, + }, nil +} diff --git a/pkg/plugins/config/tracing_test.go b/pkg/services/pluginsintegration/config/tracing_test.go similarity index 61% rename from pkg/plugins/config/tracing_test.go rename to pkg/services/pluginsintegration/config/tracing_test.go index cc24b7162a7..6f5367da02c 100644 --- a/pkg/plugins/config/tracing_test.go +++ b/pkg/services/pluginsintegration/config/tracing_test.go @@ -8,15 +8,15 @@ import ( "github.com/stretchr/testify/require" ) -func TestNewOpentelemetryCfg(t *testing.T) { +func TestNewTracingCfg(t *testing.T) { t.Run("empty", func(t *testing.T) { cfg := setting.NewCfg() - otelCfg, err := NewOpentelemetryCfg(cfg) + tracingCfg, err := newTracingCfg(cfg) require.NoError(t, err) - assert.False(t, otelCfg.IsEnabled(), "otel should be disabled") - assert.Empty(t, otelCfg.Address) - assert.Empty(t, otelCfg.Propagation) + assert.False(t, tracingCfg.IsEnabled(), "tracing should be disabled") + assert.Empty(t, tracingCfg.OpenTelemetry.Address) + assert.Empty(t, tracingCfg.OpenTelemetry.Propagation) }) t.Run("enabled", func(t *testing.T) { @@ -39,11 +39,11 @@ func TestNewOpentelemetryCfg(t *testing.T) { otlpSect.Key("propagation").SetValue(tc.propagation) } - otelCfg, err := NewOpentelemetryCfg(cfg) + tracingCfg, err := newTracingCfg(cfg) require.NoError(t, err) - assert.True(t, otelCfg.IsEnabled(), "otel should be enabled") - assert.Equal(t, address, otelCfg.Address) - assert.Equal(t, tc.propagation, otelCfg.Propagation) + assert.True(t, tracingCfg.IsEnabled(), "tracing should be enabled") + assert.Equal(t, address, tracingCfg.OpenTelemetry.Address) + assert.Equal(t, tc.propagation, tracingCfg.OpenTelemetry.Propagation) }) } }) diff --git a/pkg/services/pluginsintegration/pluginsintegration.go b/pkg/services/pluginsintegration/pluginsintegration.go index 535c5e41913..1434b9a2dbb 100644 --- a/pkg/services/pluginsintegration/pluginsintegration.go +++ b/pkg/services/pluginsintegration/pluginsintegration.go @@ -7,7 +7,7 @@ import ( "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin" "github.com/grafana/grafana/pkg/plugins/backendplugin/provider" - "github.com/grafana/grafana/pkg/plugins/config" + pCfg "github.com/grafana/grafana/pkg/plugins/config" "github.com/grafana/grafana/pkg/plugins/manager" "github.com/grafana/grafana/pkg/plugins/manager/client" "github.com/grafana/grafana/pkg/plugins/manager/filestore" @@ -23,6 +23,7 @@ import ( "github.com/grafana/grafana/pkg/plugins/repo" "github.com/grafana/grafana/pkg/services/oauthtoken" "github.com/grafana/grafana/pkg/services/pluginsintegration/clientmiddleware" + "github.com/grafana/grafana/pkg/services/pluginsintegration/config" "github.com/grafana/grafana/pkg/services/pluginsintegration/licensing" "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings" @@ -76,14 +77,14 @@ var WireExtensionSet = wire.NewSet( finder.NewLocalFinder, ) -func ProvideClientDecorator(cfg *setting.Cfg, pCfg *config.Cfg, +func ProvideClientDecorator(cfg *setting.Cfg, pCfg *pCfg.Cfg, pluginRegistry registry.Service, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer) (*client.Decorator, error) { return NewClientDecorator(cfg, pCfg, pluginRegistry, oAuthTokenService, tracer) } -func NewClientDecorator(cfg *setting.Cfg, pCfg *config.Cfg, +func NewClientDecorator(cfg *setting.Cfg, pCfg *pCfg.Cfg, pluginRegistry registry.Service, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer) (*client.Decorator, error) { diff --git a/pkg/services/publicdashboards/service/query.go b/pkg/services/publicdashboards/service/query.go index 35180debcfb..22c6fd4f96c 100644 --- a/pkg/services/publicdashboards/service/query.go +++ b/pkg/services/publicdashboards/service/query.go @@ -213,7 +213,10 @@ func getUniqueDashboardDatasourceUids(dashboard *simplejson.Json) []string { var datasourceUids []string exists := map[string]bool{} - for _, panelObj := range dashboard.Get("panels").MustArray() { + // collapsed rows contain panels in a nested structure, so we need to flatten them before calculate unique uids + flattenedPanels := getFlattenedPanels(dashboard) + + for _, panelObj := range flattenedPanels { panel := simplejson.NewFromAny(panelObj) uid := getDataSourceUidFromJson(panel) @@ -238,6 +241,23 @@ func getUniqueDashboardDatasourceUids(dashboard *simplejson.Json) []string { return datasourceUids } +func getFlattenedPanels(dashboard *simplejson.Json) []interface{} { + var flatPanels []interface{} + for _, panelObj := range dashboard.Get("panels").MustArray() { + panel := simplejson.NewFromAny(panelObj) + // if the panel is a row and it is collapsed, get the queries from the panels inside the row + // if it is not collapsed, the row does not have any panels + if panel.Get("type").MustString() == "row" { + if panel.Get("collapsed").MustBool() { + flatPanels = append(flatPanels, panel.Get("panels").MustArray()...) + } + } else { + flatPanels = append(flatPanels, panelObj) + } + } + return flatPanels +} + func groupQueriesByPanelId(dashboard *simplejson.Json) map[int64][]*simplejson.Json { result := make(map[int64][]*simplejson.Json) diff --git a/pkg/services/publicdashboards/service/query_test.go b/pkg/services/publicdashboards/service/query_test.go index 1d8ccf2e8bd..ecc0aff01db 100644 --- a/pkg/services/publicdashboards/service/query_test.go +++ b/pkg/services/publicdashboards/service/query_test.go @@ -432,6 +432,218 @@ const ( ], "schemaVersion": 35 }` + + dashboardWithCollapsedRows = ` +{ +"panels": [ + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 12, + "title": "Row title", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "qCbTUC37k" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "qCbTUC37k" + }, + "editorMode": "builder", + "expr": "access_evaluation_duration_bucket", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Panel Title", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 10, + "panels": [ + { + "datasource": { + "type": "influxdb", + "uid": "P49A45DF074423DFB" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.4.0-pre", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "P49A45DF074423DFB" + }, + "query": "// v.bucket, v.timeRangeStart, and v.timeRange stop are all variables supported by the flux plugin and influxdb\nfrom(bucket: v.bucket)\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_value\"] >= 10 and r[\"_value\"] <= 20)", + "refId": "A" + } + ], + "title": "Panel Title", + "type": "timeseries" + } + ], + "title": "Row title 1", + "type": "row" + } + ] +}` ) func TestGetQueryDataResponse(t *testing.T) { @@ -500,7 +712,7 @@ func TestFindAnnotations(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) config := setting.NewCfg() tagService := tagimpl.ProvideService(sqlStore, sqlStore.Cfg) - annotationsRepo := annotationsimpl.ProvideService(sqlStore, config, tagService) + annotationsRepo := annotationsimpl.ProvideService(sqlStore, config, featuremgmt.WithFeatures(), tagService) fakeStore := FakePublicDashboardStore{} service := &PublicDashboardServiceImpl{ log: log.New("test.logger"), @@ -951,6 +1163,16 @@ func TestGetUniqueDashboardDatasourceUids(t *testing.T) { uids := getUniqueDashboardDatasourceUids(json) require.Len(t, uids, 0) }) + + t.Run("can get unique datasource ids from dashboard with rows", func(t *testing.T) { + json, err := simplejson.NewJson([]byte(dashboardWithCollapsedRows)) + require.NoError(t, err) + + uids := getUniqueDashboardDatasourceUids(json) + require.Len(t, uids, 2) + require.Equal(t, "qCbTUC37k", uids[0]) + require.Equal(t, "P49A45DF074423DFB", uids[1]) + }) } func TestBuildMetricRequest(t *testing.T) { diff --git a/pkg/services/sqlstore/permissions/dashboard.go b/pkg/services/sqlstore/permissions/dashboard.go index bb50a034061..0a1501795c1 100644 --- a/pkg/services/sqlstore/permissions/dashboard.go +++ b/pkg/services/sqlstore/permissions/dashboard.go @@ -1,16 +1,23 @@ package permissions import ( + "bytes" + "fmt" "strings" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "github.com/grafana/grafana/pkg/services/user" ) +// maximum possible capacity for recursive queries array: one query for folder and one for dashboard actions +const maximumRecursiveQueries = 2 + type DashboardPermissionFilter struct { OrgRole org.RoleType Dialect migrator.Dialect @@ -78,14 +85,25 @@ func (d DashboardPermissionFilter) Where() (string, []interface{}) { return sql, params } -type AccessControlDashboardPermissionFilter struct { +type clause struct { + string + params []interface{} +} + +type accessControlDashboardPermissionFilter struct { user *user.SignedInUser dashboardActions []string folderActions []string + features featuremgmt.FeatureToggles + + where clause + // any recursive CTE queries (if supported) + recQueries []clause + recursiveQueriesAreSupported bool } // NewAccessControlDashboardPermissionFilter creates a new AccessControlDashboardPermissionFilter that is configured with specific actions calculated based on the dashboards.PermissionType and query type -func NewAccessControlDashboardPermissionFilter(user *user.SignedInUser, permissionLevel dashboards.PermissionType, queryType string) AccessControlDashboardPermissionFilter { +func NewAccessControlDashboardPermissionFilter(user *user.SignedInUser, permissionLevel dashboards.PermissionType, queryType string, features featuremgmt.FeatureToggles, recursiveQueriesAreSupported bool) *accessControlDashboardPermissionFilter { needEdit := permissionLevel > dashboards.PERMISSION_VIEW var folderActions []string @@ -121,12 +139,26 @@ func NewAccessControlDashboardPermissionFilter(user *user.SignedInUser, permissi } } - return AccessControlDashboardPermissionFilter{user: user, folderActions: folderActions, dashboardActions: dashboardActions} + f := accessControlDashboardPermissionFilter{user: user, folderActions: folderActions, dashboardActions: dashboardActions, features: features, + recursiveQueriesAreSupported: recursiveQueriesAreSupported, + } + + f.buildClauses() + + return &f } -func (f AccessControlDashboardPermissionFilter) Where() (string, []interface{}) { +// Where returns: +// - a where clause for filtering dashboards with expected permissions +// - an array with the query parameters +func (f *accessControlDashboardPermissionFilter) Where() (string, []interface{}) { + return f.where.string, f.where.params +} + +func (f *accessControlDashboardPermissionFilter) buildClauses() { if f.user == nil || f.user.Permissions == nil || f.user.Permissions[f.user.OrgID] == nil { - return "(1 = 0)", nil + f.where = clause{string: "(1 = 0)"} + return } dashWildcards := accesscontrol.WildcardsFromPrefix(dashboards.ScopeDashboardsPrefix) folderWildcards := accesscontrol.WildcardsFromPrefix(dashboards.ScopeFoldersPrefix) @@ -136,6 +168,10 @@ func (f AccessControlDashboardPermissionFilter) Where() (string, []interface{}) var args []interface{} builder := strings.Builder{} builder.WriteRune('(') + + permSelector := strings.Builder{} + var permSelectorArgs []interface{} + if len(f.dashboardActions) > 0 { toCheck := actionsToCheck(f.dashboardActions, f.user.Permissions[f.user.OrgID], dashWildcards, folderWildcards) @@ -155,24 +191,50 @@ func (f AccessControlDashboardPermissionFilter) Where() (string, []interface{}) builder.WriteString(") AND NOT dashboard.is_folder)") builder.WriteString(" OR ") - builder.WriteString("(dashboard.folder_id IN (SELECT id FROM dashboard as d WHERE d.uid IN (SELECT substr(scope, 13) FROM permission WHERE scope LIKE 'folders:uid:%' ") - builder.WriteString(rolesFilter) - args = append(args, params...) + permSelector.WriteString("(SELECT substr(scope, 13) FROM permission WHERE scope LIKE 'folders:uid:%' ") + permSelector.WriteString(rolesFilter) + permSelectorArgs = append(permSelectorArgs, params...) if len(toCheck) == 1 { - builder.WriteString(" AND action = ?") - args = append(args, toCheck[0]) + permSelector.WriteString(" AND action = ?") + permSelectorArgs = append(permSelectorArgs, toCheck[0]) } else { - builder.WriteString(" AND action IN (?" + strings.Repeat(", ?", len(toCheck)-1) + ") GROUP BY role_id, scope HAVING COUNT(action) = ?") - args = append(args, toCheck...) - args = append(args, len(toCheck)) + permSelector.WriteString(" AND action IN (?" + strings.Repeat(", ?", len(toCheck)-1) + ") GROUP BY role_id, scope HAVING COUNT(action) = ?") + permSelectorArgs = append(permSelectorArgs, toCheck...) + permSelectorArgs = append(permSelectorArgs, len(toCheck)) } - builder.WriteString(")) AND NOT dashboard.is_folder)") + permSelector.WriteRune(')') + + switch f.features.IsEnabled(featuremgmt.FlagNestedFolders) { + case true: + switch f.recursiveQueriesAreSupported { + case true: + recQueryName := fmt.Sprintf("RecQry%d", len(f.recQueries)) + f.addRecQry(recQueryName, permSelector.String(), permSelectorArgs) + builder.WriteString("(dashboard.folder_id IN (SELECT d.id FROM dashboard as d ") + builder.WriteString(fmt.Sprintf("WHERE d.uid IN (SELECT uid FROM %s)", recQueryName)) + default: + nestedFoldersSelectors, nestedFoldersArgs := nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "folder_id", "id") + builder.WriteRune('(') + builder.WriteString(nestedFoldersSelectors) + args = append(args, nestedFoldersArgs...) + } + default: + builder.WriteString("(dashboard.folder_id IN (SELECT d.id FROM dashboard as d ") + builder.WriteString("WHERE d.uid IN ") + builder.WriteString(permSelector.String()) + args = append(args, permSelectorArgs...) + } + builder.WriteString(") AND NOT dashboard.is_folder)") } else { builder.WriteString("NOT dashboard.is_folder") } } + // recycle and reuse + permSelector.Reset() + permSelectorArgs = permSelectorArgs[:0] + if len(f.folderActions) > 0 { if len(f.dashboardActions) > 0 { builder.WriteString(" OR ") @@ -180,24 +242,80 @@ func (f AccessControlDashboardPermissionFilter) Where() (string, []interface{}) toCheck := actionsToCheck(f.folderActions, f.user.Permissions[f.user.OrgID], folderWildcards) if len(toCheck) > 0 { - builder.WriteString("(dashboard.uid IN (SELECT substr(scope, 13) FROM permission WHERE scope LIKE 'folders:uid:%'") - builder.WriteString(rolesFilter) - args = append(args, params...) + permSelector.WriteString("(SELECT substr(scope, 13) FROM permission WHERE scope LIKE 'folders:uid:%'") + permSelector.WriteString(rolesFilter) + permSelectorArgs = append(permSelectorArgs, params...) if len(toCheck) == 1 { - builder.WriteString(" AND action = ?") - args = append(args, toCheck[0]) + permSelector.WriteString(" AND action = ?") + permSelectorArgs = append(permSelectorArgs, toCheck[0]) } else { - builder.WriteString(" AND action IN (?" + strings.Repeat(", ?", len(toCheck)-1) + ") GROUP BY role_id, scope HAVING COUNT(action) = ?") - args = append(args, toCheck...) - args = append(args, len(toCheck)) + permSelector.WriteString(" AND action IN (?" + strings.Repeat(", ?", len(toCheck)-1) + ") GROUP BY role_id, scope HAVING COUNT(action) = ?") + permSelectorArgs = append(permSelectorArgs, toCheck...) + permSelectorArgs = append(permSelectorArgs, len(toCheck)) } - builder.WriteString(") AND dashboard.is_folder)") + permSelector.WriteRune(')') + + switch f.features.IsEnabled(featuremgmt.FlagNestedFolders) { + case true: + switch f.recursiveQueriesAreSupported { + case true: + recQueryName := fmt.Sprintf("RecQry%d", len(f.recQueries)) + f.addRecQry(recQueryName, permSelector.String(), permSelectorArgs) + builder.WriteString("(dashboard.uid IN ") + builder.WriteString(fmt.Sprintf("(SELECT uid FROM %s)", recQueryName)) + default: + nestedFoldersSelectors, nestedFoldersArgs := nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "uid", "uid") + builder.WriteRune('(') + builder.WriteString(nestedFoldersSelectors) + builder.WriteRune(')') + args = append(args, nestedFoldersArgs...) + } + default: + builder.WriteString("(dashboard.uid IN ") + builder.WriteString(permSelector.String()) + args = append(args, permSelectorArgs...) + } + builder.WriteString(" AND dashboard.is_folder)") } else { builder.WriteString("dashboard.is_folder") } } builder.WriteRune(')') - return builder.String(), args + + f.where = clause{string: builder.String(), params: args} +} + +// With returns: +// - a with clause for fetching folders with inherited permissions if nested folders are enabled or an empty string +func (f *accessControlDashboardPermissionFilter) With() (string, []interface{}) { + var sb bytes.Buffer + var params []interface{} + if len(f.recQueries) > 0 { + sb.WriteString("WITH RECURSIVE ") + sb.WriteString(f.recQueries[0].string) + params = append(params, f.recQueries[0].params...) + for _, r := range f.recQueries[1:] { + sb.WriteRune(',') + sb.WriteString(r.string) + params = append(params, r.params...) + } + } + return sb.String(), params +} + +func (f *accessControlDashboardPermissionFilter) addRecQry(queryName string, whereUIDSelect string, whereParams []interface{}) { + if f.recQueries == nil { + f.recQueries = make([]clause, 0, maximumRecursiveQueries) + } + c := make([]interface{}, len(whereParams)) + copy(c, whereParams) + f.recQueries = append(f.recQueries, clause{ + string: fmt.Sprintf(`%s AS ( + SELECT uid, parent_uid, org_id FROM folder WHERE uid IN %s + UNION ALL SELECT f.uid, f.parent_uid, f.org_id FROM folder f INNER JOIN %s r ON f.parent_uid = r.uid and f.org_id = r.org_id + )`, queryName, whereUIDSelect, queryName), + params: c, + }) } func actionsToCheck(actions []string, permissions map[string][]string, wildcards ...accesscontrol.Wildcards) []interface{} { @@ -222,3 +340,28 @@ func actionsToCheck(actions []string, permissions map[string][]string, wildcards } return toCheck } + +func nestedFoldersSelectors(permSelector string, permSelectorArgs []interface{}, leftTableCol string, rightTableCol string) (string, []interface{}) { + wheres := make([]string, 0, folder.MaxNestedFolderDepth+1) + args := make([]interface{}, 0, len(permSelectorArgs)*(folder.MaxNestedFolderDepth+1)) + + joins := make([]string, 0, folder.MaxNestedFolderDepth+2) + + tmpl := "INNER JOIN folder %s ON %s.%s = %s.uid AND %s.org_id = %s.org_id " + + prev := "d" + onCol := "uid" + for i := 1; i <= folder.MaxNestedFolderDepth+2; i++ { + t := fmt.Sprintf("f%d", i) + s := fmt.Sprintf(tmpl, t, prev, onCol, t, prev, t) + joins = append(joins, s) + + wheres = append(wheres, fmt.Sprintf("(dashboard.%s IN (SELECT d.%s FROM dashboard d %s WHERE %s.uid IN %s)", leftTableCol, rightTableCol, strings.Join(joins, " "), t, permSelector)) + args = append(args, permSelectorArgs...) + + prev = t + onCol = "parent_uid" + } + + return strings.Join(wheres, ") OR "), args +} diff --git a/pkg/services/sqlstore/permissions/dashboard_test.go b/pkg/services/sqlstore/permissions/dashboard_test.go index d9552da351c..071e6ace713 100644 --- a/pkg/services/sqlstore/permissions/dashboard_test.go +++ b/pkg/services/sqlstore/permissions/dashboard_test.go @@ -9,14 +9,24 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/db" + "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/accesscontrol" + "github.com/grafana/grafana/pkg/services/accesscontrol/mock" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/dashboards/database" + "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/folder" + "github.com/grafana/grafana/pkg/services/folder/folderimpl" + "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/org" + "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/permissions" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" ) @@ -129,13 +139,18 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) { for _, tt := range tests { t.Run(tt.desc, func(t *testing.T) { store := setupTest(t, 10, 100, tt.permissions) + recursiveQueriesAreSupported, err := store.RecursiveQueriesAreSupported() + require.NoError(t, err) + usr := &user.SignedInUser{OrgID: 1, OrgRole: org.RoleViewer, Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.permissions)}} - filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tt.permission, tt.queryType) + filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tt.permission, tt.queryType, featuremgmt.WithFeatures(), recursiveQueriesAreSupported) var result int - err := store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + err = store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { q, params := filter.Where() - _, err := sess.SQL("SELECT COUNT(*) FROM dashboard WHERE "+q, params...).Get(&result) + recQry, recQryParams := filter.With() + params = append(recQryParams, params...) + _, err := sess.SQL(recQry+"\nSELECT COUNT(*) FROM dashboard WHERE "+q, params...).Get(&result) return err }) require.NoError(t, err) @@ -145,7 +160,115 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) { } } +func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) { + testCases := []struct { + desc string + queryType string + permission dashboards.PermissionType + permissions []accesscontrol.Permission + expectedResult []string + features featuremgmt.FeatureToggles + }{ + { + desc: "Should be able to view dashboards under inherited folders if nested folders are enabled", + queryType: searchstore.TypeDashboard, + permission: dashboards.PERMISSION_VIEW, + permissions: []accesscontrol.Permission{ + {Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"}, + }, + features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders), + expectedResult: []string{"dashboard under parent folder", "dashboard under subfolder"}, + }, + { + desc: "Should not be able to view dashboards under inherited folders if nested folders are not enabled", + queryType: searchstore.TypeDashboard, + permission: dashboards.PERMISSION_VIEW, + permissions: []accesscontrol.Permission{ + {Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"}, + }, + features: featuremgmt.WithFeatures(), + expectedResult: []string{"dashboard under parent folder"}, + }, + { + desc: "Should be able to view inherited folders if nested folders are enabled", + queryType: searchstore.TypeFolder, + permission: dashboards.PERMISSION_VIEW, + permissions: []accesscontrol.Permission{ + {Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"}, + }, + features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders), + expectedResult: []string{"parent", "subfolder"}, + }, + { + desc: "Should not be able to view inherited folders if nested folders are not enabled", + queryType: searchstore.TypeFolder, + permission: dashboards.PERMISSION_VIEW, + permissions: []accesscontrol.Permission{ + {Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"}, + }, + features: featuremgmt.WithFeatures(), + expectedResult: []string{"parent"}, + }, + { + desc: "Should be able to view inherited dashboards and folders if nested folders are enabled", + permission: dashboards.PERMISSION_VIEW, + permissions: []accesscontrol.Permission{ + {Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"}, + {Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"}, + }, + features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders), + expectedResult: []string{"parent", "subfolder", "dashboard under parent folder", "dashboard under subfolder"}, + }, + { + desc: "Should not be able to view inherited dashboards and folders if nested folders are not enabled", + permission: dashboards.PERMISSION_VIEW, + permissions: []accesscontrol.Permission{ + {Action: dashboards.ActionFoldersRead, Scope: "folders:uid:parent"}, + {Action: dashboards.ActionDashboardsRead, Scope: "folders:uid:parent"}, + }, + features: featuremgmt.WithFeatures(), + expectedResult: []string{"parent", "dashboard under parent folder"}, + }, + } + + origNewGuardian := guardian.New + guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true, CanSaveValue: true}) + t.Cleanup(func() { + guardian.New = origNewGuardian + }) + + var orgID int64 = 1 + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + tc.permissions = append(tc.permissions, accesscontrol.Permission{ + Action: dashboards.ActionFoldersCreate, + }, accesscontrol.Permission{ + Action: dashboards.ActionFoldersWrite, + Scope: dashboards.ScopeFoldersAll, + }) + usr := &user.SignedInUser{OrgID: orgID, OrgRole: org.RoleViewer, Permissions: map[int64]map[string][]string{orgID: accesscontrol.GroupScopesByAction(tc.permissions)}} + db := setupNestedTest(t, usr, tc.permissions, orgID, tc.features) + recursiveQueriesAreSupported, err := db.RecursiveQueriesAreSupported() + require.NoError(t, err) + filter := permissions.NewAccessControlDashboardPermissionFilter(usr, tc.permission, tc.queryType, tc.features, recursiveQueriesAreSupported) + var result []string + err = db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + q, params := filter.Where() + recQry, recQryParams := filter.With() + params = append(recQryParams, params...) + err := sess.SQL(recQry+"\nSELECT title FROM dashboard WHERE "+q, params...).Find(&result) + return err + }) + require.NoError(t, err) + assert.Equal(t, tc.expectedResult, result) + }) + } +} + func setupTest(t *testing.T, numFolders, numDashboards int, permissions []accesscontrol.Permission) db.DB { + t.Helper() + store := db.InitTestDB(t) err := store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { dashes := make([]dashboards.Dashboard, 0, numFolders+numDashboards) @@ -227,3 +350,95 @@ func setupTest(t *testing.T, numFolders, numDashboards int, permissions []access require.NoError(t, err) return store } + +func setupNestedTest(t *testing.T, usr *user.SignedInUser, perms []accesscontrol.Permission, orgID int64, features featuremgmt.FeatureToggles) db.DB { + t.Helper() + + db := sqlstore.InitTestDB(t) + + // dashboard store commands that should be called. + dashStore, err := database.ProvideDashboardStore(db, db.Cfg, features, tagimpl.ProvideService(db, db.Cfg), quotatest.New(false, nil)) + require.NoError(t, err) + + folderSvc := folderimpl.ProvideService(mock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), db.Cfg, dashStore, folderimpl.ProvideDashboardFolderStore(db), db, features) + + // create parent folder + parent, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{ + UID: "parent", + OrgID: orgID, + Title: "parent", + SignedInUser: usr, + }) + require.NoError(t, err) + + // create subfolder + subfolder, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{ + UID: "subfolder", + ParentUID: "parent", + OrgID: orgID, + Title: "subfolder", + SignedInUser: usr, + }) + require.NoError(t, err) + + // create dashboard under parent folder + _, err = dashStore.SaveDashboard(context.Background(), dashboards.SaveDashboardCommand{ + OrgID: orgID, + FolderID: parent.ID, + Dashboard: simplejson.NewFromAny(map[string]interface{}{ + "title": "dashboard under parent folder", + }), + }) + require.NoError(t, err) + + // create dashboard under subfolder + _, err = dashStore.SaveDashboard(context.Background(), dashboards.SaveDashboardCommand{ + OrgID: orgID, + FolderID: subfolder.ID, + Dashboard: simplejson.NewFromAny(map[string]interface{}{ + "title": "dashboard under subfolder", + }), + }) + require.NoError(t, err) + + err = db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + role := &accesscontrol.Role{ + OrgID: 0, + UID: "basic_viewer", + Name: "basic:viewer", + Updated: time.Now(), + Created: time.Now(), + } + _, err = sess.Insert(role) + if err != nil { + return err + } + _, err = sess.Insert(accesscontrol.BuiltinRole{ + OrgID: 0, + RoleID: role.ID, + Role: "Viewer", + Created: time.Now(), + Updated: time.Now(), + }) + if err != nil { + return err + } + + for i := range perms { + perms[i].RoleID = role.ID + perms[i].Created = time.Now() + perms[i].Updated = time.Now() + } + if len(perms) > 0 { + _, err = sess.InsertMulti(&perms) + if err != nil { + return err + } + } + + return nil + }) + require.NoError(t, err) + + return db +} diff --git a/pkg/services/sqlstore/permissions/dashboards_bench_test.go b/pkg/services/sqlstore/permissions/dashboards_bench_test.go index d213fee5ac8..84e8cb94718 100644 --- a/pkg/services/sqlstore/permissions/dashboards_bench_test.go +++ b/pkg/services/sqlstore/permissions/dashboards_bench_test.go @@ -10,26 +10,59 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/db" + "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/accesscontrol" + "github.com/grafana/grafana/pkg/services/accesscontrol/mock" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/dashboards/database" + "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/folder" + "github.com/grafana/grafana/pkg/services/folder/folderimpl" + "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/org" + "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/permissions" + "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" ) -func benchmarkDashboardPermissionFilter(b *testing.B, numUsers, numDashboards int) { - store := setupBenchMark(b, numUsers, numDashboards) +func benchmarkDashboardPermissionFilter(b *testing.B, numUsers, numDashboards, numFolders, nestingLevel int) { + usr := user.SignedInUser{UserID: 1, OrgID: 1, OrgRole: org.RoleViewer, Permissions: map[int64]map[string][]string{ + 1: accesscontrol.GroupScopesByAction([]accesscontrol.Permission{ + { + Action: dashboards.ActionFoldersCreate, + }, + { + Action: dashboards.ActionFoldersWrite, + Scope: dashboards.ScopeFoldersAll, + }, + }), + }} + + features := featuremgmt.WithFeatures() + // if nestingLevel > 0 enable nested folders + if nestingLevel > 0 { + features = featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders) + } + + store := setupBenchMark(b, usr, features, numUsers, numDashboards, numFolders, nestingLevel) + + recursiveQueriesAreSupported, err := store.RecursiveQueriesAreSupported() + require.NoError(b, err) + b.ResetTimer() for i := 0; i < b.N; i++ { - usr := &user.SignedInUser{UserID: 1, OrgID: 1, OrgRole: org.RoleViewer, Permissions: map[int64]map[string][]string{1: {}}} - filter := permissions.NewAccessControlDashboardPermissionFilter(usr, dashboards.PERMISSION_VIEW, "") + filter := permissions.NewAccessControlDashboardPermissionFilter(&usr, dashboards.PERMISSION_VIEW, "", features, recursiveQueriesAreSupported) var result int err := store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { q, params := filter.Where() - _, err := sess.SQL("SELECT COUNT(*) FROM dashboard WHERE "+q, params...).Get(&result) + recQry, recQryParams := filter.With() + params = append(recQryParams, params...) + _, err := sess.SQL(recQry+"SELECT COUNT(*) FROM dashboard WHERE "+q, params...).Get(&result) return err }) require.NoError(b, err) @@ -37,15 +70,78 @@ func benchmarkDashboardPermissionFilter(b *testing.B, numUsers, numDashboards in } } -func setupBenchMark(b *testing.B, numUsers, numDashboards int) db.DB { +func setupBenchMark(b *testing.B, usr user.SignedInUser, features featuremgmt.FeatureToggles, numUsers, numDashboards, numFolders, nestingLevel int) db.DB { + if nestingLevel > folder.MaxNestedFolderDepth { + nestingLevel = folder.MaxNestedFolderDepth + } + store := db.InitTestDB(b) - now := time.Now() - err := store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { - dashes := make([]dashboards.Dashboard, 0, numDashboards) - for i := 1; i <= numDashboards; i++ { + + quotaService := quotatest.New(false, nil) + + dashboardWriteStore, err := database.ProvideDashboardStore(store, store.Cfg, features, tagimpl.ProvideService(store, store.Cfg), quotaService) + require.NoError(b, err) + + folderSvc := folderimpl.ProvideService(mock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), store.Cfg, dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(store), store, features) + + origNewGuardian := guardian.New + guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true, CanSaveValue: true}) + b.Cleanup(func() { + guardian.New = origNewGuardian + }) + + rootFolders := make([]*folder.Folder, 0, numFolders) + dashes := make([]dashboards.Dashboard, 0, numDashboards) + parentUID := "" + for i := 0; i < numFolders; i++ { + uid := fmt.Sprintf("f%d", i) + f, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{ + UID: uid, + OrgID: usr.OrgID, + Title: uid, + SignedInUser: &usr, + ParentUID: parentUID, + }) + require.NoError(b, err) + rootFolders = append(rootFolders, f) + + parentUID := f.UID + var leaf *folder.Folder + for j := 1; j <= nestingLevel; j++ { + uid := fmt.Sprintf("f%d_%d", i, j) + sf, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{ + UID: uid, + OrgID: usr.OrgID, + Title: uid, + SignedInUser: &usr, + ParentUID: parentUID, + }) + require.NoError(b, err) + parentUID = sf.UID + leaf = sf + } + + str := fmt.Sprintf("dashboard under folder %s", leaf.Title) + now := time.Now() + dashes = append(dashes, dashboards.Dashboard{ + OrgID: usr.OrgID, + IsFolder: false, + UID: str, + Slug: str, + Title: str, + Data: simplejson.New(), + Created: now, + Updated: now, + FolderID: leaf.ID, + }) + } + + err = store.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + now := time.Now() + for i := len(dashes); i < numDashboards; i++ { str := strconv.Itoa(i) dashes = append(dashes, dashboards.Dashboard{ - OrgID: 1, + OrgID: usr.OrgID, IsFolder: false, UID: str, Slug: str, @@ -79,10 +175,24 @@ func setupBenchMark(b *testing.B, numUsers, numDashboards int) db.DB { Created: now, }) for _, dash := range dashes { + // add permission to read dashboards under the general + if dash.FolderID == 0 { + permissions = append(permissions, accesscontrol.Permission{ + RoleID: int64(i), + Action: dashboards.ActionDashboardsRead, + Scope: dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dash.UID), + Updated: now, + Created: now, + }) + } + } + + for _, f := range rootFolders { + // add permission to read folders under specific folders permissions = append(permissions, accesscontrol.Permission{ RoleID: int64(i), Action: dashboards.ActionDashboardsRead, - Scope: dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dash.UID), + Scope: dashboards.ScopeFoldersProvider.GetResourceScopeUID(f.UID), Updated: now, Created: now, }) @@ -113,16 +223,52 @@ func setupBenchMark(b *testing.B, numUsers, numDashboards int) db.DB { return store } -func BenchmarkDashboardPermissionFilter_100_100(b *testing.B) { - benchmarkDashboardPermissionFilter(b, 100, 100) +func BenchmarkDashboardPermissionFilter_100_100_0_0(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 100, 100, 0, 0) } -func BenchmarkDashboardPermissionFilter_100_1000(b *testing.B) { - benchmarkDashboardPermissionFilter(b, 100, 1000) +func BenchmarkDashboardPermissionFilter_100_100_10_2(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 100, 100, 10, 2) } -func BenchmarkDashboardPermissionFilter_300_10000(b *testing.B) { - benchmarkDashboardPermissionFilter(b, 300, 10000) +func BenchmarkDashboardPermissionFilter_100_100_10_4(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 100, 100, 10, 4) +} + +func BenchmarkDashboardPermissionFilter_100_100_10_8(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 100, 100, 10, 8) +} + +func BenchmarkDashboardPermissionFilter_100_1000_0_0(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 100, 1000, 0, 0) +} + +func BenchmarkDashboardPermissionFilter_100_1000_10_2(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 100, 1000, 10, 2) +} + +func BenchmarkDashboardPermissionFilter_100_1000_10_4(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 100, 1000, 10, 4) +} + +func BenchmarkDashboardPermissionFilter_100_1000_10_8(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 100, 1000, 10, 8) +} + +func BenchmarkDashboardPermissionFilter_300_10000_0_0(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 300, 10000, 0, 0) +} + +func BenchmarkDashboardPermissionFilter_300_10000_10_2(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 300, 10000, 10, 2) +} + +func BenchmarkDashboardPermissionFilter_300_10000_10_4(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 300, 10000, 10, 4) +} + +func BenchmarkDashboardPermissionFilter_300_10000_10_8(b *testing.B) { + benchmarkDashboardPermissionFilter(b, 300, 10000, 10, 8) } func batch(count, batchSize int, eachFn func(start, end int) error) error { diff --git a/pkg/services/sqlstore/searchstore/builder.go b/pkg/services/sqlstore/searchstore/builder.go index 1ae89d05de9..3fb805262e4 100644 --- a/pkg/services/sqlstore/searchstore/builder.go +++ b/pkg/services/sqlstore/searchstore/builder.go @@ -44,6 +44,9 @@ func (b *Builder) ToSQL(limit, page int64) (string, []interface{}) { } func (b *Builder) buildSelect() { + var recQuery string + var recQueryParams []interface{} + b.sql.WriteString( `SELECT dashboard.id, @@ -61,9 +64,25 @@ func (b *Builder) buildSelect() { if f, ok := f.(FilterSelect); ok { b.sql.WriteString(fmt.Sprintf(", %s", f.Select())) } + + if f, ok := f.(FilterWith); ok { + recQuery, recQueryParams = f.With() + } } b.sql.WriteString(` FROM `) + + if recQuery == "" { + return + } + + // prepend recursive queries + var bf bytes.Buffer + bf.WriteString(recQuery) + bf.WriteString(b.sql.String()) + + b.sql = bf + b.params = append(recQueryParams, b.params...) } func (b *Builder) applyFilters() (ordering string) { diff --git a/pkg/services/sqlstore/searchstore/filters.go b/pkg/services/sqlstore/searchstore/filters.go index f5cc63e421a..170d6a2cf4d 100644 --- a/pkg/services/sqlstore/searchstore/filters.go +++ b/pkg/services/sqlstore/searchstore/filters.go @@ -14,6 +14,12 @@ type FilterWhere interface { Where() (string, []interface{}) } +// FilterWith returns any recursive CTE queries (if supported) +// and their parameters +type FilterWith interface { + With() (string, []interface{}) +} + // FilterGroupBy should be used after performing an outer join on the // search result to ensure there is only one of each ID in the results. // The id column must be present in the result. diff --git a/pkg/services/sqlstore/searchstore/search_test.go b/pkg/services/sqlstore/searchstore/search_test.go index 9d0945aac3d..b092579ab17 100644 --- a/pkg/services/sqlstore/searchstore/search_test.go +++ b/pkg/services/sqlstore/searchstore/search_test.go @@ -10,7 +10,9 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/db" + "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/sqlstore/permissions" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" @@ -148,6 +150,145 @@ func TestBuilder_Permissions(t *testing.T) { assert.Len(t, res, 0) } +func TestBuilder_RBAC(t *testing.T) { + testsCases := []struct { + desc string + userPermissions []accesscontrol.Permission + features featuremgmt.FeatureToggles + expectedParams []interface{} + }{ + { + desc: "no user permissions", + features: featuremgmt.WithFeatures(), + expectedParams: []interface{}{ + int64(1), + }, + }, + { + desc: "user with view permission", + userPermissions: []accesscontrol.Permission{ + {Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"}, + }, + features: featuremgmt.WithFeatures(), + expectedParams: []interface{}{ + int64(1), + int64(1), + int64(1), + 0, + "Viewer", + int64(1), + 0, + "dashboards:read", + "dashboards:write", + 2, + int64(1), + int64(1), + 0, + "Viewer", + int64(1), + 0, + "dashboards:read", + "dashboards:write", + 2, + int64(1), + int64(1), + 0, + "Viewer", + int64(1), + 0, + "folders:read", + "dashboards:create", + 2, + }, + }, + { + desc: "user with view permission with nesting", + userPermissions: []accesscontrol.Permission{ + {Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"}, + }, + features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders), + expectedParams: []interface{}{ + int64(1), + int64(1), + 0, + "Viewer", + int64(1), + 0, + "dashboards:read", + "dashboards:write", + 2, + int64(1), + int64(1), + 0, + "Viewer", + int64(1), + 0, + "folders:read", + "dashboards:create", + 2, + int64(1), + int64(1), + int64(1), + 0, + "Viewer", + int64(1), + 0, + "dashboards:read", + "dashboards:write", + 2, + }, + }, + } + + user := &user.SignedInUser{ + UserID: 1, + OrgID: 1, + OrgRole: org.RoleViewer, + } + + store := setupTestEnvironment(t) + createDashboards(t, store, 0, 1, user.OrgID) + + recursiveQueriesAreSupported, err := store.RecursiveQueriesAreSupported() + require.NoError(t, err) + + for _, tc := range testsCases { + t.Run(tc.desc, func(t *testing.T) { + if len(tc.userPermissions) > 0 { + user.Permissions = map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tc.userPermissions)} + } + + level := dashboards.PERMISSION_EDIT + + builder := &searchstore.Builder{ + Filters: []interface{}{ + searchstore.OrgFilter{OrgId: user.OrgID}, + searchstore.TitleSorter{}, + permissions.NewAccessControlDashboardPermissionFilter( + user, + level, + "", + tc.features, + recursiveQueriesAreSupported, + ), + }, + Dialect: store.GetDialect(), + } + + res := []dashboards.DashboardSearchProjection{} + err := store.WithDbSession(context.Background(), func(sess *db.Session) error { + sql, params := builder.ToSQL(limit, page) + // TODO: replace with a proper test + assert.Equal(t, tc.expectedParams, params) + return sess.SQL(sql, params...).Find(&res) + }) + require.NoError(t, err) + + assert.Len(t, res, 0) + }) + } +} + func setupTestEnvironment(t *testing.T) db.DB { t.Helper() store := db.InitTestDB(t) diff --git a/pkg/services/sqlstore/user.go b/pkg/services/sqlstore/user.go index d197040a1d9..19bcc640cd5 100644 --- a/pkg/services/sqlstore/user.go +++ b/pkg/services/sqlstore/user.go @@ -146,6 +146,9 @@ func verifyExistingOrg(sess *DBSession, orgId int64) error { func (ss *SQLStore) getOrCreateOrg(sess *DBSession, orgName string) (int64, error) { var org org.Org + org.Created = time.Now() + org.Updated = org.Created + if ss.Cfg.AutoAssignOrg { has, err := sess.Where("id=?", ss.Cfg.AutoAssignOrgId).Get(&org) if err != nil { @@ -164,18 +167,11 @@ func (ss *SQLStore) getOrCreateOrg(sess *DBSession, orgName string) (int64, erro org.Name = mainOrgName org.ID = int64(ss.Cfg.AutoAssignOrgId) - } else { - org.Name = orgName - } - - org.Created = time.Now() - org.Updated = time.Now() - - if org.ID != 0 { if err := sess.InsertId(&org, ss.Dialect); err != nil { return 0, err } } else { + org.Name = orgName if _, err := sess.InsertOne(&org); err != nil { return 0, err } diff --git a/pkg/tsdb/cloudwatch/constants/metrics.go b/pkg/tsdb/cloudwatch/constants/metrics.go index 0b6f4fbd9ae..e0d29a1f602 100644 --- a/pkg/tsdb/cloudwatch/constants/metrics.go +++ b/pkg/tsdb/cloudwatch/constants/metrics.go @@ -340,7 +340,7 @@ var NamespaceMetricsMap = map[string][]string{ "AWS/Glue": {"glue.driver.BlockManager.disk.diskSpaceUsed_MB", "glue.driver.ExecutorAllocationManager.executors.numberAllExecutors", "glue.driver.ExecutorAllocationManager.executors.numberMaxNeededExecutors", "glue.driver.aggregate.bytesRead", "glue.driver.aggregate.elapsedTime", "glue.driver.aggregate.numCompletedStages", "glue.driver.aggregate.numCompletedTasks", "glue.driver.aggregate.numFailedTasks", "glue.driver.aggregate.numKilledTasks", "glue.driver.aggregate.recordsRead", "glue.driver.aggregate.shuffleBytesWritten", "glue.driver.aggregate.shuffleLocalBytesRead", "glue.driver.jvm.heap.usage glue.executorId.jvm.heap.usage glue.ALL.jvm.heap.usage", "glue.driver.jvm.heap.used glue.executorId.jvm.heap.used glue.ALL.jvm.heap.used", "glue.driver.s3.filesystem.read_bytes glue.executorId.s3.filesystem.read_bytes glue.ALL.s3.filesystem.read_bytes", "glue.driver.s3.filesystem.write_bytes glue.executorId.s3.filesystem.write_bytes glue.ALL.s3.filesystem.write_bytes", "glue.driver.system.cpuSystemLoad glue.executorId.system.cpuSystemLoad glue.ALL.system.cpuSystemLoad"}, "AWS/GroundStation": {"BitErrorRate", "BlockErrorRate", "ReceivedPower", "Es/N0"}, "AWS/Inspector": {"TotalAssessmentRunFindings", "TotalAssessmentRuns", "TotalHealthyAgents", "TotalMatchingAgents"}, - "AWS/IVS": {"ConcurrentViews", "ConcurrentStreams", "LiveDeliveredTime", "LiveInputTime", "RecordedTime"}, + "AWS/IVS": {"ConcurrentViews", "ConcurrentStreams", "IngestAudioBitrate", "IngestFramerate", "IngestVideoBitrate", "KeyframeInterval", "LiveDeliveredTime", "LiveInputTime", "RecordedTime"}, "AWS/IoT": {"CanceledJobExecutionCount", "CanceledJobExecutionTotalCount", "ClientError", "Connect.AuthError", "Connect.ClientError", "Connect.ServerError", "Connect.Success", "Connect.Throttle", "DeleteThingShadow.Accepted", "FailedJobExecutionCount", "FailedJobExecutionTotalCount", "Failure", "GetThingShadow.Accepted", "InProgressJobExecutionCount", "InProgressJobExecutionTotalCount", "NonCompliantResources", "NumLogBatchesFailedToPublishThrottled", "NumLogEventsFailedToPublishThrottled", "ParseError", "Ping.Success", "PublishIn.AuthError", "PublishIn.ClientError", "PublishIn.ServerError", "PublishIn.Success", "PublishIn.Throttle", "PublishOut.AuthError", "PublishOut.ClientError", "PublishOut.Success", "QueuedJobExecutionCount", "QueuedJobExecutionTotalCount", "RejectedJobExecutionCount", "RejectedJobExecutionTotalCount", "RemovedJobExecutionCount", "RemovedJobExecutionTotalCount", "ResourcesEvaluated", "RuleMessageThrottled", "RuleNotFound", "RulesExecuted", "ServerError", "Subscribe.AuthError", "Subscribe.ClientError", "Subscribe.ServerError", "Subscribe.Success", "Subscribe.Throttle", "SuccededJobExecutionCount", "SuccededJobExecutionTotalCount", "Success", "TopicMatch", "Unsubscribe.ClientError", "Unsubscribe.ServerError", "Unsubscribe.Success", "Unsubscribe.Throttle", "UpdateThingShadow.Accepted", "Violations", "ViolationsCleared", "ViolationsInvalidated"}, "AWS/IoTAnalytics": {"ActionExecution", "ActivityExecutionError", "IncomingMessages"}, "AWS/IoTSiteWise": {"Gateway.Heartbeat", "Gateway.PublishSuccessCount", "Gateway.PublishFailureCount", "Gateway.ProcessFailureCount", "OPCUACollector.Heartbeat", "OPCUACollector.ActiveDataStreamCount", "OPCUACollector.IncomingValuesCount"}, diff --git a/pkg/tsdb/elasticsearch/client/search_request.go b/pkg/tsdb/elasticsearch/client/search_request.go index dd7f8642d37..d267210f103 100644 --- a/pkg/tsdb/elasticsearch/client/search_request.go +++ b/pkg/tsdb/elasticsearch/client/search_request.go @@ -73,10 +73,21 @@ func (b *SearchRequestBuilder) Size(size int) *SearchRequestBuilder { return b } -// SortDesc adds a sort to the search request -func (b *SearchRequestBuilder) SortDesc(field, unmappedType string) *SearchRequestBuilder { +type SortOrder string + +const ( + SortOrderAsc SortOrder = "asc" + SortOrderDesc SortOrder = "desc" +) + +// Sort adds a "asc" | "desc" sort to the search request +func (b *SearchRequestBuilder) Sort(order SortOrder, field string, unmappedType string) *SearchRequestBuilder { + if order != SortOrderAsc && order != SortOrderDesc { + return b + } + props := map[string]string{ - "order": "desc", + "order": string(order), } if unmappedType != "" { @@ -110,6 +121,16 @@ func (b *SearchRequestBuilder) AddHighlight() *SearchRequestBuilder { return b } +func (b *SearchRequestBuilder) AddSearchAfter(value interface{}) *SearchRequestBuilder { + if b.customProps["search_after"] == nil { + b.customProps["search_after"] = []interface{}{value} + } else { + b.customProps["search_after"] = append(b.customProps["search_after"].([]interface{}), value) + } + + return b +} + // Query creates and return a query builder func (b *SearchRequestBuilder) Query() *QueryBuilder { if b.queryBuilder == nil { diff --git a/pkg/tsdb/elasticsearch/client/search_request_test.go b/pkg/tsdb/elasticsearch/client/search_request_test.go index f3f1601c9a1..f89b4ccd0ed 100644 --- a/pkg/tsdb/elasticsearch/client/search_request_test.go +++ b/pkg/tsdb/elasticsearch/client/search_request_test.go @@ -45,7 +45,7 @@ func TestSearchRequest(t *testing.T) { t.Run("When adding size, sort, filters", func(t *testing.T) { b := setup() b.Size(200) - b.SortDesc(timeField, "boolean") + b.Sort(SortOrderDesc, timeField, "boolean") filters := b.Query().Bool().Filter() filters.AddDateRangeFilter(timeField, 10, 5, DateFormatEpochMS) filters.AddQueryStringFilter("test", true) diff --git a/pkg/tsdb/elasticsearch/data_query.go b/pkg/tsdb/elasticsearch/data_query.go index 0d4653ab80a..f725ce441b6 100644 --- a/pkg/tsdb/elasticsearch/data_query.go +++ b/pkg/tsdb/elasticsearch/data_query.go @@ -317,12 +317,24 @@ func isRawDocumentQuery(query *Query) bool { func processLogsQuery(q *Query, b *es.SearchRequestBuilder, from, to int64, defaultTimeField string) { metric := q.Metrics[0] - b.SortDesc(defaultTimeField, "boolean") - b.SortDesc("_doc", "") + sort := es.SortOrderDesc + if metric.Settings.Get("sortDirection").MustString() == "asc" { + // This is currently used only for log context query + sort = es.SortOrderAsc + } + b.Sort(sort, defaultTimeField, "boolean") + b.Sort(sort, "_doc", "") b.AddDocValueField(defaultTimeField) b.Size(stringToIntWithDefaultValue(metric.Settings.Get("limit").MustString(), defaultSize)) b.AddHighlight() + // This is currently used only for log context query to get + // log lines before and after the selected log line + searchAfter := metric.Settings.Get("searchAfter").MustArray() + for _, value := range searchAfter { + b.AddSearchAfter(value) + } + // For log query, we add a date histogram aggregation aggBuilder := b.Agg() q.BucketAggs = append(q.BucketAggs, &BucketAgg{ @@ -342,8 +354,8 @@ func processLogsQuery(q *Query, b *es.SearchRequestBuilder, from, to int64, defa func processDocumentQuery(q *Query, b *es.SearchRequestBuilder, from, to int64, defaultTimeField string) { metric := q.Metrics[0] - b.SortDesc(defaultTimeField, "boolean") - b.SortDesc("_doc", "") + b.Sort(es.SortOrderDesc, defaultTimeField, "boolean") + b.Sort(es.SortOrderDesc, "_doc", "") b.AddDocValueField(defaultTimeField) b.Size(stringToIntWithDefaultValue(metric.Settings.Get("size").MustString(), defaultSize)) } diff --git a/pkg/tsdb/elasticsearch/data_query_test.go b/pkg/tsdb/elasticsearch/data_query_test.go index 478ae5feab2..f43f05d8430 100644 --- a/pkg/tsdb/elasticsearch/data_query_test.go +++ b/pkg/tsdb/elasticsearch/data_query_test.go @@ -1354,6 +1354,25 @@ func TestExecuteElasticsearchDataQuery(t *testing.T) { }) }) + t.Run("With log context query with sortDirection and searchAfter should return correct query", func(t *testing.T) { + c := newFakeClient() + _, err := executeElasticsearchDataQuery(c, `{ + "metrics": [{ "type": "logs", "id": "1", "settings": { "limit": "1000", "sortDirection": "asc", "searchAfter": [1, "2"] }}] + }`, from, to) + require.NoError(t, err) + sr := c.multisearchRequests[0].Requests[0] + require.Equal(t, sr.Sort["@timestamp"], map[string]string{"order": "asc", "unmapped_type": "boolean"}) + require.Equal(t, sr.Sort["_doc"], map[string]string{"order": "asc"}) + + searchAfter := sr.CustomProps["search_after"].([]interface{}) + firstSearchAfter, err := searchAfter[0].(json.Number).Int64() + require.NoError(t, err) + require.Equal(t, firstSearchAfter, int64(1)) + secondSearchAfter := searchAfter[1].(string) + require.NoError(t, err) + require.Equal(t, secondSearchAfter, "2") + }) + t.Run("With invalid query should return error", (func(t *testing.T) { c := newFakeClient() _, err := executeElasticsearchDataQuery(c, `{ diff --git a/pkg/tsdb/influxdb/flux/testdata/grouping.golden.jsonc b/pkg/tsdb/influxdb/flux/testdata/grouping.golden.jsonc index 1a6da1a668a..e69529d5b16 100644 --- a/pkg/tsdb/influxdb/flux/testdata/grouping.golden.jsonc +++ b/pkg/tsdb/influxdb/flux/testdata/grouping.golden.jsonc @@ -104,6 +104,14 @@ 3.56, null ] + ], + "nanos": [ + [ + 0, + 0, + 881833 + ], + null ] } }, @@ -146,6 +154,15 @@ 1.74, null ] + ], + "nanos": [ + [ + 0, + 0, + 0, + 881833 + ], + null ] } }, @@ -200,6 +217,21 @@ 1.71, null ] + ], + "nanos": [ + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 881833 + ], + null ] } } diff --git a/pkg/tsdb/influxdb/flux/testdata/multiple.golden.jsonc b/pkg/tsdb/influxdb/flux/testdata/multiple.golden.jsonc index ac09d56e348..444c50c4c9d 100644 --- a/pkg/tsdb/influxdb/flux/testdata/multiple.golden.jsonc +++ b/pkg/tsdb/influxdb/flux/testdata/multiple.golden.jsonc @@ -92,6 +92,13 @@ 1.4, 6.6 ] + ], + "nanos": [ + [ + 814545, + 214724 + ], + null ] } }, @@ -131,6 +138,13 @@ 4, -1 ] + ], + "nanos": [ + [ + 814545, + 214724 + ], + null ] } }, @@ -170,6 +184,13 @@ 0, 2 ] + ], + "nanos": [ + [ + 978640, + 100374 + ], + null ] } } diff --git a/pkg/tsdb/influxdb/flux/testdata/non_standard_time_column.golden.jsonc b/pkg/tsdb/influxdb/flux/testdata/non_standard_time_column.golden.jsonc index 0680c4f629e..b62a1c33f9f 100644 --- a/pkg/tsdb/influxdb/flux/testdata/non_standard_time_column.golden.jsonc +++ b/pkg/tsdb/influxdb/flux/testdata/non_standard_time_column.golden.jsonc @@ -76,6 +76,15 @@ [ 156.304 ] + ], + "nanos": [ + [ + 584046 + ], + [ + 584046 + ], + null ] } } diff --git a/pkg/tsdb/influxdb/flux/testdata/simple.golden.jsonc b/pkg/tsdb/influxdb/flux/testdata/simple.golden.jsonc index a5dd5329b50..8bf18138289 100644 --- a/pkg/tsdb/influxdb/flux/testdata/simple.golden.jsonc +++ b/pkg/tsdb/influxdb/flux/testdata/simple.golden.jsonc @@ -64,6 +64,13 @@ 1.4, 6.6 ] + ], + "nanos": [ + [ + 814545, + 214724 + ], + null ] } } diff --git a/pkg/tsdb/influxdb/flux/testdata/table.golden.jsonc b/pkg/tsdb/influxdb/flux/testdata/table.golden.jsonc index 144491e159f..786dbb1decb 100644 --- a/pkg/tsdb/influxdb/flux/testdata/table.golden.jsonc +++ b/pkg/tsdb/influxdb/flux/testdata/table.golden.jsonc @@ -59,6 +59,12 @@ [ 42 ] + ], + "nanos": [ + [ + 905100 + ], + null ] } } diff --git a/pkg/tsdb/loki/testdata/streams_simple.golden.jsonc b/pkg/tsdb/loki/testdata/streams_simple.golden.jsonc index 2bd8cc42b5c..1d83e77e033 100644 --- a/pkg/tsdb/loki/testdata/streams_simple.golden.jsonc +++ b/pkg/tsdb/loki/testdata/streams_simple.golden.jsonc @@ -356,6 +356,20 @@ "1645030245539423744_fd17f65c_sq", "1645030244091700992_62ae07f3_sq" ] + ], + "nanos": [ + null, + [ + 757120, + 735040, + 587968, + 587968, + 423744, + 700992 + ], + null, + null, + null ] } } diff --git a/plugins-bundled/internal/input-datasource/package.json b/plugins-bundled/internal/input-datasource/package.json index 9b41b602b40..202c3a7fa11 100644 --- a/plugins-bundled/internal/input-datasource/package.json +++ b/plugins-bundled/internal/input-datasource/package.json @@ -1,6 +1,6 @@ { "name": "@grafana-plugins/input-datasource", - "version": "9.5.0-pre", + "version": "10.0.0-pre", "description": "Input Datasource", "private": true, "repository": { @@ -15,15 +15,15 @@ }, "author": "Grafana Labs", "devDependencies": { - "@grafana/toolkit": "9.5.0-pre", + "@grafana/toolkit": "10.0.0-pre", "@types/jest": "26.0.15", "@types/lodash": "4.14.149", "@types/react": "17.0.30", "lodash": "4.17.21" }, "dependencies": { - "@grafana/data": "9.5.0-pre", - "@grafana/ui": "9.5.0-pre", + "@grafana/data": "10.0.0-pre", + "@grafana/ui": "10.0.0-pre", "jquery": "3.5.1", "react": "17.0.1", "react-dom": "17.0.1", diff --git a/public/app/core/components/AppChrome/AppChrome.tsx b/public/app/core/components/AppChrome/AppChrome.tsx index ef63d3f0fc6..548436f4101 100644 --- a/public/app/core/components/AppChrome/AppChrome.tsx +++ b/public/app/core/components/AppChrome/AppChrome.tsx @@ -104,6 +104,7 @@ const getStyles = (theme: GrafanaTheme2) => { boxShadow: shadow, background: theme.colors.background.primary, flexDirection: 'column', + borderBottom: `1px solid ${theme.colors.border.weak}`, }), }; }; diff --git a/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx b/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx index 9a13cfb57da..c322b4c3875 100644 --- a/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx +++ b/public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx @@ -19,6 +19,7 @@ export const QuickAdd = ({}: Props) => { const navBarTree = useSelector((state) => state.navBarTree); const breakpoint = theme.breakpoints.values.sm; + const [isOpen, setIsOpen] = useState(false); const [isSmallScreen, setIsSmallScreen] = useState(!window.matchMedia(`(min-width: ${breakpoint}px)`).matches); const createActions = useMemo(() => findCreateActions(navBarTree), [navBarTree]); @@ -46,14 +47,13 @@ export const QuickAdd = ({}: Props) => { return createActions.length > 0 ? ( <> - - {(isOpen) => - isSmallScreen ? ( - - ) : ( - - ) - } + + diff --git a/public/app/core/components/PageNew/Page.tsx b/public/app/core/components/PageNew/Page.tsx index 6d9fe53dce3..73a09f82603 100644 --- a/public/app/core/components/PageNew/Page.tsx +++ b/public/app/core/components/PageNew/Page.tsx @@ -131,17 +131,15 @@ const getStyles = (theme: GrafanaTheme2) => { padding: theme.spacing(2), borderRadius: theme.shape.borderRadius(1), border: `1px solid ${theme.colors.border.weak}`, + borderBottom: 'none', background: theme.colors.background.primary, display: 'flex', flexDirection: 'column', flexGrow: 1, margin: theme.spacing(0, 0, 0, 0), - [theme.breakpoints.up('sm')]: { - margin: theme.spacing(0, 1, 1, 1), - }, [theme.breakpoints.up('md')]: { - margin: theme.spacing(2, 2, 2, 1), + margin: theme.spacing(2, 2, 0, 1), padding: theme.spacing(3), }, }), diff --git a/public/app/core/components/PageNew/SectionNav.tsx b/public/app/core/components/PageNew/SectionNav.tsx index 746ac980cc1..1b46e1a86c4 100644 --- a/public/app/core/components/PageNew/SectionNav.tsx +++ b/public/app/core/components/PageNew/SectionNav.tsx @@ -100,6 +100,7 @@ const getStyles = (theme: GrafanaTheme2) => { flexDirection: 'column', padding: theme.spacing(2, 1, 2, 2), minWidth: '250px', + [theme.breakpoints.up('md')]: { padding: theme.spacing(4.5, 1, 2, 2), }, diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts index d2e9b6c42f0..16acfd7c110 100644 --- a/public/app/core/services/backend_srv.ts +++ b/public/app/core/services/backend_srv.ts @@ -50,6 +50,8 @@ export interface FolderRequestOptions { withAccessControl?: boolean; } +const GRAFANA_TRACEID_HEADER = 'grafana-trace-id'; + export class BackendSrv implements BackendService { private inFlightRequests: Subject = new Subject(); private HTTP_REQUEST_CANCELED = -1; @@ -223,6 +225,7 @@ export class BackendSrv implements BackendService { type, redirected, config: options, + traceId: response.headers.get(GRAFANA_TRACEID_HEADER) ?? undefined, }; return fetchResponse; }), @@ -238,7 +241,13 @@ export class BackendSrv implements BackendService { filter((response) => response.ok === false), mergeMap((response) => { const { status, statusText, data } = response; - const fetchErrorResponse: FetchError = { status, statusText, data, config: options }; + const fetchErrorResponse: FetchError = { + status, + statusText, + data, + config: options, + traceId: response.headers.get(GRAFANA_TRACEID_HEADER) ?? undefined, + }; return throwError(fetchErrorResponse); }), retryWhen((attempts: Observable) => diff --git a/public/app/core/specs/backend_srv.test.ts b/public/app/core/specs/backend_srv.test.ts index a0fe3067587..ffa46ae60db 100644 --- a/public/app/core/specs/backend_srv.test.ts +++ b/public/app/core/specs/backend_srv.test.ts @@ -1,5 +1,5 @@ import 'whatwg-fetch'; // fetch polyfill needed for PhantomJs rendering -import { Observable, of } from 'rxjs'; +import { Observable, of, lastValueFrom } from 'rxjs'; import { delay } from 'rxjs/operators'; import { AppEvents, DataQueryErrorType, EventBusExtended } from '@grafana/data'; @@ -21,6 +21,7 @@ const getTestContext = (overides?: object) => { redirected: false, type: 'basic', url: 'http://localhost:3000/api/some-mock', + headers: new Map(), }; const props = { ...defaults, ...overides }; const textMock = jest.fn().mockResolvedValue(JSON.stringify(props.data)); @@ -29,6 +30,7 @@ const getTestContext = (overides?: object) => { ok: props.ok, status: props.status, statusText: props.statusText, + headers: props.headers, text: textMock, redirected: false, type: 'basic', @@ -355,6 +357,63 @@ describe('backendSrv', () => { }); }); }); + + describe('traceId handling', () => { + const opts = { url: '/something', method: 'GET' }; + it('should handle a success-response without traceId', async () => { + const ctx = getTestContext({ status: 200, statusText: 'OK', headers: new Headers() }); + const res = await lastValueFrom(ctx.backendSrv.fetch(opts)); + expect(res.traceId).toBeUndefined(); + }); + + it('should handle a success-response with traceId', async () => { + const ctx = getTestContext({ + status: 200, + statusText: 'OK', + headers: new Headers({ + 'grafana-trace-id': 'traceId1', + }), + }); + const res = await lastValueFrom(ctx.backendSrv.fetch(opts)); + expect(res.traceId).toBe('traceId1'); + }); + + it('should handle an error-response without traceId', () => { + const ctx = getTestContext({ + ok: false, + status: 500, + statusText: 'INTERNAL SERVER ERROR', + headers: new Headers(), + }); + return lastValueFrom(ctx.backendSrv.fetch(opts)).then( + (data) => { + throw new Error('must not get here'); + }, + (error) => { + expect(error.traceId).toBeUndefined(); + } + ); + }); + + it('should handle an error-response with traceId', () => { + const ctx = getTestContext({ + ok: false, + status: 500, + statusText: 'INTERNAL SERVER ERROR', + headers: new Headers({ + 'grafana-trace-id': 'traceId1', + }), + }); + return lastValueFrom(ctx.backendSrv.fetch(opts)).then( + (data) => { + throw new Error('must not get here'); + }, + (error) => { + expect(error.traceId).toBe('traceId1'); + } + ); + }); + }); }); describe('datasourceRequest', () => { @@ -369,6 +428,7 @@ describe('backendSrv', () => { ok: true, status: 200, statusText: 'Ok', + headers: new Map(), text: () => Promise.resolve(JSON.stringify(slowData)), redirected: false, type: 'basic', @@ -382,6 +442,7 @@ describe('backendSrv', () => { ok: true, status: 200, statusText: 'Ok', + headers: new Map(), text: () => Promise.resolve(JSON.stringify(fastData)), redirected: false, type: 'basic', diff --git a/public/app/features/alerting/unified/api/alertmanager.ts b/public/app/features/alerting/unified/api/alertmanager.ts index 2f75264468f..ba565453d42 100644 --- a/public/app/features/alerting/unified/api/alertmanager.ts +++ b/public/app/features/alerting/unified/api/alertmanager.ts @@ -34,6 +34,8 @@ export async function fetchAlertManagerConfig(alertManagerSourceName: string): P template_files: result.data.template_files ?? {}, template_file_provenances: result.data.template_file_provenances ?? {}, alertmanager_config: result.data.alertmanager_config ?? {}, + last_applied: result.data.last_applied, + id: result.data.id, }; } catch (e) { // if no config has been uploaded to grafana, it returns error instead of latest config diff --git a/public/app/features/alerting/unified/api/alertmanagerApi.ts b/public/app/features/alerting/unified/api/alertmanagerApi.ts index be7f2634b44..66f6d760422 100644 --- a/public/app/features/alerting/unified/api/alertmanagerApi.ts +++ b/public/app/features/alerting/unified/api/alertmanagerApi.ts @@ -1,12 +1,16 @@ import { AlertmanagerChoice, + AlertManagerCortexConfig, ExternalAlertmanagerConfig, ExternalAlertmanagers, ExternalAlertmanagersResponse, } from '../../../../plugins/datasource/alertmanager/types'; +import { getDatasourceAPIUid, GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource'; import { alertingApi } from './alertingApi'; +const LIMIT_TO_SUCCESSFULLY_APPLIED_AMS = 10; + export interface AlertmanagersChoiceResponse { alertmanagersChoice: AlertmanagerChoice; numExternalAlertmanagers: number; @@ -33,5 +37,24 @@ export const alertmanagerApi = alertingApi.injectEndpoints({ query: (config) => ({ url: '/api/v1/ngalert/admin_config', method: 'POST', data: config }), invalidatesTags: ['AlertmanagerChoice'], }), + + getValidAlertManagersConfig: build.query({ + //this is only available for the "grafana" alert manager + query: () => ({ + url: `/api/alertmanager/${getDatasourceAPIUid( + GRAFANA_RULES_SOURCE_NAME + )}/config/history?limit=${LIMIT_TO_SUCCESSFULLY_APPLIED_AMS}`, + }), + }), + + resetAlertManagerConfigToOldVersion: build.mutation<{ message: string }, { id: number }>({ + //this is only available for the "grafana" alert manager + query: (config) => ({ + url: `/api/alertmanager/${getDatasourceAPIUid(GRAFANA_RULES_SOURCE_NAME)}/config/history/${ + config.id + }/_activate`, + method: 'POST', + }), + }), }), }); diff --git a/public/app/features/alerting/unified/components/admin/AlertmanagerConfig.test.tsx b/public/app/features/alerting/unified/components/admin/AlertmanagerConfig.test.tsx index a9bebf53196..5b6df00d2f9 100644 --- a/public/app/features/alerting/unified/components/admin/AlertmanagerConfig.test.tsx +++ b/public/app/features/alerting/unified/components/admin/AlertmanagerConfig.test.tsx @@ -100,9 +100,7 @@ describe('Admin config', () => { alertmanager_config: {}, }); mocks.api.deleteAlertManagerConfig.mockResolvedValue(); - - await renderAdminPage(dataSources.alertManager.name); - + renderAdminPage(dataSources.alertManager.name); await userEvent.click(await ui.resetButton.find()); await userEvent.click(ui.confirmButton.get()); await waitFor(() => expect(mocks.api.deleteAlertManagerConfig).toHaveBeenCalled()); @@ -128,7 +126,7 @@ describe('Admin config', () => { mocks.api.fetchConfig.mockImplementation(() => Promise.resolve(savedConfig ?? defaultConfig)); mocks.api.updateAlertManagerConfig.mockResolvedValue(); - await renderAdminPage(dataSources.alertManager.name); + renderAdminPage(dataSources.alertManager.name); const input = await ui.configInput.find(); expect(input.value).toEqual(JSON.stringify(defaultConfig, null, 2)); await userEvent.clear(input); @@ -147,7 +145,7 @@ describe('Admin config', () => { ...someCloudAlertManagerStatus, config: someCloudAlertManagerConfig.alertmanager_config, }); - await renderAdminPage(dataSources.promAlertManager.name); + renderAdminPage(dataSources.promAlertManager.name); await ui.readOnlyConfig.find(); expect(ui.configInput.query()).not.toBeInTheDocument(); diff --git a/public/app/features/alerting/unified/components/admin/AlertmanagerConfig.tsx b/public/app/features/alerting/unified/components/admin/AlertmanagerConfig.tsx index 959e55d4d3a..b5d4261ba13 100644 --- a/public/app/features/alerting/unified/components/admin/AlertmanagerConfig.tsx +++ b/public/app/features/alerting/unified/components/admin/AlertmanagerConfig.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/css'; import React, { useEffect, useState, useMemo } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; -import { Alert, Button, ConfirmModal, TextArea, HorizontalGroup, Field, Form, useStyles2 } from '@grafana/ui'; +import { Alert, useStyles2 } from '@grafana/ui'; import { useDispatch } from 'app/types'; import { useAlertManagerSourceName } from '../../hooks/useAlertManagerSourceName'; @@ -17,7 +17,10 @@ import { GRAFANA_RULES_SOURCE_NAME, isVanillaPrometheusAlertManagerDataSource } import { initialAsyncRequestState } from '../../utils/redux'; import { AlertManagerPicker } from '../AlertManagerPicker'; -interface FormValues { +import AlertmanagerConfigSelector, { ValidAmConfigOption } from './AlertmanagerConfigSelector'; +import { ConfigEditor } from './ConfigEditor'; + +export interface FormValues { configJSON: string; } @@ -29,11 +32,14 @@ export default function AlertmanagerConfig(): JSX.Element { const [showConfirmDeleteAMConfig, setShowConfirmDeleteAMConfig] = useState(false); const { loading: isDeleting } = useUnifiedAlertingSelector((state) => state.deleteAMConfig); const { loading: isSaving } = useUnifiedAlertingSelector((state) => state.saveAMConfig); + const readOnly = alertManagerSourceName ? isVanillaPrometheusAlertManagerDataSource(alertManagerSourceName) : false; const styles = useStyles2(getStyles); const configRequests = useUnifiedAlertingSelector((state) => state.amConfigs); + const [selectedAmConfig, setSelectedAmConfig] = useState(); + const { result: config, loading: isLoadingConfig, @@ -60,6 +66,13 @@ export default function AlertmanagerConfig(): JSX.Element { [config] ); + const defaultValidValues = useMemo( + (): FormValues => ({ + configJSON: selectedAmConfig ? JSON.stringify(selectedAmConfig.value, null, 2) : '', + }), + [selectedAmConfig] + ); + const loading = isDeleting || isLoadingConfig || isSaving; const onSubmit = (values: FormValues) => { @@ -84,9 +97,25 @@ export default function AlertmanagerConfig(): JSX.Element { dataSources={alertManagers} /> {loadingError && !loading && ( - - {loadingError.message || 'Unknown error.'} - + <> + + {loadingError.message || 'Unknown error.'} + + + {alertManagerSourceName === GRAFANA_RULES_SOURCE_NAME && ( + + )} + )} {isDeleting && alertManagerSourceName !== GRAFANA_RULES_SOURCE_NAME && ( @@ -94,70 +123,17 @@ export default function AlertmanagerConfig(): JSX.Element { )} {alertManagerSourceName && config && ( -
- {({ register, errors }) => ( - <> - {!readOnly && ( - -