mirror of
https://github.com/grafana/grafana.git
synced 2025-12-21 03:54:29 +08:00
Compare commits
14 Commits
zoltan/pos
...
v11.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7a938db9a | ||
|
|
b9513983ce | ||
|
|
df7987a6b8 | ||
|
|
56e82b7a1c | ||
|
|
41e7cd2c02 | ||
|
|
6167aac263 | ||
|
|
6ee1bfb736 | ||
|
|
e0d8318caa | ||
|
|
842179916d | ||
|
|
d7d80d2634 | ||
|
|
fb0204c8df | ||
|
|
5f7f04518b | ||
|
|
5e369c6709 | ||
|
|
940d71250b |
220
.drone.yml
220
.drone.yml
@@ -25,7 +25,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- ./bin/build verify-drone
|
||||
@@ -75,7 +75,7 @@ steps:
|
||||
- go install github.com/bazelbuild/buildtools/buildifier@latest
|
||||
- buildifier --lint=warn -mode=check -r .
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: lint-starlark
|
||||
trigger:
|
||||
event:
|
||||
@@ -427,7 +427,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -436,21 +436,21 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- apk add --update build-base shared-mime-info shared-mime-info-lang
|
||||
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: test-backend
|
||||
- commands:
|
||||
- apk add --update build-base
|
||||
@@ -459,7 +459,7 @@ steps:
|
||||
| grep -o '\(.*\)/' | sort -u)
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: test-backend-integration
|
||||
trigger:
|
||||
event:
|
||||
@@ -513,7 +513,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- echo $(/usr/bin/github-app-external-token) > /github-app/token
|
||||
@@ -558,16 +558,16 @@ steps:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- go run scripts/modowners/modowners.go check go.mod
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: validate-modfile
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make swagger-validate
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: validate-openapi-spec
|
||||
trigger:
|
||||
event:
|
||||
@@ -643,7 +643,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- '# It is required that code generated from Thema/CUE be committed and in sync
|
||||
@@ -653,7 +653,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -662,7 +662,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- yarn install --immutable || yarn install --immutable
|
||||
@@ -698,7 +698,7 @@ steps:
|
||||
- /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64
|
||||
-a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
|
||||
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
|
||||
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.4 --yarn-cache=$$YARN_CACHE_FOLDER
|
||||
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.5 --yarn-cache=$$YARN_CACHE_FOLDER
|
||||
--build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.20.3
|
||||
--tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{
|
||||
.version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD
|
||||
@@ -1096,7 +1096,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- echo $DRONE_RUNNER_NAME
|
||||
@@ -1110,7 +1110,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -1119,14 +1119,14 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- dockerize -wait tcp://postgres:5432 -timeout 120s
|
||||
@@ -1147,7 +1147,7 @@ steps:
|
||||
GRAFANA_TEST_DB: postgres
|
||||
PGPASSWORD: grafanatest
|
||||
POSTGRES_HOST: postgres
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: postgres-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://mysql80:3306 -timeout 120s
|
||||
@@ -1168,7 +1168,7 @@ steps:
|
||||
environment:
|
||||
GRAFANA_TEST_DB: mysql
|
||||
MYSQL_HOST: mysql80
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: mysql-8.0-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://redis:6379 -timeout 120s
|
||||
@@ -1184,7 +1184,7 @@ steps:
|
||||
- wait-for-redis
|
||||
environment:
|
||||
REDIS_URL: redis://redis:6379/0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: redis-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://memcached:11211 -timeout 120s
|
||||
@@ -1200,7 +1200,7 @@ steps:
|
||||
- wait-for-memcached
|
||||
environment:
|
||||
MEMCACHED_HOSTS: memcached:11211
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: memcached-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
|
||||
@@ -1216,7 +1216,7 @@ steps:
|
||||
environment:
|
||||
AM_TENANT_ID: test
|
||||
AM_URL: http://mimir_backend:8080
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: remote-alertmanager-integration-tests
|
||||
trigger:
|
||||
event:
|
||||
@@ -1273,11 +1273,6 @@ steps:
|
||||
depends_on: []
|
||||
image: node:22.11.0-alpine
|
||||
name: yarn-install
|
||||
- commands:
|
||||
- pip3 install codespell
|
||||
- codespell -I docs/.codespellignore docs/
|
||||
image: python:3.8
|
||||
name: codespell
|
||||
- commands:
|
||||
- yarn run prettier:checkDocs
|
||||
depends_on:
|
||||
@@ -1303,7 +1298,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
trigger:
|
||||
event:
|
||||
@@ -1424,7 +1419,7 @@ steps:
|
||||
&& return 1; fi
|
||||
depends_on:
|
||||
- clone-enterprise
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: swagger-gen
|
||||
trigger:
|
||||
event:
|
||||
@@ -1529,7 +1524,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- '# It is required that code generated from Thema/CUE be committed and in sync
|
||||
@@ -1540,7 +1535,7 @@ steps:
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on:
|
||||
- clone-enterprise
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -1550,14 +1545,14 @@ steps:
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on:
|
||||
- clone-enterprise
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- apk add --update build-base
|
||||
@@ -1565,7 +1560,7 @@ steps:
|
||||
- go test -v -run=^$ -benchmem -timeout=1h -count=8 -bench=. ${GO_PACKAGES}
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: sqlite-benchmark-integration-tests
|
||||
- commands:
|
||||
- apk add --update build-base
|
||||
@@ -1577,7 +1572,7 @@ steps:
|
||||
GRAFANA_TEST_DB: postgres
|
||||
PGPASSWORD: grafanatest
|
||||
POSTGRES_HOST: postgres
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: postgres-benchmark-integration-tests
|
||||
- commands:
|
||||
- apk add --update build-base
|
||||
@@ -1588,7 +1583,7 @@ steps:
|
||||
environment:
|
||||
GRAFANA_TEST_DB: mysql
|
||||
MYSQL_HOST: mysql80
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: mysql-8.0-benchmark-integration-tests
|
||||
trigger:
|
||||
event:
|
||||
@@ -1635,11 +1630,6 @@ steps:
|
||||
depends_on: []
|
||||
image: node:22.11.0-alpine
|
||||
name: yarn-install
|
||||
- commands:
|
||||
- pip3 install codespell
|
||||
- codespell -I docs/.codespellignore docs/
|
||||
image: python:3.8
|
||||
name: codespell
|
||||
- commands:
|
||||
- yarn run prettier:checkDocs
|
||||
depends_on:
|
||||
@@ -1665,7 +1655,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
trigger:
|
||||
branch: main
|
||||
@@ -1838,7 +1828,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -1847,21 +1837,21 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- apk add --update build-base shared-mime-info shared-mime-info-lang
|
||||
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: test-backend
|
||||
- commands:
|
||||
- apk add --update build-base
|
||||
@@ -1870,7 +1860,7 @@ steps:
|
||||
| grep -o '\(.*\)/' | sort -u)
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: test-backend-integration
|
||||
trigger:
|
||||
branch: main
|
||||
@@ -1915,22 +1905,22 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- go run scripts/modowners/modowners.go check go.mod
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: validate-modfile
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make swagger-validate
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: validate-openapi-spec
|
||||
- commands:
|
||||
- ./bin/build verify-drone
|
||||
@@ -2062,7 +2052,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- '# It is required that code generated from Thema/CUE be committed and in sync
|
||||
@@ -2072,7 +2062,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -2081,7 +2071,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- yarn install --immutable || yarn install --immutable
|
||||
@@ -2116,7 +2106,7 @@ steps:
|
||||
- /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64
|
||||
-a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
|
||||
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
|
||||
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.4 --yarn-cache=$$YARN_CACHE_FOLDER
|
||||
-a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.5 --yarn-cache=$$YARN_CACHE_FOLDER
|
||||
--build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.20.3
|
||||
--tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{
|
||||
.version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD
|
||||
@@ -2591,7 +2581,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- echo $DRONE_RUNNER_NAME
|
||||
@@ -2605,7 +2595,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -2614,14 +2604,14 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- dockerize -wait tcp://postgres:5432 -timeout 120s
|
||||
@@ -2642,7 +2632,7 @@ steps:
|
||||
GRAFANA_TEST_DB: postgres
|
||||
PGPASSWORD: grafanatest
|
||||
POSTGRES_HOST: postgres
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: postgres-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://mysql80:3306 -timeout 120s
|
||||
@@ -2663,7 +2653,7 @@ steps:
|
||||
environment:
|
||||
GRAFANA_TEST_DB: mysql
|
||||
MYSQL_HOST: mysql80
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: mysql-8.0-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://redis:6379 -timeout 120s
|
||||
@@ -2679,7 +2669,7 @@ steps:
|
||||
- wait-for-redis
|
||||
environment:
|
||||
REDIS_URL: redis://redis:6379/0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: redis-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://memcached:11211 -timeout 120s
|
||||
@@ -2695,7 +2685,7 @@ steps:
|
||||
- wait-for-memcached
|
||||
environment:
|
||||
MEMCACHED_HOSTS: memcached:11211
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: memcached-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
|
||||
@@ -2711,7 +2701,7 @@ steps:
|
||||
environment:
|
||||
AM_TENANT_ID: test
|
||||
AM_URL: http://mimir_backend:8080
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: remote-alertmanager-integration-tests
|
||||
trigger:
|
||||
branch: main
|
||||
@@ -2970,7 +2960,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -2979,21 +2969,21 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- apk add --update build-base shared-mime-info shared-mime-info-lang
|
||||
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: test-backend
|
||||
- commands:
|
||||
- apk add --update build-base
|
||||
@@ -3002,7 +2992,7 @@ steps:
|
||||
| grep -o '\(.*\)/' | sort -u)
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: test-backend-integration
|
||||
trigger:
|
||||
branch:
|
||||
@@ -3045,22 +3035,22 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- go run scripts/modowners/modowners.go check go.mod
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: validate-modfile
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make swagger-validate
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: validate-openapi-spec
|
||||
trigger:
|
||||
branch:
|
||||
@@ -3139,7 +3129,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- echo $DRONE_RUNNER_NAME
|
||||
@@ -3153,7 +3143,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -3162,14 +3152,14 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- dockerize -wait tcp://postgres:5432 -timeout 120s
|
||||
@@ -3190,7 +3180,7 @@ steps:
|
||||
GRAFANA_TEST_DB: postgres
|
||||
PGPASSWORD: grafanatest
|
||||
POSTGRES_HOST: postgres
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: postgres-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://mysql80:3306 -timeout 120s
|
||||
@@ -3211,7 +3201,7 @@ steps:
|
||||
environment:
|
||||
GRAFANA_TEST_DB: mysql
|
||||
MYSQL_HOST: mysql80
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: mysql-8.0-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://redis:6379 -timeout 120s
|
||||
@@ -3227,7 +3217,7 @@ steps:
|
||||
- wait-for-redis
|
||||
environment:
|
||||
REDIS_URL: redis://redis:6379/0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: redis-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://memcached:11211 -timeout 120s
|
||||
@@ -3243,7 +3233,7 @@ steps:
|
||||
- wait-for-memcached
|
||||
environment:
|
||||
MEMCACHED_HOSTS: memcached:11211
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: memcached-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
|
||||
@@ -3259,7 +3249,7 @@ steps:
|
||||
environment:
|
||||
AM_TENANT_ID: test
|
||||
AM_URL: http://mimir_backend:8080
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: remote-alertmanager-integration-tests
|
||||
trigger:
|
||||
branch:
|
||||
@@ -3359,7 +3349,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- ./bin/build artifacts docker fetch --edition oss
|
||||
@@ -3491,7 +3481,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- ./bin/build artifacts docker fetch --edition oss
|
||||
@@ -3632,7 +3622,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- ./bin/build artifacts packages --artifacts-editions=oss --tag $${DRONE_TAG} --src-bucket
|
||||
@@ -3724,7 +3714,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- yarn install --immutable || yarn install --immutable
|
||||
@@ -3824,7 +3814,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- depends_on:
|
||||
- compile-build-cmd
|
||||
@@ -3921,7 +3911,7 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- ./bin/build publish grafana-com --edition oss ${DRONE_TAG}
|
||||
@@ -3983,7 +3973,7 @@ steps:
|
||||
from_secret: grafana_api_key
|
||||
GCP_KEY_BASE64:
|
||||
from_secret: gcp_key_base64
|
||||
GO_VERSION: 1.23.4
|
||||
GO_VERSION: 1.23.5
|
||||
GPG_PASSPHRASE:
|
||||
from_secret: packages_gpg_passphrase
|
||||
GPG_PRIVATE_KEY:
|
||||
@@ -4058,7 +4048,7 @@ steps:
|
||||
from_secret: grafana_api_key
|
||||
GCP_KEY_BASE64:
|
||||
from_secret: gcp_key_base64
|
||||
GO_VERSION: 1.23.4
|
||||
GO_VERSION: 1.23.5
|
||||
GPG_PASSPHRASE:
|
||||
from_secret: packages_gpg_passphrase
|
||||
GPG_PRIVATE_KEY:
|
||||
@@ -4115,13 +4105,13 @@ steps:
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- ./bin/build whatsnew-checker
|
||||
depends_on:
|
||||
- compile-build-cmd
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: whats-new-checker
|
||||
trigger:
|
||||
event:
|
||||
@@ -4220,7 +4210,7 @@ steps:
|
||||
from_secret: grafana_api_key
|
||||
GCP_KEY_BASE64:
|
||||
from_secret: gcp_key_base64
|
||||
GO_VERSION: 1.23.4
|
||||
GO_VERSION: 1.23.5
|
||||
GPG_PASSPHRASE:
|
||||
from_secret: packages_gpg_passphrase
|
||||
GPG_PRIVATE_KEY:
|
||||
@@ -4371,7 +4361,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -4380,21 +4370,21 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- apk add --update build-base shared-mime-info shared-mime-info-lang
|
||||
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: test-backend
|
||||
- commands:
|
||||
- apk add --update build-base
|
||||
@@ -4403,7 +4393,7 @@ steps:
|
||||
| grep -o '\(.*\)/' | sort -u)
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: test-backend-integration
|
||||
trigger:
|
||||
cron:
|
||||
@@ -4457,7 +4447,7 @@ steps:
|
||||
from_secret: grafana_api_key
|
||||
GCP_KEY_BASE64:
|
||||
from_secret: gcp_key_base64
|
||||
GO_VERSION: 1.23.4
|
||||
GO_VERSION: 1.23.5
|
||||
GPG_PASSPHRASE:
|
||||
from_secret: packages_gpg_passphrase
|
||||
GPG_PRIVATE_KEY:
|
||||
@@ -4601,7 +4591,7 @@ steps:
|
||||
from_secret: grafana_api_key
|
||||
GCP_KEY_BASE64:
|
||||
from_secret: gcp_key_base64
|
||||
GO_VERSION: 1.23.4
|
||||
GO_VERSION: 1.23.5
|
||||
GPG_PASSPHRASE:
|
||||
from_secret: packages_gpg_passphrase
|
||||
GPG_PRIVATE_KEY:
|
||||
@@ -4708,7 +4698,7 @@ steps:
|
||||
- export GITHUB_TOKEN=$(cat /github-app/token)
|
||||
- 'dagger run --silent /src/grafana-build artifacts -a $${ARTIFACTS} --grafana-ref=$${GRAFANA_REF}
|
||||
--enterprise-ref=$${ENTERPRISE_REF} --grafana-repo=$${GRAFANA_REPO} --version=$${VERSION} '
|
||||
- --go-version=1.23.4
|
||||
- --go-version=1.23.5
|
||||
depends_on:
|
||||
- github-app-generate-token
|
||||
environment:
|
||||
@@ -4729,7 +4719,7 @@ steps:
|
||||
from_secret: grafana_api_key
|
||||
GCP_KEY_BASE64:
|
||||
from_secret: gcp_key_base64
|
||||
GO_VERSION: 1.23.4
|
||||
GO_VERSION: 1.23.5
|
||||
GPG_PASSPHRASE:
|
||||
from_secret: packages_gpg_passphrase
|
||||
GPG_PRIVATE_KEY:
|
||||
@@ -4863,7 +4853,7 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
@@ -4872,14 +4862,14 @@ steps:
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- dockerize -wait tcp://postgres:5432 -timeout 120s
|
||||
@@ -4900,7 +4890,7 @@ steps:
|
||||
GRAFANA_TEST_DB: postgres
|
||||
PGPASSWORD: grafanatest
|
||||
POSTGRES_HOST: postgres
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: postgres-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://mysql80:3306 -timeout 120s
|
||||
@@ -4921,7 +4911,7 @@ steps:
|
||||
environment:
|
||||
GRAFANA_TEST_DB: mysql
|
||||
MYSQL_HOST: mysql80
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: mysql-8.0-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://redis:6379 -timeout 120s
|
||||
@@ -4937,7 +4927,7 @@ steps:
|
||||
- wait-for-redis
|
||||
environment:
|
||||
REDIS_URL: redis://redis:6379/0
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: redis-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://memcached:11211 -timeout 120s
|
||||
@@ -4953,7 +4943,7 @@ steps:
|
||||
- wait-for-memcached
|
||||
environment:
|
||||
MEMCACHED_HOSTS: memcached:11211
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: memcached-integration-tests
|
||||
- commands:
|
||||
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
|
||||
@@ -4969,7 +4959,7 @@ steps:
|
||||
environment:
|
||||
AM_TENANT_ID: test
|
||||
AM_URL: http://mimir_backend:8080
|
||||
image: golang:1.23.4-alpine
|
||||
image: golang:1.23.5-alpine
|
||||
name: remote-alertmanager-integration-tests
|
||||
trigger:
|
||||
event:
|
||||
@@ -5272,7 +5262,7 @@ steps:
|
||||
- commands:
|
||||
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM docker:27-cli
|
||||
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM alpine/git:2.40.1
|
||||
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM golang:1.23.4-alpine
|
||||
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM golang:1.23.5-alpine
|
||||
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM node:22.11.0-alpine
|
||||
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM node:22-bookworm
|
||||
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM google/cloud-sdk:431.0.0
|
||||
@@ -5310,7 +5300,7 @@ steps:
|
||||
- commands:
|
||||
- trivy --exit-code 1 --severity HIGH,CRITICAL docker:27-cli
|
||||
- trivy --exit-code 1 --severity HIGH,CRITICAL alpine/git:2.40.1
|
||||
- trivy --exit-code 1 --severity HIGH,CRITICAL golang:1.23.4-alpine
|
||||
- trivy --exit-code 1 --severity HIGH,CRITICAL golang:1.23.5-alpine
|
||||
- trivy --exit-code 1 --severity HIGH,CRITICAL node:22.11.0-alpine
|
||||
- trivy --exit-code 1 --severity HIGH,CRITICAL node:22-bookworm
|
||||
- trivy --exit-code 1 --severity HIGH,CRITICAL google/cloud-sdk:431.0.0
|
||||
@@ -5579,6 +5569,6 @@ kind: secret
|
||||
name: gcr_credentials
|
||||
---
|
||||
kind: signature
|
||||
hmac: bdf4cd3767ad13e5a8d7221731676e8ee1991dae0da9ae2cee92087d5c660ece
|
||||
hmac: 154c1f072294cef09ba4f579eed30b1e29bc5c263897c862f4574432d321502c
|
||||
|
||||
...
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
ARG BASE_IMAGE=alpine:3.20
|
||||
ARG JS_IMAGE=node:22-alpine
|
||||
ARG JS_PLATFORM=linux/amd64
|
||||
ARG GO_IMAGE=golang:1.23.1-alpine
|
||||
ARG GO_IMAGE=golang:1.23.5-alpine
|
||||
|
||||
ARG GO_SRC=go-builder
|
||||
ARG JS_SRC=js-builder
|
||||
|
||||
2
Makefile
2
Makefile
@@ -8,7 +8,7 @@ WIRE_TAGS = "oss"
|
||||
include .bingo/Variables.mk
|
||||
|
||||
GO = go
|
||||
GO_VERSION = 1.23.4
|
||||
GO_VERSION = 1.23.5
|
||||
GO_LINT_FILES ?= $(shell ./scripts/go-workspace/golangci-lint-includes.sh)
|
||||
GO_TEST_FILES ?= $(shell ./scripts/go-workspace/test-includes.sh)
|
||||
SH_FILES ?= $(shell find ./scripts -name *.sh)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/grafana/grafana/apps/alerting/notifications
|
||||
|
||||
go 1.23.4
|
||||
go 1.23.5
|
||||
|
||||
replace github.com/grafana/grafana => ../../..
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
aks
|
||||
eror
|
||||
geomap
|
||||
Geomap
|
||||
grafanalib
|
||||
grafonnet
|
||||
iam
|
||||
Jsonnet
|
||||
[Operato Windrose](https://grafana.com/grafana/plugins/operato-windrose-panel/)
|
||||
runbook
|
||||
sergent
|
||||
sparkline
|
||||
wan
|
||||
@@ -95,4 +95,4 @@ To set up LBAC for data sources for a data source, refer to [Configure LBAC for
|
||||
|
||||
## Provisioning of LBAC rules
|
||||
|
||||
We recommend using our Terraform provider to set up provisioning for [Resource data source config LBAC rules] (https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/data_source_config_lbac_rules). Refer to our provider documentation to learn how to configure rules for a data source.
|
||||
We recommend using our Terraform provider to set up provisioning for [Resource data source config LBAC rules](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/data_source_config_lbac_rules). Refer to our provider documentation to learn how to configure rules for a data source.
|
||||
|
||||
@@ -256,14 +256,24 @@ The system creates a session when a user signs in to Grafana from a new device,
|
||||
|
||||
When a user reaches the session limit, the fourth connection succeeds and the longest inactive session is signed out.
|
||||
|
||||
### Request usage billing
|
||||
|
||||
You can request Grafana Labs to activate usage billing which allows an unlimited number of active users. When usage billing is enabled, Grafana does not enforce active user limits or display warning banners. Instead, you are charged for active users that exceed the limit, according to your customer contract.
|
||||
|
||||
Usage billing involves a contractual agreement between you and Grafana Labs, and it is only available if Grafana Enterprise is configured to [automatically refresh its license token]({{< relref "../../setup-grafana/configure-grafana/enterprise-configuration/#auto_refresh_license" >}}).
|
||||
|
||||
### Request a change to your license
|
||||
|
||||
To increase the number of licensed users within Grafana, extend a license, or change your licensed URL, contact [Grafana support](/profile/org#support) or your Grafana Labs account team. They will update your license, which you can activate from within Grafana.
|
||||
|
||||
For instructions about how to activate your license after it is updated, refer to [Activate an Enterprise license]({{< relref "#activate-an-enterprise-license" >}}).
|
||||
|
||||
## Usage billing
|
||||
|
||||
Standard Grafana Enterprise licenses include a certain number of seats that can be used, and prevent more users logging into Grafana than have been licensed. This makes sense if you prefer a predictable bill. It can however be a problem if you anticipate uneven usage patterns over time or when it's critical that no user ever be prevented from logging into Grafana due to capacity constraints.
|
||||
|
||||
For those use-cases we support usage-based billing, where your license includes a certain number of included users and you are billed on a monthly basis for any excess active users during the month.
|
||||
|
||||
Usage billing involves a contractual agreement between you and Grafana Labs and an update to your license, and it is only available if Grafana Enterprise version 10.0.0 or higher is configured to [automatically refresh its license token]({{< relref "../../setup-grafana/configure-grafana/enterprise-configuration/#auto_refresh_license" >}}).
|
||||
|
||||
### User deduplication
|
||||
|
||||
If your organization has multiple Grafana Enterprise instances with usage billing enabled, then each active user counts only once toward your license, regardless of how many instances that user signs into. Each Grafana Enterprise instance submits a hashed list of users to Grafana Labs via API every day. Each user email address or anonymous device ID is hashed using a one-way sha256 algorithm, and submitted to Grafana where the hashed users are deduplicated across instances.
|
||||
|
||||
### Request usage billing
|
||||
|
||||
To request usage billing, contact your Grafana Labs account team or [submit a support ticket](https://grafana.com/profile/org#support).
|
||||
|
||||
@@ -218,3 +218,7 @@ For further details on how to template alert rules, refer to:
|
||||
|
||||
- [Annotation and label template reference](ref:alert-rule-template-reference)
|
||||
- [Annotation and label examples](ref:alert-rule-template-examples)
|
||||
|
||||
{{< admonition type="tip" >}}
|
||||
For a practical example of templating, refer to our [Getting Started with Templating tutorial](https://grafana.com/tutorials/alerting-get-started-pt4/).
|
||||
{{< /admonition >}}
|
||||
|
||||
@@ -193,15 +193,11 @@ For additional functions to display or format data, refer to:
|
||||
Here’s an example of creating a `severity` label based on a query value:
|
||||
|
||||
```go
|
||||
{{ if (gt $values.A.Value 90.0) -}}
|
||||
critical
|
||||
{{ else if (gt $values.A.Value 80.0) -}}
|
||||
high
|
||||
{{ else if (gt $values.A.Value 60.0) -}}
|
||||
medium
|
||||
{{ else -}}
|
||||
low
|
||||
{{- end }}
|
||||
{{- if (gt $values.A.Value 90.0) -}}critical
|
||||
{{- else if (gt $values.A.Value 80.0) -}}high
|
||||
{{- else if (gt $values.A.Value 60.0) -}}medium
|
||||
{{- else -}}low
|
||||
{{- end -}}
|
||||
```
|
||||
|
||||
In this example, the `severity` label is determined by the query value:
|
||||
@@ -222,10 +218,13 @@ You should avoid displaying query values in labels, as this may create many aler
|
||||
You can use labels to differentiate alerts coming from various environments (e.g., production, staging, dev). For example, you may want to add a label that sets the environment based on the instance’s label. Here’s how you can template it:
|
||||
|
||||
```go
|
||||
{{ if eq $labels.instance "prod-server-1" }}production
|
||||
{{ else if eq $labels.instance "staging-server-1" }}staging
|
||||
{{ else }}development
|
||||
{{ end }}
|
||||
{{- if eq $labels.instance "prod-server-1" -}}
|
||||
production
|
||||
{{- else if eq $labels.instance "staging-server-1" -}}
|
||||
staging
|
||||
{{- else -}}
|
||||
development
|
||||
{{- end -}}
|
||||
```
|
||||
|
||||
This would print:
|
||||
@@ -237,10 +236,13 @@ This would print:
|
||||
To make this template more flexible, you can use a regular expression that matches the instance name with the instance name prefix using the [`match()`](ref:reference-match) function:
|
||||
|
||||
```go
|
||||
{{ if match "^prod-server-.*" $labels.instance }}production
|
||||
{{ else if match "^staging-server-.*" $labels.instance}}staging
|
||||
{{ else }}development
|
||||
{{ end }}
|
||||
{{- if match "^prod-server-.*" $labels.instance -}}
|
||||
production
|
||||
{{- else if match "^staging-server-.*" $labels.instance -}}
|
||||
staging
|
||||
{{- else -}}
|
||||
development
|
||||
{{- end -}}
|
||||
```
|
||||
|
||||
{{< collapse title="Legacy Alerting templates" >}}
|
||||
|
||||
@@ -108,3 +108,7 @@ For further details on how to write notification templates, refer to:
|
||||
- [Select, create, and preview a notification template](ref:manage-notification-templates)
|
||||
- [Notification template reference](ref:reference)
|
||||
- [Notification template examples](ref:examples)
|
||||
|
||||
{{< admonition type="tip" >}}
|
||||
For a practical example of templating, refer to our [Getting Started with Templating tutorial](https://grafana.com/tutorials/alerting-get-started-pt4/).
|
||||
{{< /admonition >}}
|
||||
|
||||
@@ -111,6 +111,12 @@ The name of the alert is {{ .Labels.alertname }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
You can then use the template by passing the [notification data (dot `.`)](ref:reference-notification-data):
|
||||
|
||||
```go
|
||||
{{ template "custom_message" . }}
|
||||
```
|
||||
|
||||
```template_output
|
||||
The name of the alert is InstanceDown
|
||||
|
||||
@@ -140,7 +146,11 @@ In this example:
|
||||
- A template (`alert.summary_and_description`) is defined to print the `summary`, `status`, and `description` of one [alert](ref:reference-alert).
|
||||
- The main template `custom.alerts` iterates the list of alerts (`.Alerts`) in [notification data](ref:reference-notification-data), executing the `alert.summary_and_description` template to print the details of each alert.
|
||||
|
||||
The notification message would look like this:
|
||||
Execute the template by passing the dot (`.`):
|
||||
|
||||
```go
|
||||
{{ template "custom.alerts" . }}
|
||||
```
|
||||
|
||||
```template_output
|
||||
2 alert(s)
|
||||
@@ -178,7 +188,11 @@ The following example is similar to the previous one, but it separates firing an
|
||||
|
||||
Instead of `.Alerts`, the template accesses `.Alerts.Firing` and `.Alerts.Resolved` separately to print details for each alert.
|
||||
|
||||
The output might now look like this:
|
||||
Run the template by passing the dot (`.`):
|
||||
|
||||
```go
|
||||
{{ template "custom.firing_and_resolved_alerts" . }}
|
||||
```
|
||||
|
||||
```template_output
|
||||
1 resolved alert(s)
|
||||
@@ -215,6 +229,12 @@ Common annotations: {{ len .CommonAnnotations.SortedPairs }}
|
||||
|
||||
Note that `.CommonAnnotations` and `.CommonLabels` are part of [notification data](ref:reference-notification-data).
|
||||
|
||||
Execute the template by passing the dot (`.`) as argument:
|
||||
|
||||
```go
|
||||
{{ template "custom.common_labels_and_annotations" . }}
|
||||
```
|
||||
|
||||
```template_output
|
||||
1 resolved alert(s)
|
||||
1 firing alert(s)
|
||||
@@ -257,6 +277,12 @@ In this example:
|
||||
- The `custom.alert_labels_and_annotations` template iterates over the list of resolved and firing alerts, similar to previous examples. It then executes `alert.labels_and_annotations` for each alert.
|
||||
- The `alert.labels_and_annotations` template prints all the alert labels and annotations by accessing `.Labels.SortedPairs` and `.Annotations.SortedPairs`.
|
||||
|
||||
Run the template by passing the dot (`.`):
|
||||
|
||||
```go
|
||||
{{ template "custom.alert_labels_and_annotations" . }}
|
||||
```
|
||||
|
||||
```template_output
|
||||
1 resolved alert(s)
|
||||
|
||||
@@ -307,7 +333,11 @@ Note that the following example works only for Grafana-managed alerts. It displa
|
||||
{{ end -}}
|
||||
```
|
||||
|
||||
The output of this template looks like this:
|
||||
Pass the dot (`.`) to execute the template:
|
||||
|
||||
```go
|
||||
{{ template "custom.alert_additional_details" . }}
|
||||
```
|
||||
|
||||
```template_output
|
||||
1 resolved alert(s)
|
||||
@@ -339,6 +369,12 @@ Here’s a basic example that displays the number of firing and resolved alerts
|
||||
{{ end -}}
|
||||
```
|
||||
|
||||
Execute the template by passing the dot (`.`) as argument:
|
||||
|
||||
```go
|
||||
{{ template "custom_title" . }}
|
||||
```
|
||||
|
||||
```template_output
|
||||
🚨 1 firing alerts. ✅ 1 resolved alerts.
|
||||
```
|
||||
@@ -357,6 +393,12 @@ This is a more advanced example:
|
||||
- Outputs `.GroupLabels`, the labels used to [group multiple alerts in one notification](ref:group-alert-notifications).
|
||||
- Prints `CommonLabels`, excluding labels in `.GroupLabels`.
|
||||
|
||||
Execute the template by passing the dot (`.`):
|
||||
|
||||
```go
|
||||
{{ template "copy_of_default_title" . }}
|
||||
```
|
||||
|
||||
```template_output
|
||||
[FIRING:1, RESOLVED:1] api warning (sql_db)
|
||||
```
|
||||
|
||||
@@ -86,6 +86,12 @@ Here's an example that prints all available notification data from dot (`.`):
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
You can execute this template by passing the dot (`.`):
|
||||
|
||||
```go
|
||||
{{ template "custom_template" . }}
|
||||
```
|
||||
|
||||
## Alert
|
||||
|
||||
`Alert` contains data for an individual alert:
|
||||
@@ -133,6 +139,12 @@ This example iterates over the list of firing and resolved alerts (`.Alerts`) in
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
You can run this template by passing the dot (`.`):
|
||||
|
||||
```go
|
||||
{{ template "custom_template" . }}
|
||||
```
|
||||
|
||||
## KV
|
||||
|
||||
`KV` is a set of key value pairs, where each key and value is a string.
|
||||
|
||||
@@ -91,7 +91,7 @@ Note that `No Data` and `Error` states are supported only for Grafana-managed al
|
||||
|
||||
{{< docs/shared lookup="alerts/table-configure-no-data-and-error.md" source="grafana" version="<GRAFANA_VERSION>" >}}
|
||||
|
||||
Note that when you configure the **No Data** or **Error** behavior to `Alerting` or `Normal`, Grafana attempts to keep a stable set of fields under notification `Values`. If your query returns no data or an error, Grafana re-uses the latest known set of fields in `Values`, but will use `-1` in place of the measured value.
|
||||
Note that when you configure the **No Data** or **Error** behavior to `Alerting` or `Normal`, Grafana attempts to keep a stable set of fields under notification `Values`. If your query returns no data or an error, Grafana reuses the latest known set of fields in `Values`, but will use `-1` in place of the measured value.
|
||||
|
||||
### Reduce `No Data` or `Error` alerts
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ refs:
|
||||
|
||||
Grouping in Grafana Alerting allows you to batch relevant alerts together into a smaller number of notifications. This is particularly important if notifications are delivered to first-responders, such as engineers on-call, where receiving lots of notifications in a short period of time can be overwhelming. In some cases, it can negatively impact a first-responders ability to respond to an incident. For example, consider a large outage where many of your systems are down. In this case, grouping can be the difference between receiving 1 phone call and 100 phone calls.
|
||||
|
||||
{{< admonition type="tip" >}}
|
||||
For a practical example of grouping, refer to our [Getting Started with Grouping tutorial](https://grafana.com/tutorials/alerting-get-started-pt3/).
|
||||
{{< /admonition >}}
|
||||
|
||||
## Group notifications
|
||||
|
||||
Grouping combines similar alert instances within a specific period into a single notification, reducing alert noise.
|
||||
|
||||
@@ -75,6 +75,10 @@ Each policy consists of a set of label matchers (0 or more) that specify which a
|
||||
|
||||
{{< figure src="/media/docs/alerting/notification-routing.png" max-width="750px" caption="Matching alert instances with notification policies" alt="Example of a notification policy tree" >}}
|
||||
|
||||
{{< admonition type="tip" >}}
|
||||
For a practical example of routing with notification policies, refer to our [Getting Started with Alert Instances and Notification Routing tutorial](https://grafana.com/tutorials/alerting-get-started-pt4/).
|
||||
{{< /admonition >}}
|
||||
|
||||
## Routing
|
||||
|
||||
To determine which notification policies handle an alert instance, the system looks for matching policies starting from the top of the tree—beginning with the default notification policy.
|
||||
|
||||
@@ -69,6 +69,10 @@ In Grafana, you have various options to template your alert notification message
|
||||
- Template notifications when you want to customize the appearance and information of your notifications.
|
||||
- Avoid using notification templates to add extra information to alert instances—use annotations instead.
|
||||
|
||||
{{< admonition type="tip" >}}
|
||||
For a practical example of templating, refer to our [Getting Started with Templating tutorial](https://grafana.com/tutorials/alerting-get-started-pt4/).
|
||||
{{< /admonition >}}
|
||||
|
||||
This diagram illustrates the entire templating process, from querying labels and templating the alert summary and notification to the final alert notification message.
|
||||
|
||||
{{< figure src="/media/docs/alerting/how-notification-templates-works.png" max-width="1200px" caption="How templating works" >}}
|
||||
|
||||
351
docs/sources/dashboards/create-reports/_index.md
Normal file
351
docs/sources/dashboards/create-reports/_index.md
Normal file
@@ -0,0 +1,351 @@
|
||||
---
|
||||
aliases:
|
||||
- ../administration/reports/ # /docs/grafana/latest/administration/reports/
|
||||
- ../enterprise/export-pdf/ # /docs/grafana/latest/enterprise/export-pdf/
|
||||
- ../enterprise/reporting/ # /docs/grafana/latest/enterprise/reporting/
|
||||
- ../panels/create-reports/ # /docs/grafana/latest/panels/create-reports/
|
||||
- reporting/ # /docs/grafana/latest/dashboards/reporting/
|
||||
keywords:
|
||||
- grafana
|
||||
- reporting
|
||||
- export
|
||||
- pdf
|
||||
labels:
|
||||
products:
|
||||
- cloud
|
||||
- enterprise
|
||||
menuTitle: Reporting
|
||||
title: Create and manage reports
|
||||
description: Generate and share PDF reports from your Grafana dashboards
|
||||
weight: 600
|
||||
refs:
|
||||
repeat-panels-or-rows:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/panels-visualizations/configure-panel-options/#configure-repeating-panels
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/visualizations/panels-visualizations/configure-panel-options/#configure-repeating-panels
|
||||
http-apis:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/developers/http_api/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/developers/http_api/
|
||||
image-rendering:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/image-rendering/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/image-rendering/
|
||||
rbac:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
permission:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/
|
||||
role-based-access-control:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
configuration:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/
|
||||
image-rendering:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/image-rendering/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/image-rendering/
|
||||
templates-and-variables:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/dashboards/variables/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/visualizations/dashboards/variables/
|
||||
grafana-enterprise:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/
|
||||
configuration:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#filters
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#filters
|
||||
time-range-controls:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/dashboards/use-dashboards/#set-dashboard-time-range
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/visualizations/dashboards/use-dashboards/#set-dashboard-time-range
|
||||
send-report:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/developers/http_api/reporting/#send-a-report
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/developer-resources/api-reference/http-api/reporting/#send-a-report
|
||||
smtp:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#smtp
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#smtp
|
||||
temp-data-lifetime:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#temp_data_lifetime
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#temp_data_lifetime
|
||||
rendering-configuration:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/dashboards/create-reports/report-settings/#rendering-configuration
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/dashboards/create-reports/report-settings/#rendering-configuration
|
||||
reporting-configuration:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/enterprise-configuration/#reporting
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/enterprise-configuration/#reporting
|
||||
|
||||
---
|
||||
|
||||
# Create and manage reports
|
||||
|
||||
**Reporting** allows you to automatically generate PDFs from any of your dashboards and have Grafana email them to interested parties on a schedule. This is available in Grafana Cloud and in Grafana Enterprise.
|
||||
|
||||
{{< admonition type="note" >}}
|
||||
If you have [Role-based access control](ref:role-based-access-control) enabled, for some actions you would need to have relevant permissions.
|
||||
Refer to specific guides to understand what permissions are required.
|
||||
{{< /admonition >}}
|
||||
|
||||
Any changes you make to a dashboard used in a report are reflected the next time the report is sent. For example, if you change the time range in the dashboard, then the time range in the report also changes, unless you've configured a custom time range.
|
||||
|
||||
## Requirements
|
||||
|
||||
- SMTP must be configured for reports to be sent. Refer to [SMTP](ref:smtp) in [Configuration](ref:configuration) for more information.
|
||||
- The Image Renderer plugin must be installed or the remote rendering service must be set up. Refer to [Image rendering](ref:image-rendering) for more information.
|
||||
|
||||
### Rendering configuration
|
||||
|
||||
When generating reports, each panel renders separately before being collected in a PDF. You can configure the per-panel rendering timeout and number of concurrently rendered panels.
|
||||
|
||||
To make a panel more legible, you can set a scale factor for the rendered images. However, a higher scale factor increases the file size of the generated PDF.
|
||||
|
||||
You can also specify custom fonts that support different Unicode scripts. The DejaVu font is the default used for PDF rendering.
|
||||
|
||||
These options are available in the [reporting configuration](ref:reporting-configuration) of the `ini` file for Enterprise Grafana.
|
||||
|
||||
## Access control
|
||||
|
||||
When [RBAC](ref:rbac) is enabled, you need to have the relevant [Permissions](ref:permission) to create and manage reports.
|
||||
|
||||
## Create a report
|
||||
|
||||
Only organization administrators can create reports by default. You can customize who can create reports with [Role-based access control](ref:role-based-access-control).
|
||||
|
||||
The report creation process is multi-step, but you don't need to complete these steps in order and you can skip steps by clicking a step name at the top of the page:
|
||||
|
||||

|
||||
|
||||
To create a report, follow these steps:
|
||||
|
||||
1. Click **Dashboards > Reporting** in the main menu.
|
||||
1. Click **+ Create a new report**.
|
||||
1. Complete the report steps, as needed; you don't need to complete these steps in order and you can skip steps by clicking a step name at the top of the page:
|
||||
- [Select dashboard](#1-select-dashboard)
|
||||
- [Format report](#2-format-report)
|
||||
- [Schedule](#3-schedule)
|
||||
- [Share](#4-share)
|
||||
- [Confirm](#5-confirm)
|
||||
1. Click one of the following buttons in the top-right corner of the screen:
|
||||
- **Send now** or **Schedule send** - The report is sent according the schedule you've set.
|
||||
- **Save as draft** - You can save a draft at any point during the report creation or update process, even if it's missing required fields. The report won't be sent according to its schedule while it's a draft.
|
||||
- **Discard** - Delete the report draft. This action can't be reversed.
|
||||
|
||||
### 1. Select dashboard
|
||||
|
||||
At this step, select the dashboard or dashboards on which the report is based, as well as the variables and time range for those dashboards. The options are:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Source dashboard | Select the dashboard from which you want to generate the report. |
|
||||
| [Template variables (optional)](#template-variables) | Select the variable values for the selected dashboard. This option is only displayed if the dashboard has variables. |
|
||||
| [Time range (optional)](#time-range) | By default, reports use the saved time range of the dashboard. Optionally, you can change the time range of the report. |
|
||||
| Add another dashboard | Add more dashboards to the report. Additional dashboards will be rendered as new pages in the same PDF file, or additional images if you chose to embed images in your report email. You can't add the same dashboard to a report multiple times. |
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
#### Template variables
|
||||
|
||||
This option is only displayed if the dashboard has variables.
|
||||
|
||||
You can configure report-specific template variables for the dashboard on the report page. The variables that you select will override the variables from the dashboard, and they are used when rendering a PDF file of the report. For detailed information about using template variables, refer to the [Templates and variables](ref:templates-and-variables) section.
|
||||
|
||||
The query variables saved with a report might become out of date if the results of that query change. For example, if your template variable queries for a list of hostnames and a new hostname is added, then it will not be included in the report. If that occurs, the selected variables must be manually updated in the report. If you select the **All** value for the template variable or if you keep the dashboard's original variable selection, then the report stays up-to-date as new values are added.
|
||||
|
||||
#### Time range
|
||||
|
||||
By default, reports use the saved time range of the dashboard. Optionally, you can change the time range of the report by:
|
||||
|
||||
- Saving a modified time range to the dashboard. Changing the dashboard time range without saving it doesn't change the time zone of the report.
|
||||
- Setting a time range via the **Time range** field in the report form. If specified, the custom time range overrides the time range from the report's dashboard.
|
||||
|
||||
The page header of the report displays the time range for the dashboard's data queries.
|
||||
|
||||
##### Report time zones
|
||||
|
||||
Reports use the time zone of the dashboard from which they’re generated. You can control the time zone for your reports by setting the dashboard to a specific time zone. Note that this affects the display of the dashboard for all users.
|
||||
|
||||
If a dashboard has the **Browser Time** setting, the reports generated from that dashboard use the time zone of the Grafana server. As a result, this time zone might not match the time zone of users creating or receiving the report.
|
||||
|
||||
If the time zone is set differently between your Grafana server and its remote image renderer, then the time ranges in the report might be different between the page header and the time axes in the panels. To avoid this, set the time zone to UTC for dashboards when using a remote renderer. Each dashboard's time zone setting is visible in the [time range controls](ref:time-range-controls).
|
||||
|
||||
### 2. Format report
|
||||
|
||||
At this step, set the report formatting options. You can select multiple options:
|
||||
|
||||
- [Attach the report as a PDF](#attach-the-report-as-a-pdf)
|
||||
- [Include table data as PDF appendix](#table-data-in-pdf) (Public preview only)
|
||||
- [Embed a dashboard image in the email](#embed-a-dashboard-as-an-image-in-the-email)
|
||||
- [Attach a CSV file of the table panel data](#attach-a-csv-file-of-the-table-panel-data)
|
||||
- [Attach a separate PDF of table data](#table-data-in-pdf) (Public preview only)
|
||||
|
||||
#### Attach the report as a PDF
|
||||
|
||||
If you selected the PDF format option, under the **Style the PDF** section, set the following options:
|
||||
|
||||
- **Show template variables** - Click the checkbox to select this option.
|
||||
- **Orientation** - Set the report orientation in **Portrait** or **Landscape**. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
|
||||
- **Layout** - Select one of the following:
|
||||
- **Simple** - Renders each panel as full-width across the PDF. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
|
||||
- **Grid** - Renders the PDF with the same panel arrangement and width as the source dashboard. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
|
||||
- **Zoom** - Zoom in to enlarge text in your PDF, or zoom out to see more data (like table columns) per panel.
|
||||
|
||||
Click **Preview PDF** in the top-right corner of the screen to view a rendered PDF with the options you selected.
|
||||
|
||||
##### Layout and orientation
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
| Layout | Orientation | Description | Preview |
|
||||
| ------ | ----------- | --------------------------------------------------------------------------------------------------------- | ------------ |
|
||||
| Simple | Portrait | Generates an A4 page in portrait mode with three panels per page. | {{< figure src="/static/img/docs/enterprise/reports_portrait_preview.png" max-width="500px" alt="Simple layout in portrait" >}} |
|
||||
| Simple | Landscape | Generates an A4 page in landscape mode with a single panel per page. | {{< figure src="/static/img/docs/enterprise/reports_landscape_preview.png" max-width="500px" alt="Simple layout in landscape" >}} |
|
||||
| Grid | Portrait | Generates an A4 page in portrait mode with panels arranged in the same way as at the original dashboard. | {{< figure src="/static/img/docs/enterprise/reports_grid_portrait_preview.png" max-width="500px" alt="Grid layout in portrait" >}} |
|
||||
| Grid | Landscape | Generates an A4 page in landscape mode with panels arranged in the same way as in the original dashboard. | {{< figure src="/static/img/docs/enterprise/reports_grid_landscape_preview.png" max-width="500px" alt="Grid layout in landscape" >}} |
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
#### Embed a dashboard as an image in the email
|
||||
|
||||
You can send a report email with an image of the dashboard embedded in the email instead of attached as a PDF. In this case, the email recipients can see the dashboard at a glance instead of having to open the PDF.
|
||||
|
||||
#### Attach a CSV file of the table panel data
|
||||
|
||||
{{< admonition type="note" >}}
|
||||
To use this feature in Grafana Enterprise, you must have [Grafana image renderer plugin](/grafana/plugins/grafana-image-renderer) v3.0.
|
||||
{{< /admonition >}}
|
||||
|
||||
You can attach a CSV file to the report email for each table panel on the selected dashboard, along with the PDF report. By default, CSV files larger than 10Mb are not sent, which keeps email servers from rejecting the email. You can increase or decrease this limit in the [reporting configuration](ref:rendering-configuration).
|
||||
|
||||
This feature relies on the same plugin that supports the [image rendering](ref:image-rendering) features.
|
||||
|
||||
When the CSV file is generated, it is temporarily written to the `csv` folder in the Grafana `data` folder.
|
||||
|
||||
A background job runs every 10 minutes and removes temporary CSV files. You can configure how long a CSV file should be stored before being removed by configuring the [temp-data-lifetime](ref:temp-data-lifetime) setting. This setting also affects how long a renderer PNG file should be stored.
|
||||
|
||||
Click **Download CSV** in the top-right corner of the screen to see the file.
|
||||
|
||||
#### Table data in PDF
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Available in public preview (`pdfTables` feature toggle) in [Grafana Enterprise](ref:grafana-enterprise) v10.3+ with the [Grafana image renderer plugin](/grafana/plugins/grafana-image-renderer) v3.0+, as well as [Grafana Cloud](/docs/grafana-cloud/).
|
||||
{{% /admonition %}}
|
||||
|
||||
When there's more data in your table visualizations than can be shown in the dashboard PDF, you can select one of these two options to access all table visualization data as PDF in your reports:
|
||||
|
||||
- **Include table data as PDF appendix** - Adds an appendix to the main dashboard PDF.
|
||||
- **Attach a separate PDF of table data** - Generates a separate PDF file.
|
||||
|
||||
This feature relies on the same plugin that supports the [image rendering](ref:image-rendering) features.
|
||||
|
||||
### 3. Schedule
|
||||
|
||||
At this step, set scheduling information. Options vary depending on the frequency you select.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Frequency | Scheduled reports can be sent once, or repeated on an hourly, daily, weekly, or monthly basis, or sent at custom intervals. You can also disable scheduling by selecting **Never**, for example to send the report using the API. |
|
||||
| Time | Choose one of the following:<ul><li>**Send now** sends the report immediately after you save it. To stop sending the report at some point in the future, add an end date.</li><li>**Send later** schedules a report for a later date. When you select this option, the required **Start date**, **Start time**, and **Time zone** options are displayed.</li></ul> |
|
||||
| End date | If you leave the end date empty, the report is sent out indefinitely. |
|
||||
| Send only from Monday to Friday | For reports that have an hourly or daily frequency, you can choose to send them only from Monday to Friday. |
|
||||
| Send on the last day of the month | When you schedule a report with a monthly frequency, and set the start date between the 29th and the 31st of the month, the report is only sent during the months that have those dates. If you want the report to be sent every month, select this option instead. This way, the report is sent on the last day of every month regardless of how many days there are in any given month. |
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
### 4. Share
|
||||
|
||||
At this step, enter information related to sharing the report:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Report name | Name of the report as you want it to appear in the **Reports** list. The report name also populates the email subject line. |
|
||||
| Recipients | Enter the email addresses of the people or teams that you want to receive the report, separated by commas or semicolons. |
|
||||
| Reply-to email address | The address that appears in the **Reply to** field of the email. |
|
||||
| Message | Message body in the email with the report. |
|
||||
| Include a dashboard link | Include a link to the dashboard from within the report email. |
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
Click **Send test email** in the top-right corner of the screen to verify that the configuration works as expected and to verify that emails are working. You can choose to send this email to the recipients configured for the report, or to a different set of email addresses only used for testing. The last saved version of the report will be sent to selected emails.
|
||||
|
||||
### 5. Confirm
|
||||
|
||||
At this step, the confirmation page displays all your the settings. Review them and confirm that they're correct or click the provided **Edit** links for each section to make updates.
|
||||
|
||||
Then, click **Send now** or **Schedule send**.
|
||||
|
||||
You can also save the report as a draft or discard it. Discarding the report is irreversible.
|
||||
|
||||
## Send a report using the API
|
||||
|
||||
You can send reports programmatically with the [send report](ref:send-report) endpoint in the [HTTP APIs](ref:http-apis).
|
||||
|
||||
## Manage reports
|
||||
|
||||
On the **Reports** page, you can view and manage your existing reports or create new ones.
|
||||
|
||||

|
||||
|
||||
### Edit
|
||||
|
||||
To edit a report, follow these steps:
|
||||
|
||||
1. In the main menu, click **Dashboards > Reporting**.
|
||||
1. Click the row of the report you want to update.
|
||||
1. Click the **Edit report** button in the top-right hand corner or click the **Edit** link for a specific section to go to that one directly.
|
||||
1. When you've finished making changes, click **Confirm** at the top of the screen to go to the last step.
|
||||
1. Click **Update report**.
|
||||
|
||||
### Pause or resume a report
|
||||
|
||||
You can pause and resume sending reports from the report list view. To do this, follow these steps:
|
||||
|
||||
1. In the main menu, click **Dashboards > Reporting**.
|
||||
1. On the row of the report you want to update, do one of the following:
|
||||
|
||||
- Click the pause icon - The report won't be sent according to its schedule until it's resumed.
|
||||
- Click the resume icon - The report resumes on its previous schedule.
|
||||
|
||||
## Troubleshoot Reporting
|
||||
|
||||
To troubleshoot and get more log information, enable debug logging in the configuration file. Refer to [Configuration](ref:configuration) for more information.
|
||||
|
||||
```bash
|
||||
[log]
|
||||
filters = report:debug
|
||||
```
|
||||
@@ -1,363 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- ../administration/reports/ # /docs/grafana/latest/administration/reports/
|
||||
- ../enterprise/export-pdf/ # /docs/grafana/latest/enterprise/export-pdf/
|
||||
- ../enterprise/reporting/ # /docs/grafana/latest/enterprise/reporting/
|
||||
- ../panels/create-reports/ # /docs/grafana/latest/panels/create-reports/
|
||||
- reporting/ # /docs/grafana/latest/dashboards/reporting/
|
||||
keywords:
|
||||
- grafana
|
||||
- reporting
|
||||
- export
|
||||
- pdf
|
||||
labels:
|
||||
products:
|
||||
- cloud
|
||||
- enterprise
|
||||
menuTitle: Reporting
|
||||
title: Create and manage reports
|
||||
description: Generate and share PDF reports from your Grafana dashboards
|
||||
weight: 600
|
||||
refs:
|
||||
repeat-panels-or-rows:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/panels-visualizations/configure-panel-options/#configure-repeating-rows-or-panels
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/visualizations/panels-visualizations/configure-panel-options/#configure-repeating-rows-or-panels
|
||||
http-apis:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/developers/http_api/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/developers/http_api/
|
||||
image-rendering:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/image-rendering/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/image-rendering/
|
||||
rbac:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
permission:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/
|
||||
role-based-access-control:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
configuration:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/
|
||||
image-rendering:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/image-rendering/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/image-rendering/
|
||||
templates-and-variables:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/dashboards/variables/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/visualizations/dashboards/variables/
|
||||
grafana-enterprise:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/
|
||||
configuration:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#filters
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#filters
|
||||
time-range-controls:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/dashboards/use-dashboards/#set-dashboard-time-range
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/visualizations/dashboards/use-dashboards/#set-dashboard-time-range
|
||||
send-report:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/developers/http_api/reporting/#send-a-report
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/developer-resources/api-reference/http-api/reporting/#send-a-report
|
||||
smtp:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#smtp
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#smtp
|
||||
temp-data-lifetime:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#temp-data-lifetime
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#temp-data-lifetime
|
||||
---
|
||||
|
||||
# Create and manage reports
|
||||
|
||||
Reporting enables you to automatically generate PDFs from any of your dashboards and have Grafana email them to interested parties on a schedule. This is available in Grafana Cloud and in Grafana Enterprise.
|
||||
|
||||
> If you have [Role-based access control](ref:role-based-access-control) enabled, for some actions you would need to have relevant permissions.
|
||||
> Refer to specific guides to understand what permissions are required.
|
||||
|
||||
Any changes you make to a dashboard used in a report are reflected the next time the report is sent. For example, if you change the time range in the dashboard, then the time range in the report also changes, unless you've configured a custom time range.
|
||||
|
||||
For information about recent improvements to the reporting UI, refer to [Grafana reporting: How we improved the UX in Grafana](https://grafana.com/blog/2022/06/29/grafana-reporting-how-we-improved-the-ux-in-grafana/).
|
||||
|
||||
## Requirements
|
||||
|
||||
- SMTP must be configured for reports to be sent. Refer to [SMTP](ref:smtp) in [Configuration](ref:configuration) for more information.
|
||||
- The Image Renderer plugin must be installed or the remote rendering service must be set up. Refer to [Image rendering](ref:image-rendering) for more information.
|
||||
|
||||
## Access control
|
||||
|
||||
When [RBAC](ref:rbac) is enabled, you need to have the relevant [Permissions](ref:permission) to create and manage reports.
|
||||
|
||||
## Create or update a report
|
||||
|
||||
Only organization administrators can create reports by default. You can customize who can create reports with [Role-based access control](ref:role-based-access-control).
|
||||
|
||||
1. Click **Dashboards > Reports** in the side navigation menu.
|
||||
|
||||
The Reports page allows you to view, create, and update your reports. The report form has a multi-step layout. The steps do not need to be completed in succession and can be skipped over by clicking a step name.
|
||||
|
||||
1. Click **+ Create a new report**.
|
||||
1. Select report dashboard.
|
||||
- **Source dashboard:** Select the dashboard from which you want to generate the report.
|
||||
- **Time range:** (optional) Use custom time range for the report. For more information, refer to [Report time range](#report-time-range).
|
||||
- **Add another dashboard:** Add more than one dashboard to the report.
|
||||
1. Format the report.
|
||||
- **Choose format options for the report:** Select at least one option. Attach report as PDF, embed dashboard as an image, or attach CSV file of table panel data.
|
||||
- If you selected the PDF format option:
|
||||
- Select an orientation for the report: **Portrait** or **Landscape**.
|
||||
- Select a layout for the generated report: **Simple** or **Grid**. The simple layout renders each panel as full-width across the PDF. The grid layout renders the PDF with the same panel arrangement and width as the source dashboard.
|
||||
- Select a zoom level for the report. Zoom in to enlarge text in your PDF, or zoom out to see more data (like table columns) per panel.
|
||||
- Click **Preview PDF** to view a rendered PDF with the options you selected.
|
||||
1. Schedule report.
|
||||
- Enter scheduling information. Options vary depending on the frequency selected.
|
||||
1. Enter report information. All fields are required unless otherwise indicated.
|
||||
- **Report name:** Name of the report as you want it to appear in the **Reports** list. The report name populates the email subject line.
|
||||
- **Recipients:** Enter the emails of the people or teams that you want to receive the report, separated by commas or semicolons.
|
||||
- **Reply to:** (optional) The address that appears in the **Reply to** field of the email.
|
||||
- **Message:** (optional) Message body in the email with the report.
|
||||
- **Include a dashboard link:** Include a link to the dashboard from within the report email.
|
||||
- **Send test email:** To verify that the configuration works as expected. You can choose to send this email to the recipients configured for the report, or to a different set of email addresses only used for testing.
|
||||
1. Preview and save the report.
|
||||
|
||||
### Save as draft
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
You can save a report as a draft at any point during the report creation or update process. You can save a report as a draft even if it's missing required fields. Also, the report won't be sent according to its schedule while it's a draft.
|
||||
|
||||
### Choose template variables
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
You can configure report-specific template variables for the dashboard on the report page. The variables that you select will override the variables from the dashboard, and they are used when rendering a PDF file of the report. For detailed information about using template variables, refer to the [Templates and variables](ref:templates-and-variables) section.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
The query variables saved with a report might become of date if the results of that query change. For example, if your template variable queries for a list of hostnames and a new hostname is added, then it will not be included in the report. If that occurs, the selected variables must be manually updated in the report. If you select the `All` value for the template variable or if you keep the dashboard's original variable selection, then the report stays up-to-date as new values are added.
|
||||
{{% /admonition %}}
|
||||
|
||||
### Render a report with panels or rows set to repeat by a variable
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
You can include dynamic dashboards with panels or rows, set to repeat by a variable, into reports. For detailed information about setting up repeating panels or rows in dashboards, refer to [Repeat panels or rows](ref:repeat-panels-or-rows).
|
||||
|
||||
### Report time range
|
||||
|
||||
> **Note:** You can set custom report time ranges in [Grafana Enterprise](ref:grafana-enterprise) 7.2+ and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
By default, reports use the saved time range of the dashboard. You can change the time range of the report by:
|
||||
|
||||
- Saving a modified time range to the dashboard. Changing the dashboard time range without saving it doesn't change the time zone of the report.
|
||||
- Setting a time range via the **Time range** field in the report form. If specified, the custom time range overrides the time range from the report's dashboard.
|
||||
|
||||
The page header of the report displays the time range for the dashboard's data queries.
|
||||
|
||||
#### Report time zones
|
||||
|
||||
Reports use the time zone of the dashboard from which they’re generated. You can control the time zone for your reports by setting the dashboard to a specific time zone. Note that this affects the display of the dashboard for all users.
|
||||
|
||||
If a dashboard has the **Browser Time** setting, the reports generated from that dashboard use the time zone of the Grafana server. As a result, this time zone might not match the time zone of users creating or receiving the report.
|
||||
|
||||
If the time zone is set differently between your Grafana server and its remote image renderer, then the time ranges in the report might be different between the page header and the time axes in the panels. To avoid this, set the time zone to UTC for dashboards when using a remote renderer. Each dashboard's time zone setting is visible in the [time range controls](ref:time-range-controls).
|
||||
|
||||
### Layout and orientation
|
||||
|
||||
| Layout | Orientation | Support | Description | Preview |
|
||||
| ------ | ----------- | ------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Simple | Portrait | v6.4+ | Generates an A4 page in portrait mode with three panels per page. | {{< figure src="/static/img/docs/enterprise/reports_portrait_preview.png" max-width="500px" max-height="500px" class="docs-image--no-shadow" alt="Simple layout in portrait" >}} |
|
||||
| Simple | Landscape | v6.7+ | Generates an A4 page in landscape mode with a single panel per page. | {{< figure src="/static/img/docs/enterprise/reports_landscape_preview.png" max-width="500px" class="docs-image--no-shadow" alt="Simple layout in landscape" >}} |
|
||||
| Grid | Portrait | v7.2+ | Generates an A4 page in portrait mode with panels arranged in the same way as at the original dashboard. | {{< figure src="/static/img/docs/enterprise/reports_grid_portrait_preview.png" max-width="500px" max-height="500px" class="docs-image--no-shadow" alt="Grid layout in portrait" >}} |
|
||||
| Grid | Landscape | v7.2+ | Generates an A4 page in landscape mode with panels arranged in the same way as in the original dashboard. | {{< figure src="/static/img/docs/enterprise/reports_grid_landscape_preview.png" max-width="500px" class="docs-image--no-shadow" alt="Grid layout in landscape" >}} |
|
||||
|
||||
### CSV export
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) 8+ with the [Grafana image renderer plugin](/grafana/plugins/grafana-image-renderer) v3.0+, and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
You can attach a CSV file to the report email for each table panel on the selected dashboard, along with the PDF report. By default, CSVs larger than 10Mb are not sent which keeps email servers from rejecting the email. You can increase or decrease this limit in the [reporting configuration](#rendering-configuration).
|
||||
|
||||
This feature relies on the same plugin that supports the [image rendering](ref:image-rendering) features.
|
||||
|
||||
When the CSV file is generated, it is temporarily written to the `csv` folder in the Grafana `data` folder.
|
||||
|
||||
A background job runs every 10 minutes and removes temporary CSV files. You can configure how long a CSV file should be stored before being removed by configuring the [temp-data-lifetime](ref:temp-data-lifetime) setting. This setting also affects how long a renderer PNG file should be stored.
|
||||
|
||||
### Table data in PDF
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Available in public preview (`pdfTables` feature toggle) in [Grafana Enterprise](ref:grafana-enterprise) v10.3+ with the [Grafana image renderer plugin](/grafana/plugins/grafana-image-renderer) v3.0+, and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
{{% /admonition %}}
|
||||
|
||||
When there's more data in your table visualizations than can be shown in the dashboard PDF, you can select one of these two options to access all table visualization data as PDF in your reports:
|
||||
|
||||
- **Include table data as PDF appendix** - Adds an appendix to the main dashboard PDF.
|
||||
- **Attach a separate PDF of table data** - Generates a separate PDF file.
|
||||
|
||||
This feature relies on the same plugin that supports the [image rendering](ref:image-rendering) features.
|
||||
|
||||
### Scheduling
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
Scheduled reports can be sent once, or repeated on an hourly, daily, weekly, or monthly basis, or sent at custom intervals. You can also disable scheduling by selecting **Never**, for example to send the report via the API.
|
||||
|
||||
**Send now or schedule for later**
|
||||
|
||||
- **Send now** sends the report immediately after you save it. To stop sending the report at some point in the future, add an end date. If you leave the end date empty, the report is sent out indefinitely.
|
||||
|
||||
- **Send later** schedules a report for a later date. Thus, the start date and time are required fields. If you leave the end date empty, the report is sent out indefinitely.
|
||||
|
||||
**Send only from Monday to Friday**
|
||||
|
||||
For reports that have an hourly or daily frequency, you can choose to send them only from Monday to Friday.
|
||||
|
||||
**Send on the last day of the month**
|
||||
|
||||
When you schedule a report with a monthly frequency, and set the start date between the 29th and the 31st of the month, the report is only sent during the months that have those dates. If you want the report to be sent every month, select the **Send on the last day of the month** option instead. This way, the report is sent on the last day of every month regardless of how many days there are in any given month.
|
||||
|
||||
#### Send a test email
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
1. In the report, click **Send test email**.
|
||||
1. In the **Email** field, enter the email address or addresses that you want to test, separated by a semicolon.
|
||||
If you want to use email addresses from the report, then select the **Use emails from report** check box.
|
||||
1. Click **Send**.
|
||||
|
||||
The last saved version of the report will be sent to selected emails. You can use this to verify emails are working and to make sure the report is generated and displayed as you expect.
|
||||
|
||||
### Pause a report
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
You can pause sending reports from the report list view by clicking the pause icon. The report will not be sent according to its schedule until it is resumed by clicking the resume button on the report row.
|
||||
|
||||
### Add multiple dashboards to a report
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
You can add more than one dashboard to a report. Additional dashboards will be rendered as new pages in the same PDF file, or additional images if you chose to embed images in your report email. You cannot add the same dashboard to a report multiple times.
|
||||
|
||||
### Embed a dashboard as an image into a report
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
You can send a report email with an image of the dashboard embedded in the email instead of attached as a PDF. In this case, the email recipients can see the dashboard at a glance instead of having to open the PDF.
|
||||
|
||||
## Export dashboard as PDF
|
||||
|
||||
You can generate and save PDF files of any dashboard.
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
1. In the dashboard that you want to export as PDF, click the **Share** button.
|
||||
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.
|
||||
|
||||
Grafana opens the PDF file in a new window or browser tab.
|
||||
|
||||
## Send a report via the API
|
||||
|
||||
You can send reports programmatically with the [send report](ref:send-report) endpoint in the [HTTP APIs](ref:http-apis).
|
||||
|
||||
## Rendering configuration
|
||||
|
||||
When generating reports, each panel renders separately before being collected in a PDF. You can configure the per-panel rendering timeout and number of concurrently rendered panels.
|
||||
|
||||
To make a panel more legible, you can set a scale factor for the rendered images. However, a higher scale factor increases the file size of the generated PDF.
|
||||
|
||||
You can also specify custom fonts that support different Unicode scripts. The DejaVu font is the default used for PDF rendering.
|
||||
|
||||
These options are available in the [configuration](ref:configuration) file.
|
||||
|
||||
```ini
|
||||
[reporting]
|
||||
# Use this option to enable or disable the reporting feature. When disabled, no reports are generated, and the UI is hidden. By default, reporting is enabled.
|
||||
enabled = true
|
||||
# Set timeout for the following reporting rendering requests: generating PDFs, generating embedded dashboard images for report emails, and generating attached CSV files.
|
||||
rendering_timeout = 10s
|
||||
# Set maximum number of concurrent calls to the rendering service
|
||||
concurrent_render_limit = 4
|
||||
# Set the scale factor for rendering images. 2 is enough for monitor resolutions
|
||||
# 4 would be better for printed material. Setting a higher value affects performance and memory
|
||||
image_scale_factor = 2
|
||||
# Set the maximum file size in megabytes for the report email attachments
|
||||
max_attachment_size_mb = 10
|
||||
# Path to the directory containing font files
|
||||
fonts_path =
|
||||
# Name of the TrueType font file with regular style
|
||||
font_regular = DejaVuSansCondensed.ttf
|
||||
# Name of the TrueType font file with bold style
|
||||
font_bold = DejaVuSansCondensed-Bold.ttf
|
||||
# Name of the TrueType font file with italic style
|
||||
font_italic = DejaVuSansCondensed-Oblique.ttf
|
||||
# Maximum number of times the following reporting rendering requests are retried before returning an error: generating PDFs, generating embedded dashboard images for report emails, and generating attached CSV files. To disable the retry feature, enter `0`. This is available in public preview and requires the `reportingRetries` feature toggle.
|
||||
max_retries_per_panel = 3
|
||||
# Allowed domains to receive reports. Use an asterisk (`*`) to allow all domains. Use a comma-separated list to allow multiple domains. Example: allowed_domains = grafana.com, example.org
|
||||
allowed_domains = *
|
||||
```
|
||||
|
||||
## Report settings
|
||||
|
||||
> **Note:** Available in [Grafana Enterprise](ref:grafana-enterprise) and [Grafana Cloud](/docs/grafana-cloud/).
|
||||
|
||||
You can configure organization-wide report settings in the **Settings** under **Dashboards > Reporting**. Settings are applied to all the reports for current organization.
|
||||
|
||||
You can customize the branding options.
|
||||
|
||||
### Attachment settings
|
||||
|
||||
#### PDF
|
||||
|
||||
- **Company logo:** Company logo displayed in the report PDF. It can be configured by specifying a URL, or by uploading a file. The maximum file size is 16 MB. Defaults to the Grafana logo.
|
||||
|
||||
- **Theme:** Theme of the PDF attached to the report. Defaults to **Light**. The selected theme is also applied to the PDFs generated when you click **Preview PDF** during report creation or select the **Export as PDF** option on a dashboard. If **Current** is selected, the PDF in the report will be in the Admin's instance theme, but the preview and exported PDFs will be in the user's instance theme.
|
||||
|
||||
#### Embedded Image
|
||||
|
||||
- **Theme:** Theme of the dashboard image embedded in the email. Defaults to **Dark**.
|
||||
|
||||
### Email branding
|
||||
|
||||
- **Company logo:** Company logo displayed in the report email. It can be configured by specifying a URL, or by uploading a file. The maximum file size is 16 MB. Defaults to the Grafana logo.
|
||||
- **Email footer:** Toggle to enable the report email footer. Select **Sent by** or **None**.
|
||||
- **Footer link text:** Text of the link in the report email footer. Defaults to `Grafana`.
|
||||
- **Footer link URL:** Link of the report email footer.
|
||||
|
||||
Currently, the API does not allow for the simultaneous upload of files with identical names for both the email logo and report logo. You can still upload the same file for each logo separately in two distinct steps.
|
||||
|
||||
## Troubleshoot reporting
|
||||
|
||||
To troubleshoot and get more log information, enable debug logging in the configuration file. Refer to [Configuration](ref:configuration) for more information.
|
||||
|
||||
```bash
|
||||
[log]
|
||||
filters = report:debug
|
||||
```
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
keywords:
|
||||
- grafana
|
||||
- reporting
|
||||
- settings
|
||||
labels:
|
||||
products:
|
||||
- cloud
|
||||
- enterprise
|
||||
menuTitle: Settings
|
||||
title: Reporting settings
|
||||
description: Manage organizational Reporting settings
|
||||
weight: 700
|
||||
refs:
|
||||
grafana-enterprise:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/
|
||||
configuration:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#filters
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#filters
|
||||
---
|
||||
|
||||
# Reporting settings
|
||||
|
||||
You can configure organization-wide report settings and branding options in **Dashboards > Reporting > Settings**. Settings are applied to all the reports for the current organization.
|
||||
|
||||
## Attachment settings
|
||||
|
||||
The options in this section control the branding and theming of the report attachments.
|
||||
|
||||
### PDF
|
||||
|
||||
- **Company logo** - Company logo displayed in the report PDF. It can be configured by specifying a URL, or by uploading a file. The maximum file size is 16 MB. Defaults to the Grafana logo.
|
||||
|
||||
- **Theme** - Theme of the PDF attached to the report. Defaults to **Light**. The selected theme is also applied to the PDFs generated when you click **Preview PDF** during report creation or select the **Export as PDF** option on a dashboard. If **Current** is selected, the PDF in the report will be in the instance theme of the Admin, but the preview and exported PDFs will be in the user's instance theme.
|
||||
|
||||
### Embedded Image
|
||||
|
||||
- **Theme** - Theme of the dashboard image embedded in the email. Defaults to **Dark**.
|
||||
|
||||
<!-- vale Grafana.WordList = NO -->
|
||||
|
||||
## Email branding
|
||||
|
||||
<!-- vale Grafana.WordList = YES -->
|
||||
|
||||
- **Company logo** - Company logo displayed in the report email. It can be configured by specifying a URL, or by uploading a file. The maximum file size is 16 MB. Defaults to the Grafana logo.
|
||||
- **Email footer** - Toggle to enable the report email footer. Select **Sent by** or **None**.
|
||||
- **Footer link text** - Text of the link in the report email footer. Defaults to `Grafana`.
|
||||
- **Footer link URL** - Link of the report email footer.
|
||||
|
||||
Currently, the API does not allow for the simultaneous upload of files with identical names for both the email logo and report logo. You can still upload the same file for each logo separately in two distinct steps.
|
||||
@@ -244,9 +244,10 @@ guaranteed because plugin developers can override this functionality. The follow
|
||||
|
||||
### Unsupported
|
||||
|
||||
- DynamoDB
|
||||
- Dynatrace
|
||||
- Graphite
|
||||
- Google Sheets
|
||||
- Dynatrace
|
||||
|
||||
### Unconfirmed
|
||||
|
||||
|
||||
@@ -138,21 +138,25 @@ Age for recent active users.
|
||||
|
||||
## [reporting]
|
||||
|
||||
### enabled
|
||||
|
||||
Enable or disable the reporting feature. When disabled, no reports are generated, and the UI is hidden. By default, reporting is enabled (`true`).
|
||||
|
||||
### rendering_timeout
|
||||
|
||||
Timeout for the following reporting rendering requests: generating PDFs, generating embedded dashboard images for report emails, and generating attached CSV files.
|
||||
Timeout for the following reporting rendering requests: generating PDFs, generating embedded dashboard images for report emails, and generating attached CSV files. Default is 10 seconds.
|
||||
|
||||
### concurrent_render_limit
|
||||
|
||||
Maximum number of concurrent calls to the rendering service.
|
||||
Maximum number of concurrent calls to the rendering service. Default is `4`.
|
||||
|
||||
### image_scale_factor
|
||||
|
||||
Scale factor for rendering images. Value `2` is enough for monitor resolutions, `4` would be better for printed material. Setting a higher value affects performance and memory.
|
||||
Scale factor for rendering images. Value `2` is enough for monitor resolutions, `4` would be better for printed material. Setting a higher value affects performance and memory. Default is `2`.
|
||||
|
||||
### max_attachment_size_mb
|
||||
|
||||
Set the maximum file size in megabytes for the report email attachments.
|
||||
Set the maximum file size in megabytes for the report email attachments. Default is `10`.
|
||||
|
||||
### fonts_path
|
||||
|
||||
@@ -160,7 +164,7 @@ Path to the directory containing font files.
|
||||
|
||||
### font_regular
|
||||
|
||||
Name of the TrueType font file with regular style.
|
||||
Name of the TrueType font file with regular style. Default is `DejaVuSansCondensed.ttf`.
|
||||
|
||||
### font_bold
|
||||
|
||||
@@ -168,15 +172,15 @@ Name of the TrueType font file with bold style.
|
||||
|
||||
### font_italic
|
||||
|
||||
Name of the TrueType font file with italic style.
|
||||
Name of the TrueType font file with italic style. Default is `DejaVuSansCondensed-Oblique.ttf`.
|
||||
|
||||
### max_retries_per_panel
|
||||
|
||||
Maximum number of times the following reporting rendering requests are retried before returning an error: generating PDFs, generating embedded dashboard images for report emails, and generating attached CSV files. To disable the retry feature, enter `0`. This is available in public preview and requires the `reportingRetries` feature toggle.
|
||||
Maximum number of times the following reporting rendering requests are retried before returning an error: generating PDFs, generating embedded dashboard images for report emails, and generating attached CSV files. To disable the retry feature, enter `0`. This is available in public preview and requires the `reportingRetries` feature toggle. Default is `3`.
|
||||
|
||||
### allowed_domains
|
||||
|
||||
Allowed domains to receive reports. Use an asterisk (`*`) to allow all domains. Use a comma-separated list to allow multiple domains. Example: allowed_domains = grafana.com, example.org
|
||||
Allowed domains to receive reports. Use an asterisk (`*`) to allow all domains. Use a comma-separated list to allow multiple domains. Example: `allowed_domains = grafana.com`, example.org. Default is `*`.
|
||||
|
||||
## [auditing]
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ This section describes the steps you must complete to access Grafana via web bro
|
||||
|
||||
## Customize Grafana default configuration
|
||||
|
||||
Helm is a popular package manager for Kubernetes. It bundles Kubernetes resource manifests to be re-used across different environments. These manifests are written in a templating language, allowing you to provide configuration values via `values.yaml` file, or in-line using Helm, to replace the placeholders in the manifest where these configurations should reside.
|
||||
Helm is a popular package manager for Kubernetes. It bundles Kubernetes resource manifests to be reused across different environments. These manifests are written in a templating language, allowing you to provide configuration values via `values.yaml` file, or in-line using Helm, to replace the placeholders in the manifest where these configurations should reside.
|
||||
|
||||
The `values.yaml` file allows you to customize the chart's configuration by specifying values for various parameters such as image versions, resource limits, service configurations, etc.
|
||||
|
||||
|
||||
@@ -177,6 +177,41 @@ This is the rewrite rule that's generated in the `web.config`:
|
||||
|
||||
For more detailed instruction, refer to the [tutorial on IIS URL Rewrites](/tutorials/iis/).
|
||||
|
||||
### Configure Apache
|
||||
|
||||
To use Apache as a proxy, ensure its proper installation and configuration.
|
||||
|
||||
1. Ensure that the Apache proxy module [`mod_proxy`](https://httpd.apache.org/docs/current/mod/mod_proxy.html) is installed and enabled. To enable, run the following commands:
|
||||
|
||||
```bash
|
||||
a2enmod proxy
|
||||
a2enmod proxy_http
|
||||
```
|
||||
|
||||
2. To configure the proxy, edit the site configuration file. To do so, inside the `<VirtualHost>` section, add the following code:
|
||||
|
||||
```bash
|
||||
ProxyPreserveHost on
|
||||
ProxyPass / http://your_grafana_server:3000
|
||||
ProxyPassReverse / http://your_grafana_server:3000
|
||||
```
|
||||
|
||||
3. Finally, restart Apache for the settings to take effect.
|
||||
|
||||
After you've restarted, navigate to your Apache server on port 80 and you will be redirected to Grafana.
|
||||
|
||||
To configure Grafana hosted in a sub path, replace the sub path with the following code (assuming your Grafana instance is on the sub path `your_path`):
|
||||
|
||||
```bash
|
||||
ProxyPreserveHost on
|
||||
ProxyPass /your_path http://your_grafana_server:3000
|
||||
ProxyPassReverse /your_path http://your_grafana_server:3000
|
||||
ProxyPass / http://your_grafana_server:3000/your_path
|
||||
ProxyPassReverse / http://192.168.250.5:3000/your_path
|
||||
```
|
||||
|
||||
Note that the lines containing `your_path` _must_ come before the lines referencing root path (`/`) in order for this to work correctly.
|
||||
|
||||
### Configure Traefik
|
||||
|
||||
[Traefik](https://traefik.io/traefik/) Cloud Native application proxy.
|
||||
|
||||
4
go.mod
4
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/grafana/grafana
|
||||
|
||||
go 1.23.4
|
||||
go 1.23.5
|
||||
|
||||
require (
|
||||
buf.build/gen/go/parca-dev/parca/connectrpc/go v1.17.0-20240902100956-02fd72488966.1 // @grafana/observability-traces-and-profiling
|
||||
@@ -64,7 +64,7 @@ require (
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 // @grafana/grafana-backend-group
|
||||
github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group
|
||||
github.com/gorilla/websocket v1.5.3 // @grafana/grafana-app-platform-squad
|
||||
github.com/grafana/alerting v0.0.0-20250110220613-267368fd1968 // @grafana/alerting-backend
|
||||
github.com/grafana/alerting v0.0.0-20250123190916-7b528a0bc1d5 // @grafana/alerting-backend
|
||||
github.com/grafana/authlib v0.0.0-20250108202437-7a039176d884 // @grafana/identity-access-team
|
||||
github.com/grafana/authlib/claims v0.0.0-20241202085737-df90af04f335 // @grafana/identity-access-team
|
||||
github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1489,8 +1489,8 @@ github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7Fsg
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grafana/alerting v0.0.0-20250110220613-267368fd1968 h1:dSA0aOMzNnpBmYcmwv2OT5Is4kE7rubdSxo9GZSePAY=
|
||||
github.com/grafana/alerting v0.0.0-20250110220613-267368fd1968/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||
github.com/grafana/alerting v0.0.0-20250123190916-7b528a0bc1d5 h1:mZezO6ccQl6AZv55f9JsPMph3eoHCofIJra2yhKzYMo=
|
||||
github.com/grafana/alerting v0.0.0-20250123190916-7b528a0bc1d5/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||
github.com/grafana/authlib v0.0.0-20250108202437-7a039176d884 h1:MSRBiQrSJZ+iowjU4Tgtq8+uC5/cs9XdtUdSWCNHrNE=
|
||||
github.com/grafana/authlib v0.0.0-20250108202437-7a039176d884/go.mod h1:x7df73G3xuSD35Xv9cjaMLyPJCgM9Z/Wj5ISouoAfiI=
|
||||
github.com/grafana/authlib/claims v0.0.0-20241202085737-df90af04f335 h1:3DHH81RJCi8Bcgn2MdBh7vgWUshmAFjZzBCVuxiQ0uk=
|
||||
|
||||
2
go.work
2
go.work
@@ -1,4 +1,4 @@
|
||||
go 1.23.4
|
||||
go 1.23.5
|
||||
|
||||
// The `skip:golangci-lint` comment tag is used to exclude the package from the `golangci-lint` GitHub Action.
|
||||
// The module at the root of the repo (`.`) is excluded because ./pkg/... is included manually in the `golangci-lint` configuration.
|
||||
|
||||
@@ -1697,6 +1697,7 @@ github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386/go.mod h1:JDGc
|
||||
github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
|
||||
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/cel-go v0.17.1/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
|
||||
github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/go-jsonnet v0.18.0 h1:/6pTy6g+Jh1a1I2UMoAODkqELFiVIdOxbNwv0DDzoOg=
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"generate-apis": "rtk-query-codegen-openapi ./scripts/generate-rtk-apis.ts"
|
||||
},
|
||||
"grafana": {
|
||||
"whatsNewUrl": "https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-v11-4/",
|
||||
"whatsNewUrl": "https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-v11-5/",
|
||||
"releaseNotesUrl": "https://grafana.com/docs/grafana/next/release-notes/"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -267,7 +267,7 @@ type ThreemaIntegration struct {
|
||||
type VictoropsIntegration struct {
|
||||
DisableResolveMessage *bool `json:"-" yaml:"-" hcl:"disable_resolve_message"`
|
||||
|
||||
URL string `json:"url" yaml:"url" hcl:"url"`
|
||||
URL Secret `json:"url" yaml:"url" hcl:"url"`
|
||||
|
||||
MessageType *string `json:"messageType,omitempty" yaml:"messageType,omitempty" hcl:"message_type"`
|
||||
Title *string `json:"title,omitempty" yaml:"title,omitempty" hcl:"title"`
|
||||
|
||||
@@ -388,6 +388,7 @@ func GetAvailableNotifiers() []*NotifierPlugin {
|
||||
Placeholder: "VictorOps url",
|
||||
PropertyName: "url",
|
||||
Required: true,
|
||||
Secure: true,
|
||||
},
|
||||
{ // New in 8.0.
|
||||
Label: "Message Type",
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestGetSecretKeysForContactPointType(t *testing.T) {
|
||||
{receiverType: "kafka", expectedSecretFields: []string{"password"}},
|
||||
{receiverType: "email", expectedSecretFields: []string{}},
|
||||
{receiverType: "pagerduty", expectedSecretFields: []string{"integrationKey"}},
|
||||
{receiverType: "victorops", expectedSecretFields: []string{}},
|
||||
{receiverType: "victorops", expectedSecretFields: []string{"url"}},
|
||||
{receiverType: "oncall", expectedSecretFields: []string{"password", "authorization_credentials"}},
|
||||
{receiverType: "pushover", expectedSecretFields: []string{"apiToken", "userKey"}},
|
||||
{receiverType: "slack", expectedSecretFields: []string{"token", "url"}},
|
||||
|
||||
@@ -485,6 +485,14 @@ func (rs *ReceiverService) UpdateReceiver(ctx context.Context, r *models.Receive
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We re-encrypt the existing receiver to ensure any unencrypted secure fields that are correctly encrypted, note this should NOT re-encrypt secure fields that are already encrypted.
|
||||
// This is rare, but can happen if a receiver is created with unencrypted secure fields and then the secure option is added later.
|
||||
// Preferably, this would be handled by receiver config versions and migrations but for now this is a good safety net.
|
||||
err = existing.Encrypt(rs.encryptor(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
span.AddEvent("Loaded current receiver", trace.WithAttributes(
|
||||
attribute.String("concurrency_token", revision.ConcurrencyToken),
|
||||
attribute.String("receiver", existing.Name),
|
||||
|
||||
@@ -583,6 +583,44 @@ func TestReceiverService_Update(t *testing.T) {
|
||||
), rm.Encrypted(models.Base64Enrypt)),
|
||||
expectedProvenances: map[string]models.Provenance{slackIntegration.UID: models.ProvenanceNone},
|
||||
},
|
||||
{
|
||||
name: "encrypts previously unencrypted secure fields",
|
||||
user: writer,
|
||||
receiver: models.CopyReceiverWith(baseReceiver, rm.WithIntegrations(
|
||||
models.CopyIntegrationWith(slackIntegration, im.AddSetting("token", "unencryptedValue"))),
|
||||
),
|
||||
existing: util.Pointer(models.CopyReceiverWith(baseReceiver, rm.WithIntegrations(
|
||||
models.CopyIntegrationWith(slackIntegration,
|
||||
im.AddSetting("token", "unencryptedValue"), // This will get encrypted.
|
||||
),
|
||||
))),
|
||||
expectedUpdate: models.CopyReceiverWith(baseReceiver, rm.WithIntegrations(
|
||||
models.CopyIntegrationWith(slackIntegration,
|
||||
im.AddSecureSetting("token", "dW5lbmNyeXB0ZWRWYWx1ZQ==")),
|
||||
), rm.Encrypted(models.Base64Enrypt)),
|
||||
expectedProvenances: map[string]models.Provenance{slackIntegration.UID: models.ProvenanceNone},
|
||||
},
|
||||
{
|
||||
// This test is important for covering the rare case when an existing field is marked as secure.
|
||||
// The UI will receive the field as secure and, if unchanged, will pass it back on update as a secureField instead of a Setting.
|
||||
name: "encrypts previously unencrypted secure fields when passed in as secureFields",
|
||||
user: writer,
|
||||
receiver: models.CopyReceiverWith(baseReceiver, rm.WithIntegrations(
|
||||
models.CopyIntegrationWith(slackIntegration, im.AddSetting("newField", "newValue"))),
|
||||
),
|
||||
secureFields: map[string][]string{slackIntegration.UID: {"token"}},
|
||||
existing: util.Pointer(models.CopyReceiverWith(baseReceiver, rm.WithIntegrations(
|
||||
models.CopyIntegrationWith(slackIntegration,
|
||||
im.AddSetting("token", "unencryptedValue"), // This will get encrypted.
|
||||
),
|
||||
))),
|
||||
expectedUpdate: models.CopyReceiverWith(baseReceiver, rm.WithIntegrations(
|
||||
models.CopyIntegrationWith(slackIntegration,
|
||||
im.AddSetting("newField", "newValue"),
|
||||
im.AddSecureSetting("token", "dW5lbmNyeXB0ZWRWYWx1ZQ==")),
|
||||
), rm.Encrypted(models.Base64Enrypt)),
|
||||
expectedProvenances: map[string]models.Provenance{slackIntegration.UID: models.ProvenanceNone},
|
||||
},
|
||||
{
|
||||
name: "doesn't copy existing unsecure fields",
|
||||
user: writer,
|
||||
@@ -684,8 +722,22 @@ func TestReceiverService_Update(t *testing.T) {
|
||||
sut := createReceiverServiceSut(t, &secretsService)
|
||||
|
||||
if tc.existing != nil {
|
||||
created, err := sut.CreateReceiver(context.Background(), tc.existing, tc.user.GetOrgID(), tc.user)
|
||||
// Create route after receivers as they will be referenced.
|
||||
revision, err := sut.cfgStore.Get(context.Background(), tc.user.GetOrgID())
|
||||
require.NoError(t, err)
|
||||
result, err := revision.CreateReceiver(tc.existing)
|
||||
require.NoError(t, err)
|
||||
|
||||
created, err := PostableApiReceiverToReceiver(result, tc.existing.Provenance)
|
||||
require.NoError(t, err)
|
||||
err = sut.cfgStore.Save(context.Background(), revision, tc.user.GetOrgID())
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, integration := range created.Integrations {
|
||||
target := definitions.EmbeddedContactPoint{UID: integration.UID}
|
||||
err = sut.provisioningStore.SetProvenance(context.Background(), &target, tc.user.GetOrgID(), created.Provenance)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if tc.version == "" {
|
||||
tc.version = created.Version
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/grafana/grafana/pkg/storage/unified/apistore
|
||||
|
||||
go 1.23.4
|
||||
go 1.23.5
|
||||
|
||||
replace (
|
||||
github.com/grafana/grafana => ../../../..
|
||||
@@ -169,7 +169,7 @@ require (
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/grafana/alerting v0.0.0-20250110220613-267368fd1968 // indirect
|
||||
github.com/grafana/alerting v0.0.0-20250123190916-7b528a0bc1d5 // indirect
|
||||
github.com/grafana/authlib v0.0.0-20250108202437-7a039176d884 // indirect
|
||||
github.com/grafana/dataplane/sdata v0.0.9 // indirect
|
||||
github.com/grafana/dskit v0.0.0-20241105154643-a6b453a88040 // indirect
|
||||
|
||||
@@ -543,8 +543,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grafana/alerting v0.0.0-20250110220613-267368fd1968 h1:dSA0aOMzNnpBmYcmwv2OT5Is4kE7rubdSxo9GZSePAY=
|
||||
github.com/grafana/alerting v0.0.0-20250110220613-267368fd1968/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||
github.com/grafana/alerting v0.0.0-20250123190916-7b528a0bc1d5 h1:mZezO6ccQl6AZv55f9JsPMph3eoHCofIJra2yhKzYMo=
|
||||
github.com/grafana/alerting v0.0.0-20250123190916-7b528a0bc1d5/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||
github.com/grafana/authlib v0.0.0-20250108202437-7a039176d884 h1:MSRBiQrSJZ+iowjU4Tgtq8+uC5/cs9XdtUdSWCNHrNE=
|
||||
github.com/grafana/authlib v0.0.0-20250108202437-7a039176d884/go.mod h1:x7df73G3xuSD35Xv9cjaMLyPJCgM9Z/Wj5ISouoAfiI=
|
||||
github.com/grafana/authlib/claims v0.0.0-20241202085737-df90af04f335 h1:3DHH81RJCi8Bcgn2MdBh7vgWUshmAFjZzBCVuxiQ0uk=
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/grafana/grafana/pkg/storage/unified/resource
|
||||
|
||||
go 1.23.4
|
||||
go 1.23.5
|
||||
|
||||
replace (
|
||||
github.com/grafana/grafana => ../../../..
|
||||
@@ -116,7 +116,7 @@ require (
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/grafana/alerting v0.0.0-20250110220613-267368fd1968 // indirect
|
||||
github.com/grafana/alerting v0.0.0-20250123190916-7b528a0bc1d5 // indirect
|
||||
github.com/grafana/dataplane/sdata v0.0.9 // indirect
|
||||
github.com/grafana/grafana-aws-sdk v0.31.5 // indirect
|
||||
github.com/grafana/grafana-azure-sdk-go/v2 v2.1.2 // indirect
|
||||
|
||||
@@ -398,8 +398,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
|
||||
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/grafana/alerting v0.0.0-20250110220613-267368fd1968 h1:dSA0aOMzNnpBmYcmwv2OT5Is4kE7rubdSxo9GZSePAY=
|
||||
github.com/grafana/alerting v0.0.0-20250110220613-267368fd1968/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||
github.com/grafana/alerting v0.0.0-20250123190916-7b528a0bc1d5 h1:mZezO6ccQl6AZv55f9JsPMph3eoHCofIJra2yhKzYMo=
|
||||
github.com/grafana/alerting v0.0.0-20250123190916-7b528a0bc1d5/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||
github.com/grafana/authlib v0.0.0-20250108202437-7a039176d884 h1:MSRBiQrSJZ+iowjU4Tgtq8+uC5/cs9XdtUdSWCNHrNE=
|
||||
github.com/grafana/authlib v0.0.0-20250108202437-7a039176d884/go.mod h1:x7df73G3xuSD35Xv9cjaMLyPJCgM9Z/Wj5ISouoAfiI=
|
||||
github.com/grafana/authlib/claims v0.0.0-20241202085737-df90af04f335 h1:3DHH81RJCi8Bcgn2MdBh7vgWUshmAFjZzBCVuxiQ0uk=
|
||||
|
||||
@@ -33,30 +33,36 @@ func (s *httpServiceProxy) writeErrorResponse(rw http.ResponseWriter, statusCode
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
rw.WriteHeader(statusCode)
|
||||
|
||||
// Set error response to initial error message
|
||||
errorBody := map[string]string{"error": message}
|
||||
|
||||
// Attempt to locate JSON portion in error message
|
||||
re := regexp.MustCompile(`\{.*?\}`)
|
||||
jsonPart := re.FindString(message)
|
||||
if jsonPart != "" {
|
||||
var jsonData map[string]interface{}
|
||||
if unmarshalErr := json.Unmarshal([]byte(jsonPart), &jsonData); unmarshalErr != nil {
|
||||
errorBody["error"] = fmt.Sprintf("Invalid JSON format in error message. Raw error: %s", message)
|
||||
s.logger.Error("failed to unmarshal JSON error message", "error", unmarshalErr)
|
||||
} else {
|
||||
// Extract relevant fields for a formatted error message
|
||||
errorType, _ := jsonData["error"].(string)
|
||||
errorDescription, ok := jsonData["error_description"].(string)
|
||||
if !ok {
|
||||
s.logger.Error("unable to convert error_description to string", "rawError", jsonData["error_description"])
|
||||
// Attempt to just format the error as a string
|
||||
errorDescription = fmt.Sprintf("%v", jsonData["error_description"])
|
||||
}
|
||||
if errorType == "" {
|
||||
errorType = "UnknownError"
|
||||
}
|
||||
|
||||
var jsonData map[string]interface{}
|
||||
if unmarshalErr := json.Unmarshal([]byte(jsonPart), &jsonData); unmarshalErr != nil {
|
||||
errorMsg, _ := json.Marshal(map[string]string{"error": "Invalid JSON format in error message"})
|
||||
_, err := rw.Write(errorMsg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to write HTTP response: %v", err)
|
||||
errorBody["error"] = fmt.Sprintf("%s: %s", errorType, errorDescription)
|
||||
}
|
||||
return unmarshalErr
|
||||
}
|
||||
|
||||
// Extract relevant fields for a formatted error message
|
||||
errorType, _ := jsonData["error"].(string)
|
||||
errorDescription, _ := jsonData["error_description"].(string)
|
||||
if errorType == "" {
|
||||
errorType = "UnknownError"
|
||||
}
|
||||
formattedError := fmt.Sprintf("%s: %s", errorType, errorDescription)
|
||||
|
||||
errorMsg, _ := json.Marshal(map[string]string{"error": formattedError})
|
||||
_, err := rw.Write(errorMsg)
|
||||
jsonRes, _ := json.Marshal(errorBody)
|
||||
_, err := rw.Write(jsonRes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to write HTTP response: %v", err)
|
||||
}
|
||||
@@ -117,7 +123,7 @@ func (s *Service) getDataSourceFromHTTPReq(req *http.Request) (types.DatasourceI
|
||||
}
|
||||
|
||||
func writeErrorResponse(rw http.ResponseWriter, code int, msg string) {
|
||||
rw.WriteHeader(http.StatusBadRequest)
|
||||
rw.WriteHeader(code)
|
||||
errorBody := map[string]string{
|
||||
"error": msg,
|
||||
}
|
||||
@@ -154,9 +160,11 @@ func (s *Service) handleResourceReq(subDataSource string) func(rw http.ResponseW
|
||||
req.URL.Host = serviceURL.Host
|
||||
req.URL.Scheme = serviceURL.Scheme
|
||||
|
||||
rw, err = s.executors[subDataSource].ResourceRequest(rw, req, service.HTTPClient)
|
||||
_, err = s.executors[subDataSource].ResourceRequest(rw, req, service.HTTPClient)
|
||||
if err != nil {
|
||||
writeErrorResponse(rw, http.StatusInternalServerError, fmt.Sprintf("unexpected error %v", err))
|
||||
// The ResourceRequest function should handle writing the error response
|
||||
// We log the error here to ensure it's captured
|
||||
s.logger.Error("error in resource request", "error", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ async function buildTestSceneWithLibraryPanel() {
|
||||
title: 'Panel A',
|
||||
pluginId: 'table',
|
||||
key: 'panel-12',
|
||||
$behaviors: [new LibraryPanelBehavior({ title: 'LibraryPanel A title', name: 'LibraryPanel A', uid: '111' })],
|
||||
$behaviors: [new LibraryPanelBehavior({ name: 'LibraryPanel A', uid: '111' })],
|
||||
titleItems: [new VizPanelLinks({ menu: new VizPanelLinksMenu({}) })],
|
||||
$data: new SceneDataTransformer({
|
||||
transformations: [
|
||||
|
||||
@@ -200,7 +200,6 @@ describe('PanelEditor', () => {
|
||||
|
||||
const libPanelBehavior = new LibraryPanelBehavior({
|
||||
isLoaded: true,
|
||||
title: libraryPanelModel.title,
|
||||
uid: libraryPanelModel.uid,
|
||||
name: libraryPanelModel.name,
|
||||
_loadedPanel: libraryPanelModel,
|
||||
@@ -239,7 +238,7 @@ describe('PanelEditor', () => {
|
||||
// Wait for mock api to return and update the library panel
|
||||
expect(libPanelBehavior.state._loadedPanel?.version).toBe(2);
|
||||
expect(libPanelBehavior.state.name).toBe('changed name');
|
||||
expect(libPanelBehavior.state.title).toBe('changed title');
|
||||
expect(panel.state.title).toBe('changed title');
|
||||
expect((gridItem.state.body as VizPanel).state.title).toBe('changed title');
|
||||
});
|
||||
|
||||
@@ -258,7 +257,6 @@ describe('PanelEditor', () => {
|
||||
|
||||
const libPanelBehavior = new LibraryPanelBehavior({
|
||||
isLoaded: true,
|
||||
title: libraryPanelModel.title,
|
||||
uid: libraryPanelModel.uid,
|
||||
name: libraryPanelModel.name,
|
||||
_loadedPanel: libraryPanelModel,
|
||||
|
||||
@@ -177,7 +177,6 @@ describe('PanelOptions', () => {
|
||||
|
||||
const libraryPanel = new LibraryPanelBehavior({
|
||||
isLoaded: true,
|
||||
title: libraryPanelModel.title,
|
||||
uid: libraryPanelModel.uid,
|
||||
name: libraryPanelModel.name,
|
||||
_loadedPanel: libraryPanelModel,
|
||||
|
||||
@@ -96,7 +96,7 @@ describe('AddLibraryPanelWidget', () => {
|
||||
title: 'Panel Title',
|
||||
pluginId: 'table',
|
||||
key: 'panel-1',
|
||||
$behaviors: [new LibraryPanelBehavior({ title: 'LibraryPanel A title', name: 'LibraryPanel A', uid: 'uid' })],
|
||||
$behaviors: [new LibraryPanelBehavior({ name: 'LibraryPanel A', uid: 'uid' })],
|
||||
});
|
||||
|
||||
addLibPanelDrawer = new AddLibraryPanelDrawer({ panelToReplaceRef: libPanel.getRef() });
|
||||
|
||||
@@ -408,7 +408,6 @@ describe('DashboardDatasourceBehaviour', () => {
|
||||
it('should re-run queries when library panel re-runs query', async () => {
|
||||
const libPanelBehavior = new LibraryPanelBehavior({
|
||||
isLoaded: false,
|
||||
title: 'Panel title',
|
||||
uid: 'fdcvggvfy2qdca',
|
||||
name: 'My Library Panel',
|
||||
_loadedPanel: undefined,
|
||||
@@ -469,7 +468,6 @@ describe('DashboardDatasourceBehaviour', () => {
|
||||
jest.spyOn(console, 'error').mockImplementation();
|
||||
const libPanelBehavior = new LibraryPanelBehavior({
|
||||
isLoaded: false,
|
||||
title: 'Panel title',
|
||||
uid: 'fdcvggvfy2qdca',
|
||||
name: 'My Library Panel',
|
||||
_loadedPanel: undefined,
|
||||
@@ -519,7 +517,6 @@ describe('DashboardDatasourceBehaviour', () => {
|
||||
// Simulate library panel being loaded
|
||||
libPanelBehavior.setState({
|
||||
isLoaded: true,
|
||||
title: 'Panel title',
|
||||
uid: 'fdcvggvfy2qdca',
|
||||
name: 'My Library Panel',
|
||||
_loadedPanel: undefined,
|
||||
|
||||
@@ -489,7 +489,7 @@ describe('DashboardScene', () => {
|
||||
title: 'Library Panel',
|
||||
pluginId: 'table',
|
||||
key: 'panel-4',
|
||||
$behaviors: [new LibraryPanelBehavior({ title: 'Library Panel', name: 'libraryPanel', uid: 'uid' })],
|
||||
$behaviors: [new LibraryPanelBehavior({ name: 'libraryPanel', uid: 'uid' })],
|
||||
});
|
||||
|
||||
scene.copyPanel(libVizPanel);
|
||||
@@ -544,7 +544,7 @@ describe('DashboardScene', () => {
|
||||
title: 'Library Panel',
|
||||
pluginId: 'table',
|
||||
key: 'panel-4',
|
||||
$behaviors: [new LibraryPanelBehavior({ title: 'Library Panel', name: 'libraryPanel', uid: 'uid' })],
|
||||
$behaviors: [new LibraryPanelBehavior({ name: 'libraryPanel', uid: 'uid' })],
|
||||
}),
|
||||
})
|
||||
);
|
||||
@@ -563,7 +563,7 @@ describe('DashboardScene', () => {
|
||||
const libPanel = new VizPanel({
|
||||
title: 'Panel B',
|
||||
pluginId: 'table',
|
||||
$behaviors: [new LibraryPanelBehavior({ title: 'title', name: 'lib panel', uid: 'abc', isLoaded: true })],
|
||||
$behaviors: [new LibraryPanelBehavior({ name: 'lib panel', uid: 'abc', isLoaded: true })],
|
||||
});
|
||||
|
||||
const scene = buildTestScene({
|
||||
@@ -928,7 +928,7 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
title: 'Library Panel',
|
||||
pluginId: 'table',
|
||||
key: 'panel-5',
|
||||
$behaviors: [new LibraryPanelBehavior({ title: 'Library Panel', name: 'libraryPanel', uid: 'uid' })],
|
||||
$behaviors: [new LibraryPanelBehavior({ name: 'libraryPanel', uid: 'uid' })],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
@@ -946,7 +946,7 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
title: 'Library Panel',
|
||||
pluginId: 'table',
|
||||
key: 'panel-6',
|
||||
$behaviors: [new LibraryPanelBehavior({ title: 'Library Panel', name: 'libraryPanel', uid: 'uid' })],
|
||||
$behaviors: [new LibraryPanelBehavior({ name: 'libraryPanel', uid: 'uid' })],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -167,7 +167,7 @@ describe('LibraryPanelBehavior', () => {
|
||||
});
|
||||
|
||||
async function buildTestSceneWithLibraryPanel() {
|
||||
const behavior = new LibraryPanelBehavior({ title: 'LibraryPanel A title', name: 'LibraryPanel A', uid: '111' });
|
||||
const behavior = new LibraryPanelBehavior({ name: 'LibraryPanel A', uid: '111' });
|
||||
|
||||
const vizPanel = new VizPanel({
|
||||
title: 'Panel A',
|
||||
|
||||
@@ -17,8 +17,6 @@ import { AngularDeprecation } from './angular/AngularDeprecation';
|
||||
import { DashboardGridItem } from './layout-default/DashboardGridItem';
|
||||
|
||||
export interface LibraryPanelBehaviorState extends SceneObjectState {
|
||||
// Library panels use title from dashboard JSON's panel model, not from library panel definition, hence we pass it.
|
||||
title?: string;
|
||||
uid: string;
|
||||
name: string;
|
||||
isLoaded?: boolean;
|
||||
@@ -66,7 +64,7 @@ export class LibraryPanelBehavior extends SceneObjectBase<LibraryPanelBehaviorSt
|
||||
titleItems.push(new PanelNotices());
|
||||
|
||||
const vizPanelState: VizPanelState = {
|
||||
title: libPanelModel.title,
|
||||
title: vizPanel.state.title ?? libPanelModel.title,
|
||||
options: libPanelModel.options ?? {},
|
||||
fieldConfig: libPanelModel.fieldConfig,
|
||||
pluginId: libPanelModel.type,
|
||||
@@ -88,7 +86,7 @@ export class LibraryPanelBehavior extends SceneObjectBase<LibraryPanelBehaviorSt
|
||||
vizPanel.setState(vizPanelState);
|
||||
vizPanel.changePluginType(libPanelModel.type, vizPanelState.options, vizPanelState.fieldConfig);
|
||||
|
||||
this.setState({ _loadedPanel: libPanel, isLoaded: true, name: libPanel.name, title: libPanelModel.title });
|
||||
this.setState({ _loadedPanel: libPanel, isLoaded: true, name: libPanel.name });
|
||||
|
||||
const layoutElement = vizPanel.parent!;
|
||||
|
||||
|
||||
@@ -355,7 +355,6 @@ describe('transformSceneToSaveModel', () => {
|
||||
$behaviors: [
|
||||
new LibraryPanelBehavior({
|
||||
name: 'Some lib panel panel',
|
||||
title: 'A panel',
|
||||
uid: 'lib-panel-uid',
|
||||
}),
|
||||
],
|
||||
@@ -399,7 +398,7 @@ describe('transformSceneToSaveModel', () => {
|
||||
x: 0,
|
||||
y: 0,
|
||||
});
|
||||
expect(result.title).toBe('A panel');
|
||||
expect(result.title).toBe('Panel blahh blah');
|
||||
expect(result.transformations).toBeUndefined();
|
||||
expect(result.fieldConfig).toBeUndefined();
|
||||
expect(result.options).toBeUndefined();
|
||||
@@ -851,7 +850,6 @@ describe('transformSceneToSaveModel', () => {
|
||||
$behaviors: [
|
||||
new LibraryPanelBehavior({
|
||||
name: 'Some lib panel panel',
|
||||
title: 'A panel',
|
||||
uid: 'lib-panel-uid',
|
||||
}),
|
||||
],
|
||||
@@ -865,7 +863,7 @@ describe('transformSceneToSaveModel', () => {
|
||||
|
||||
expect(result[0]).toMatchObject({
|
||||
id: 4,
|
||||
title: 'A panel',
|
||||
title: 'Panel blahh blah',
|
||||
libraryPanel: {
|
||||
name: 'Some lib panel panel',
|
||||
uid: 'lib-panel-uid',
|
||||
|
||||
@@ -186,7 +186,7 @@ export function vizPanelToPanel(
|
||||
|
||||
panel = {
|
||||
id: getPanelIdForVizPanel(vizPanel),
|
||||
title: libPanel!.state.title,
|
||||
title: vizPanel.state.title,
|
||||
gridPos: gridPos,
|
||||
libraryPanel: {
|
||||
name: libPanel!.state.name,
|
||||
|
||||
@@ -17,7 +17,6 @@ describe('PanelModelCompatibilityWrapper', () => {
|
||||
const libPanel = new LibraryPanelBehavior({
|
||||
uid: 'a',
|
||||
name: 'aa',
|
||||
title: 'a',
|
||||
});
|
||||
|
||||
panel.setState({
|
||||
|
||||
@@ -5,7 +5,6 @@ This module returns all the pipelines used in the event of documentation changes
|
||||
load(
|
||||
"scripts/drone/steps/lib.star",
|
||||
"build_docs_website_step",
|
||||
"codespell_step",
|
||||
"identify_runner_step",
|
||||
"verify_gen_cue_step",
|
||||
"yarn_install_step",
|
||||
@@ -33,7 +32,6 @@ def docs_pipelines(ver_mode, trigger):
|
||||
steps = [
|
||||
identify_runner_step(),
|
||||
yarn_install_step(),
|
||||
codespell_step(),
|
||||
lint_docs(),
|
||||
build_docs_website_step(),
|
||||
verify_gen_cue_step(),
|
||||
|
||||
@@ -753,16 +753,6 @@ def frontend_metrics_step(trigger = None):
|
||||
step = dict(step, when = trigger)
|
||||
return step
|
||||
|
||||
def codespell_step():
|
||||
return {
|
||||
"name": "codespell",
|
||||
"image": images["python"],
|
||||
"commands": [
|
||||
"pip3 install codespell",
|
||||
"codespell -I docs/.codespellignore docs/",
|
||||
],
|
||||
}
|
||||
|
||||
def grafana_server_step():
|
||||
"""Runs the grafana-server binary as a service.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ global variables
|
||||
"""
|
||||
|
||||
grabpl_version = "v3.1.1"
|
||||
golang_version = "1.23.4"
|
||||
golang_version = "1.23.5"
|
||||
|
||||
# nodejs_version should match what's in ".nvmrc", but without the v prefix.
|
||||
nodejs_version = "22.11.0"
|
||||
|
||||
Reference in New Issue
Block a user