Compare commits

..

51 Commits

Author SHA1 Message Date
Arve Knudsen
a04ef6cefc 6.7.3 cherry-picks (#23808)
* AuthProxy: Fixes bug where long username could not be cached (#22926)

(cherry picked from commit 6c9d833602)

* Server: Exit with 0 if no error (#23312)

Make grafana-server exit with 0 if no error occurred.

(cherry picked from commit 5645d74cbc)

* Dashboard: Save json should preserve folderId (#23314)

(cherry picked from commit 7e3b43eabb)

* TimeSrv: Try to parse 8 and 15 digit numbers as timestamps if parsing as date fails (#21694)

* Try to parse 8 and 15 digit numbers as timestamps if parsing as date fails

Fixes #19738

* Add tests

(cherry picked from commit c89ad9b038)

* BackendSrv: include credentials when withCredentials option is set (#23380)

The fetch() API won't send cookies or other type of credentials unless
you set the credentials init option. Some datasources like Prometheus
and Elasticsearch have `withCredentials` option in Browser access mode,
but this option is not currently getting passed in the fetch() API.

Fixes #23338.

(cherry picked from commit afd8ffde69)

* Dashlist: Fixed dashlist broken in edit mode (#23426)

(cherry picked from commit 363bf7506d)

* Admin: Fix Synced via LDAP message for non-LDAP external users (#23477)

* UserAdmin: remove Synced via LDAP message for non-LDAP users

* UserAdmin: show "Synced via <provider>" message for external users

(cherry picked from commit 4d81cec34f)

* Graphite: Fixed cannot read finally of undefiend (#23512)

(cherry picked from commit 61460ea3a2)

* Hangouts: fixes notifications for alerts with empty message (#23559)

* Hangouts: fixes notifications for alerts with empty message

* Update pkg/services/alerting/notifiers/googlechat.go

Co-Authored-By: Marcus Efraimsson <marcus.efraimsson@gmail.com>

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
(cherry picked from commit 2661054fe8)

* Variables: fixes error when setting adhoc variables values (#23580)

(cherry picked from commit 0091885b13)

* Release 6.7.3

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>

* ci-metrics-publisher.sh: Fix linting issue

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>

* TablePanel: Fix XSS issue in header column rename (backport) (#23814)

* escaping html when rendering table header alias.

* fixed tooltip.

Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>

* Security: Fix annotation popup XSS vulnerability (#23813)

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
(cherry picked from commit 3955e8cbad)

Co-authored-by: Jon McKenzie <jcmcken@gmail.com>
Co-authored-by: Peter Holmberg <peterholmberg@users.noreply.github.com>
Co-authored-by: Jesse Tan <jessetan@users.noreply.github.com>
Co-authored-by: Tuan Anh Hoang-Vu <hvtuananh@gmail.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
Co-authored-by: Alexander Zobnin <alexanderzobnin@gmail.com>
Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com>
Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
2020-04-23 12:12:53 +02:00
Sofia Papagiannaki
c5ea64c2c2 Fix CI for pushing a multi-architecture manifest (#23327) 2020-04-03 17:20:45 +03:00
sam
423a25fc32 AzureMonitor: Fix Log Analytics and Application Insights for Azure China (#21803) (#22753)
Something funky going on with GitHub - the build has passed.
2020-04-02 10:02:56 +02:00
Torkel Ödegaard
86241d8bff Revert "grafana/data: PanelTypeChangedHandler API update to use PanelModel instead of panel options object [BREAKING] (#22754)"
This reverts commit 16f3fe7e15.
2020-04-02 10:01:59 +02:00
Torkel Ödegaard
670ee15dbd Bumped version 2020-04-01 18:29:54 +02:00
Torkel Ödegaard
9abfbf18e0 Snapshots: Sanitize orignal url (#23254)
(cherry picked from commit fb114a7524)
2020-04-01 18:28:50 +02:00
Torkel Ödegaard
882ed637c1 Plugins: Expose promiseToDigest (#23249)
(cherry picked from commit ccb8187ccd)
2020-04-01 18:28:49 +02:00
Torkel Ödegaard
676972e798 Variables: Do not update variable from url when value is the same (#23220)
(cherry picked from commit 49d2910e39)
2020-04-01 18:28:49 +02:00
Dominik Prokop
3be4685589 DashboardSave: Add new dashboard check (#23104)
(cherry picked from commit 046d9c1af4)
2020-04-01 18:28:49 +02:00
Torkel Ödegaard
aa227c5c20 Fix: reverted back to import * as module instead of using namespaces (#23069)
* Removed namespace declaration to prevent issues with external plugins.

* fixed imports and tests.

(cherry picked from commit f75387bd14)
2020-04-01 18:27:46 +02:00
Torkel Ödegaard
ba26ac343b BackendSrv: Adds config to response to fix external plugins that use this (#23032)
* BackendSrv: Added config to response

* QueryInspector: Removing config from showing up

* Replace config with request and make it be the unmodified params sent in

(cherry picked from commit 40d195e4a7)
2020-04-01 18:20:47 +02:00
Marcus Andersson
27a8112e06 DataLinks: make sure we use the correct datapoint when dataset contains null value. (#22981)
* Fix to make sure we have the correct dataIndex when using data links.

* fixed strict null errors.

* decreased number of errors.

(cherry picked from commit 41bc1aa3ae)
2020-04-01 18:20:36 +02:00
Steven Vachon
a0a9ca220c Fix mysterious Babel plugin errors (#22974)
(cherry picked from commit d8b346f441)
2020-04-01 18:18:51 +02:00
Torkel Ödegaard
0287819e36 Select: Fixed select text positition (#22952)
(cherry picked from commit 89203136ec)
2020-04-01 17:55:18 +02:00
Dominik Prokop
16f3fe7e15 grafana/data: PanelTypeChangedHandler API update to use PanelModel instead of panel options object [BREAKING] (#22754)
This changes PanelModel's API to support PanelModel API updates when changing panel type. Primary useful when changing panel type between Angular and React panels, as other migrations can be handled via DashboardMigrator.

API change: https://github.com/grafana/grafana/pull/22754/files#diff-d9e3f91dc7d5697f6d85ada008003b4b

(cherry picked from commit 1256d9e78d)
2020-04-01 17:55:17 +02:00
Robby Milo
ca6d08d5cb Docs: Fix Broken Link (#22894)
(cherry picked from commit a61af9ed1d)
2020-03-20 14:13:09 +01:00
Leonard Gram
d01bdb517d release 6.7.1 2020-03-20 14:13:09 +01:00
Torkel Ödegaard
63dfdb7066 Panels: Fixed size issue with panels when existing panel edit mode (#22912)
(cherry picked from commit 8e131384e3)
2020-03-20 14:13:09 +01:00
Torkel Ödegaard
e95667fffb Azure: Fixed dropdowns not showing current value (#22914)
(cherry picked from commit d16211b782)
2020-03-20 14:13:09 +01:00
Hugo Häggmark
c08b901664 BackendSrv: only add content-type on POST, PUT requests (#22910)
* BackendSrv: only add content-type on POST, PUT requests
Fixes #22869

* Tests: imports polyfill for Headers

(cherry picked from commit 8d5c6053db)
2020-03-20 14:13:09 +01:00
Cyril Tovena
7cd6fef466 Check if the datasource is of type loki using meta.id instead of name. (#22877)
Signed-off-by: Cyril Tovena <cyril.tovena@gmail.com>
(cherry picked from commit ec9167e972)
2020-03-20 14:13:09 +01:00
Arve Knudsen
1b4f93b88c CircleCI: Pin grabpl to 0.1.0 (#22904) 2020-03-19 19:06:28 +01:00
Arve Knudsen
c4656a885d Release version 6.7.0
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
2020-03-19 12:27:02 +01:00
Ivana Huckova
818a2f3d64 Design tweaks (#22886)
(cherry picked from commit 8ba75e77b1)
2020-03-19 12:27:02 +01:00
Jess
7f52e023b5 Rich history UX fixes (#22783)
* Initial commit

* Visualised renamed or deleted  datasources as well, if they have queries

* Pass ds image to card and information if the datasource was removed/renamed

* Set up card with datasource info and change run query

* Style comment, run button

* Fix button naming

* Remember last filters

* Update public/app/core/store.ts

* Update public/app/features/explore/RichHistory/RichHistory.tsx

* Update comments

* Rename datasource to data source

* Add test coverage, fix naming

* Remove unused styles, add feedback info

Co-authored-by: Ivana <ivana.huckova@gmail.com>
Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com>
(cherry picked from commit db85c3e7b9)
2020-03-19 12:27:02 +01:00
Daniel Lee
962a06545a AzureMonitor: support workspaces function for template variables (#22882)
* azuremonitor: adds support for workspaces query macro...

...for Azure Logs template variable queries

* docs: azure logs workspaces templating function

* Update docs/sources/features/datasources/azuremonitor.md

Co-Authored-By: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* docs: convert list into table

* docs: fixes prettier formatting problem

Prettier adds a slash before dollar signs in markdown. Disabling it
for this table with a prettier comment.

https://prettier.io/docs/en/ignore.html

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>
(cherry picked from commit 3b9a4e6444)
2020-03-19 12:27:02 +01:00
Arve Knudsen
79aeeaa10a SQLStore: Add migration for adding index on annotation.alert_id (#22876)
(cherry picked from commit bb05989e43)
2020-03-19 12:27:02 +01:00
Carl Bergquist
ea483c0ce1 Plugins: Return jsondetails as an json object instead of raw json on datasource healthchecks. (#22859)
(cherry picked from commit 579abad9cc)
2020-03-19 12:27:02 +01:00
Marcus Efraimsson
3e88197f96 Backend plugins: Exclude plugin metrics in Grafana's metrics endpoint (#22857)
Excludes backend plugin metrics in Grafana's metrics endpoint
Adds /api/:pluginId/metrics endpoint for retrieving metrics
from backend plugin as Prometheus text-based exposition format.

Fixes #22814

(cherry picked from commit 60e3437fc1)
2020-03-19 12:27:02 +01:00
Torkel Ödegaard
66df54db80 Graphite: Fixed issue with query editor and next select metric now showing after selecting metric node (#22856)
* Graphite: Fixed digest issue in graphite query editor

* Fixed unit test

* Updated

(cherry picked from commit aa4ed76a00)
2020-03-19 12:27:02 +01:00
Erik Sundell
e4b4480064 Stackdriver: Fix GCE auth bug when creating new data source (#22836)
* Fix test datasource for gce auth

* Cache gce default project locally

* Await gce default project call

* Remove reload functionality

* Fix build problem

(cherry picked from commit 1cd7ce24c7)
2020-03-19 12:27:02 +01:00
Marcus Efraimsson
4e4f69b5f6 @grafana/runtime: Add cancellation of queries to DataSourceWithBackend (#22818)
(cherry picked from commit eb96a8fcc8)
2020-03-19 12:27:02 +01:00
Ivana Huckova
a4b7209e39 Rich history: Test coverage (#22852)
* Add unit test coverage

* Add tests to util/richHistory

* Remove unused import

* Remove redundant tests

* Fix tests for components

* Test saving to local storage

* Add boxshadow to container

* Revert "Add boxshadow to container"

This reverts commit 5ca2e850e4.

* Fix failing tests after merging master

* Fix imports, aria-labels

* Remove console.log

(cherry picked from commit 8edf8e3982)
2020-03-19 12:27:02 +01:00
Carl Bergquist
6c001d9c09 Datasource config was not mapped for datasource healthcheck (#22848)
closes #22825

(cherry picked from commit 0a094a7319)
2020-03-19 12:27:02 +01:00
Carl Bergquist
312600aa2c upgrades plugin sdk to 0.30.0 (#22846)
ref grafana/grafana-plugin-sdk-go#94
ref grafana/grafana-plugin-sdk-go#70

(cherry picked from commit b0407b3578)
2020-03-19 12:27:02 +01:00
Ivana Huckova
26d701dcf9 Rich History: UX adjustments and fixes (#22729)
* Initial commit

* Fix spelling of data sources

* Display sorting value for starred and query tab

* Fix handle color for light theme

* Add close button and fix animation

* Remove toggling of tabs

* Stop event propagation when clicking on comment buttons

* Add title for card functionality

* Remove interpolation for easier searchability of variables

* Improve syncing of comments and starred

* Add modal to check if user wants to permanently delete history

* Fix the height of the query card buttons

* Adjust slider's width based on drawer width

* Add spacing between slider and legend

* Semantic variable naming

* Fix disabled button when live tailing

* Add error handling

* Remove unused imports

* Fix starring, remove useEffect

* Remove emiting of appEvents.alertError in store

* Remove unused imports

(cherry picked from commit 544690060a)
2020-03-19 12:27:02 +01:00
Dominik Prokop
e347b62cee TablePanel: Enable new units picker (#22833)
(cherry picked from commit 58298919c8)
2020-03-19 12:27:02 +01:00
Alex Khomenko
36232857df Fix dashboard picker's props (#22815)
(cherry picked from commit 2fac834413)
2020-03-19 12:27:02 +01:00
Alex Khomenko
9d605bdd04 Grafana-UI: Add invalid state to Forms.Textarea (#22775)
(cherry picked from commit cd50da3dbe)
2020-03-19 12:27:02 +01:00
Torkel Ödegaard
4d235b978e SaveDashboard: Updated modal design/layout a bit (#22810)
(cherry picked from commit 46165a7f7b)
2020-03-19 12:27:02 +01:00
Torkel Ödegaard
6575c9cb6e Forms: Fix input suffix position (#22780)
* Forms: Fix input suffix position

* Update

(cherry picked from commit ab0238eced)
2020-03-19 12:27:02 +01:00
Torkel Ödegaard
0ad27a6596 AngularPanels: Fixed inner height calculation (#22796)
(cherry picked from commit f78501f3b5)
2020-03-19 12:27:02 +01:00
Hugo Häggmark
a0c6afa0a5 Fix: fixes issue with headers property with different casing (#22778)
Fixes #22756

(cherry picked from commit b30f4c7bb0)
2020-03-19 12:27:02 +01:00
Ryan McKinley
3d0bc141c7 DataSourceWithBackend: use /health endpoint for test (#22789)
(cherry picked from commit 8b067a5fe0)
2020-03-19 12:27:02 +01:00
Ryan McKinley
ed307897e7 Chore: remove expressions flag and allow (#22764)
(cherry picked from commit c65db9bf25)
2020-03-19 12:27:02 +01:00
Alex Khomenko
1d63f57caf Core: Pass the rest of to props to Select (#22776)
* Pass the rest of to props to Select

* Remove log

(cherry picked from commit 451c95808d)
2020-03-19 12:27:02 +01:00
Carl Bergquist
e00f393a17 Add support for sending health check to datasource plugins. (#22771)
closes #21519
ref grafana/grafana-plugin-sdk-go#93

(cherry picked from commit ebc9549cbc)
2020-03-19 12:27:02 +01:00
Marcus Andersson
277e00aaed Datasource: making sure we are having the same data field order when using mixed data sources. (#22718)
* changed so data query response always it returned in the correct order when using mixed data sources.

* refactored the code to make it a bit simpler and not failing the tests.

* changed to simple array type.

(cherry picked from commit f44c0f0643)
2020-03-19 12:27:02 +01:00
Dominik Prokop
ba6104190e DashboardSave: Autofocus save dashboard form input (#22748)
(cherry picked from commit b441b73345)
2020-03-19 12:27:02 +01:00
Steven Vachon
eaaca91f25 @grafana/e2e: cherry picked 4fecf5a7a6 (#22739) 2020-03-12 08:51:05 +01:00
Arve Knudsen
a551cd2470 Release version 6.7.0-beta1 (#22727) 2020-03-11 16:30:55 +01:00
5916 changed files with 1285671 additions and 138891 deletions

View File

@@ -1,19 +1,19 @@
[run]
init_cmds = [
["go", "run", "build.go", "-dev", "build-cli"],
["go", "run", "build.go", "-dev", "build-server"],
["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"]
["go", "run", "-mod=vendor", "build.go", "-dev", "build-cli"],
["go", "run", "-mod=vendor", "build.go", "-dev", "build-server"],
["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"]
]
watch_all = true
follow_symlinks = true
watch_dirs = [
"$WORKDIR/pkg",
"$WORKDIR/public/views",
"$WORKDIR/conf",
"$WORKDIR/pkg",
"$WORKDIR/public/views",
"$WORKDIR/conf",
]
watch_exts = [".go", ".ini", ".toml", ".template.html"]
build_delay = 1500
cmds = [
["go", "run", "build.go", "-dev", "build-server"],
["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"]
["go", "run", "-mod=vendor", "build.go", "-dev", "build-server"],
["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"]
]

File diff suppressed because it is too large Load Diff

4
.github/CODEOWNERS vendored
View File

@@ -14,10 +14,8 @@
# Documentation owner: Diana Payton
/docs/ @oddlittlebird
/contribute/ @oddlittlebird @marcusolsson
# @grafana/ui component documentation
*.mdx @marcusolsson @jessover9000
# Backend code
*.go @grafana/backend-platform
go.mod @grafana/backend-platform
go.sum @grafana/backend-platform
go.sum @grafana/backend-platform

17
.gitignore vendored
View File

@@ -11,18 +11,13 @@ awsconfig
/public/views/error.html
/emails/dist
/reports
/e2e/tmp
.yarnrc
.yarn/
vendor/
# Enterprise emails
/emails/templates/enterprise_*
/public/emails/enterprise_*
# Enterprise devenv
/devenv/docker/blocks/grafana-enterprise
/tmp
tools/phantomjs/phantomjs
tools/phantomjs/phantomjs.exe
@@ -88,8 +83,6 @@ debug.test
/devenv/bulk-dashboards/*.json
/devenv/bulk_alerting_dashboards/*.json
/devenv/datasources_bulk.yaml
/devenv/bulk_alerting_dashboards/bulk_alerting_datasources.yaml
/scripts/build/release_publisher/release_publisher
*.patch
@@ -110,10 +103,6 @@ compilation-stats.json
/packages/grafana-e2e/cypress/screenshots
/packages/grafana-e2e/cypress/videos
/packages/grafana-e2e/cypress/logs
/e2e/server.log
/e2e/**/screenshots
!/e2e/**/screenshots/expeced/*
/e2e/**/videos/*
# report dumping the whole system env
/report.*.json
/public/e2e-test/screenShots/theOutput
/public/e2e-tests/screenShots/theOutput/*.png
/public/e2e-tests/videos

View File

@@ -1,3 +0,0 @@
module.exports = {
...require('@grafana/toolkit/src/config/prettier.plugin.config.json'),
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,12 @@
FROM node:12.16.3-alpine3.11 as js-builder
WORKDIR /usr/src/app/
COPY package.json yarn.lock ./
COPY packages packages
RUN yarn install --pure-lockfile --no-progress
COPY Gruntfile.js tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js ./
COPY public public
COPY tools tools
COPY scripts scripts
COPY emails emails
ENV NODE_ENV production
RUN ./node_modules/.bin/grunt build
FROM golang:1.14.2-alpine3.11 as go-builder
# Golang build container
FROM golang:1.13.4-alpine
RUN apk add --no-cache gcc g++
WORKDIR $GOPATH/src/github.com/grafana/grafana
COPY go.mod go.sum ./
COPY vendor vendor
RUN go mod verify
@@ -31,8 +15,36 @@ COPY build.go package.json ./
RUN go run build.go build
# Final stage
FROM alpine:3.11
# Node build container
FROM node:12.13.0-alpine
# PhantomJS
RUN apk add --no-cache curl &&\
cd /tmp && curl -Ls https://github.com/dustinblackman/phantomized/releases/download/2.1.1/dockerized-phantomjs.tar.gz | tar xz &&\
cp -R lib lib64 / &&\
cp -R usr/lib/x86_64-linux-gnu /usr/lib &&\
cp -R usr/share /usr/share &&\
cp -R etc/fonts /etc &&\
curl -k -Ls https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 | tar -jxf - &&\
cp phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs
WORKDIR /usr/src/app/
COPY package.json yarn.lock ./
COPY packages packages
RUN yarn install --pure-lockfile --no-progress
COPY Gruntfile.js tsconfig.json .eslintrc .editorconfig .browserslistrc ./
COPY public public
COPY scripts scripts
COPY emails emails
ENV NODE_ENV production
RUN ./node_modules/.bin/grunt build
# Final container
FROM alpine:3.10
LABEL maintainer="Grafana team <hello@grafana.com>"
@@ -50,7 +62,7 @@ ENV PATH="/usr/share/grafana/bin:$PATH" \
WORKDIR $GF_PATHS_HOME
RUN apk add --no-cache ca-certificates bash tzdata && \
apk add --no-cache --upgrade openssl musl-utils
apk add --no-cache --upgrade --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main openssl musl-utils
COPY conf ./conf
@@ -68,9 +80,18 @@ RUN mkdir -p "$GF_PATHS_HOME/.aws" && \
chown -R grafana:grafana "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \
chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING"
COPY --from=go-builder /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-server /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-cli ./bin/
COPY --from=js-builder /usr/src/app/public ./public
COPY --from=js-builder /usr/src/app/tools ./tools
# PhantomJS
COPY --from=1 /tmp/lib /lib
COPY --from=1 /tmp/lib64 /lib64
COPY --from=1 /tmp/usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu
COPY --from=1 /tmp/usr/share /usr/share
COPY --from=1 /tmp/etc/fonts /etc/fonts
COPY --from=1 /usr/local/bin/phantomjs /usr/local/bin
COPY --from=0 /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-server /go/src/github.com/grafana/grafana/bin/linux-amd64/grafana-cli ./bin/
COPY --from=1 /usr/src/app/public ./public
COPY --from=1 /usr/src/app/tools ./tools
COPY tools/phantomjs/render.js ./tools/phantomjs/render.js
EXPOSE 3000

View File

@@ -1,26 +1,9 @@
FROM node:12.16.3-slim AS js-builder
WORKDIR /usr/src/app/
COPY package.json yarn.lock ./
COPY packages packages
RUN yarn install --pure-lockfile
COPY Gruntfile.js tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js ./
COPY public public
COPY tools tools
COPY scripts scripts
COPY emails emails
ENV NODE_ENV production
RUN ./node_modules/.bin/grunt build
FROM golang:1.14.2 AS go-builder
FROM golang:1.13.4 AS go-builder
WORKDIR /src/grafana
COPY go.mod go.sum ./
COPY vendor vendor/
RUN go mod verify
@@ -29,7 +12,29 @@ COPY pkg pkg/
RUN go run build.go build
FROM ubuntu:20.04
FROM node:12.13 AS js-builder
# PhantomJS
RUN apt-get update && apt-get install -y curl &&\
curl -L https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 | tar xj &&\
cp phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs
WORKDIR /usr/src/app/
COPY package.json yarn.lock ./
COPY packages packages
RUN yarn install --pure-lockfile
COPY Gruntfile.js tsconfig.json .eslintrc .editorconfig .browserslistrc ./
COPY public public
COPY scripts scripts
COPY emails emails
ENV NODE_ENV production
RUN ./node_modules/.bin/grunt build
FROM ubuntu:19.10
LABEL maintainer="Grafana team <hello@grafana.com>"
EXPOSE 3000
@@ -49,8 +54,8 @@ WORKDIR $GF_PATHS_HOME
COPY conf conf
# curl should be part of the image
RUN apt-get update && apt-get upgrade -y && apt-get install -y ca-certificates curl
# We need font libs for phantomjs, and curl should be part of the image
RUN apt-get update && apt-get upgrade -y && apt-get install -y ca-certificates libfontconfig1 curl
RUN mkdir -p "$GF_PATHS_HOME/.aws" && \
addgroup --system --gid $GF_GID grafana && \
@@ -66,11 +71,14 @@ RUN mkdir -p "$GF_PATHS_HOME/.aws" && \
chown -R grafana:grafana "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \
chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING"
# PhantomJS
COPY --from=js-builder /usr/local/bin/phantomjs /usr/local/bin/
COPY --from=go-builder /src/grafana/bin/linux-amd64/grafana-server /src/grafana/bin/linux-amd64/grafana-cli bin/
COPY --from=js-builder /usr/src/app/public public
COPY --from=js-builder /usr/src/app/tools tools
COPY tools/phantomjs/render.js tools/phantomjs/
COPY packaging/docker/run.sh /
USER grafana

View File

@@ -35,6 +35,7 @@ module.exports = function (grunt) {
config.libc = grunt.option('libc');
}
config.phjs = grunt.option('phjsToRelease');
config.pkg.version = grunt.option('pkgVer') || config.pkg.version;
console.log('Version', config.pkg.version);

View File

@@ -4,7 +4,7 @@
-include local/Makefile
.PHONY: all deps-go deps-js deps build-go build-server build-cli build-js build build-docker-dev build-docker-full lint-go gosec revive golangci-lint go-vet test-go test-js test run run-frontend clean devenv devenv-down revive-alerting protobuf help
.PHONY: all deps-go deps-js deps build-go build-server build-cli build-js build build-docker-dev build-docker-full lint-go gosec revive golangci-lint go-vet test-go test-js test run run-frontend clean devenv devenv-down revive-alerting help
GO = GO111MODULE=on go
GO_FILES ?= ./pkg/...
@@ -84,10 +84,7 @@ revive-alerting: scripts/go/bin/revive
@echo "lint alerting via revive"
@scripts/go/bin/revive \
-formatter stylish \
-config ./scripts/go/configs/revive-strict.toml \
./pkg/services/alerting/... \
./pkg/services/provisioning/datasources/... \
./pkg/services/provisioning/dashboards/...
./pkg/services/alerting/...
scripts/go/bin/golangci-lint: scripts/go/go.mod
@cd scripts/go; \
@@ -161,16 +158,6 @@ devenv-down: ## Stop optional services.
##@ Helpers
# We separate the protobuf generation because most development tasks on
# Grafana do not involve changing protobuf files and protoc is not a
# go-gettable dependency and so getting it installed can be inconvenient.
#
# If you are working on changes to protobuf interfaces you may either use
# this target or run the individual scripts below directly.
protobuf: ## Compile protobuf definitions
bash scripts/protobuf-check.sh
bash pkg/plugins/backendplugin/pluginextensionv2/generate.sh
clean: ## Clean up intermediate build artifacts.
@echo "cleaning"
rm -rf node_modules

View File

@@ -15,15 +15,6 @@ Grafana allows you to query, visualize, alert on and understand your metrics no
- **Alerting:** Visually define alert rules for your most important metrics. Grafana will continuously evaluate and send notifications to systems like Slack, PagerDuty, VictorOps, OpsGenie.
- **Mixed Data Sources:** Mix different data sources in the same graph! You can specify a data source on a per-query basis. This works for even custom datasources.
### Grafana 7.0 and GrafanaCONline
- Grafana 7.0 Beta is [available for download](https://grafana.com/grafana/download).
- Read [what's is new](https://grafana.com/docs/grafana/latest/guides/whats-new-in-v7-0/).
Want to learn more about Grafana 7 and more? Sign up for our online conference!
[![GrafanaCONline](public/img/grafanaconline.png)](https://grafana.com/about/events/grafanacon/2020/?source=grafana-readme)
## Get started
- [Get Grafana](https://grafana.com/get)

View File

@@ -20,6 +20,8 @@ Upgrading Go or Node.js requires making changes in many different files. See bel
The Grafana project uses [Go modules](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more) to manage dependencies on external packages. This requires a working Go environment with version 1.11 or greater installed.
All dependencies are vendored in the `vendor/` directory.
_Note:_ Since most developers of Grafana still use the `GOPATH` we need to specify `GO111MODULE=on` to make `go mod` and `got get` work as intended. If you have setup Grafana outside of the `GOPATH` on your machine you can skip `GO111MODULE=on` when running the commands below.
To add or update a new dependency, use the `go get` command:
@@ -33,14 +35,16 @@ GO111MODULE=on go get example.com/some/module/pkg
GO111MODULE=on go get example.com/some/module/pkg@vX.Y.Z
```
Tidy up the `go.mod` and `go.sum` files:
Tidy up the `go.mod` and `go.sum` files and copy the new/updated dependency to the `vendor/` directory:
```bash
# The GO111MODULE variable can be omitted when the code isn't located in GOPATH.
GO111MODULE=on go mod tidy
GO111MODULE=on go mod vendor
```
You have to commit the changes to `go.mod` and `go.sum` before submitting the pull request.
You have to commit the changes to `go.mod`, `go.sum` and the `vendor/` directory before submitting the pull request.
## Node.js dependencies

View File

@@ -23,10 +23,6 @@
"extractorMessageReporting": {
"default": {
"logLevel": "warning"
},
"ae-internal-missing-underscore": {
"logLevel": "none",
"addToApiReportFile": false
}
},
"tsdocMessageReporting": {

View File

@@ -40,6 +40,7 @@ var (
linuxPackageVersion string = "v1"
linuxPackageIteration string = ""
race bool
phjsToRelease string
workingDir string
includeBuildId bool = true
buildId string = "0"
@@ -51,6 +52,7 @@ var (
skipRpmGen bool = false
skipDebGen bool = false
printGenVersion bool = false
modVendor bool = true
)
func main() {
@@ -67,7 +69,9 @@ func main() {
flag.StringVar(&libc, "libc", "", "LIBC")
flag.BoolVar(&cgo, "cgo-enabled", cgo, "Enable cgo")
flag.StringVar(&pkgArch, "pkg-arch", "", "PKG ARCH")
flag.StringVar(&phjsToRelease, "phjs", "", "PhantomJS binary")
flag.BoolVar(&race, "race", race, "Use race detector")
flag.BoolVar(&modVendor, "modVendor", modVendor, "Go modules use vendor folder")
flag.BoolVar(&includeBuildId, "includeBuildId", includeBuildId, "IncludeBuildId in package name")
flag.BoolVar(&enterprise, "enterprise", enterprise, "Build enterprise version of Grafana")
flag.StringVar(&buildIdRaw, "buildId", "0", "Build ID from CI system")
@@ -385,6 +389,7 @@ func createPackage(options linuxPackageOptions) {
if enterprise {
description += " Enterprise"
}
args = append(args, "--vendor", description)
if !enterprise {
args = append(args, "--license", "\"Apache 2.0\"")
@@ -454,6 +459,9 @@ func gruntBuildArg(task string) []string {
if libc != "" {
args = append(args, fmt.Sprintf("--libc=%s", libc))
}
if phjsToRelease != "" {
args = append(args, fmt.Sprintf("--phjsToRelease=%v", phjsToRelease))
}
if enterprise {
args = append(args, "--enterprise")
}
@@ -501,6 +509,9 @@ func build(binaryName, pkg string, tags []string) {
if race {
args = append(args, "-race")
}
if modVendor {
args = append(args, "-mod=vendor")
}
args = append(args, "-o", binary)
args = append(args, pkg)

View File

@@ -230,9 +230,9 @@ snapshot_remove_expired = true
# Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1
versions_to_keep = 20
# Minimum dashboard refresh interval. When set, this will restrict users to set the refresh interval of a dashboard lower than given interval. Per default this is 5 seconds.
# Minimum dashboard refresh interval. When set, this will restrict users to set the refresh interval of a dashboard lower than given interval. Per default this is not set/unrestricted.
# The interval string is a possibly signed sequence of decimal numbers, followed by a unit suffix (ms, s, m, h, d), e.g. 30s or 1m.
min_refresh_interval = 5s
min_refresh_interval =
#################################### Users ###############################
[users]
@@ -298,9 +298,6 @@ signout_redirect_url =
# This setting is ignored if multiple OAuth providers are configured.
oauth_auto_login = false
# OAuth state max age cookie duration. Defaults to 60 seconds.
oauth_state_cookie_max_age = 60
# limit of api_key seconds to live before expiration
api_key_max_seconds_to_live = -1
@@ -386,21 +383,6 @@ token_url = https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
allowed_domains =
allowed_groups =
#################################### Okta OAuth #######################
[auth.okta]
name = Okta
enabled = false
allow_sign_up = true
client_id = some_id
client_secret = some_secret
scopes = openid profile email groups
auth_url = https://<tenant-id>.okta.com/oauth2/v1/authorize
token_url = https://<tenant-id>.okta.com/oauth2/v1/token
api_url = https://<tenant-id>.okta.com/oauth2/v1/userinfo
allowed_domains =
allowed_groups =
role_attribute_path =
#################################### Generic OAuth #######################
[auth.generic_oauth]
name = OAuth
@@ -423,6 +405,47 @@ tls_client_cert =
tls_client_key =
tls_client_ca =
#################################### SAML Auth ###########################
[auth.saml] # Enterprise only
# Defaults to false. If true, the feature is enabled
enabled = false
# Base64-encoded public X.509 certificate. Used to sign requests to the IdP
certificate =
# Path to the public X.509 certificate. Used to sign requests to the IdP
certificate_path =
# Base64-encoded private key. Used to decrypt assertions from the IdP
private_key =
# Path to the private key. Used to decrypt assertions from the IdP
private_key_path =
# Base64-encoded IdP SAML metadata XML. Used to verify and obtain binding locations from the IdP
idp_metadata =
# Path to the SAML metadata XML. Used to verify and obtain binding locations from the IdP
idp_metadata_path =
# URL to fetch SAML IdP metadata. Used to verify and obtain binding locations from the IdP
idp_metadata_url =
# Duration, since the IdP issued a response and the SP is allowed to process it. Defaults to 90 seconds
max_issue_delay = 90s
# Duration, for how long the SP's metadata should be valid. Defaults to 48 hours
metadata_valid_duration = 48h
# Friendly name or name of the attribute within the SAML assertion to use as the user's name
assertion_attribute_name = displayName
# Friendly name or name of the attribute within the SAML assertion to use as the user's login handle
assertion_attribute_login = mail
# Friendly name or name of the attribute within the SAML assertion to use as the user's email
assertion_attribute_email = mail
#################################### Basic Auth ##########################
[auth.basic]
enabled = true
@@ -683,9 +706,6 @@ container_name =
server_url =
# If the remote HTTP image renderer service runs on a different server than the Grafana server you may have to configure this to a URL where Grafana is reachable, e.g. http://grafana.domain/.
callback_url =
# Concurrent render request limit affects when the /render HTTP endpoint is used. Rendering many images at the same time can overload the server,
# which this setting can help protect against by only allowing a certain amount of concurrent requests.
concurrent_render_request_limit = 30
[panels]
# here for to support old env variables, can remove after a few months
@@ -695,68 +715,6 @@ disable_sanitize_html = false
[plugins]
enable_alpha = false
app_tls_skip_verify_insecure = false
# Enter a comma-separated list of plugin identifiers to identify plugins that are allowed to be loaded even if they lack a valid signature.
allow_loading_unsigned_plugins =
#################################### Grafana Image Renderer Plugin ##########################
[plugin.grafana-image-renderer]
# Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert.
# See ICUs metaZones.txt (https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt) for a list of supported
# timezone IDs. Fallbacks to TZ environment variable if not set.
rendering_timezone =
# Instruct headless browser instance to use a default language when not provided by Grafana, e.g. when rendering panel image of alert.
# Please refer to the HTTP header Accept-Language to understand how to format this value, e.g. 'fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5'.
rendering_language =
# Instruct headless browser instance to use a default device scale factor when not provided by Grafana, e.g. when rendering panel image of alert.
# Default is 1. Using a higher value will produce more detailed images (higher DPI), but will require more disk space to store an image.
rendering_viewport_device_scale_factor =
# Instruct headless browser instance whether to ignore HTTPS errors during navigation. Per default HTTPS errors are not ignored. Due to
# the security risk it's not recommended to ignore HTTPS errors.
rendering_ignore_https_errors =
# Instruct headless browser instance whether to capture and log verbose information when rendering an image. Default is false and will
# only capture and log error messages. When enabled, debug messages are captured and logged as well.
# For the verbose information to be included in the Grafana server log you have to adjust the rendering log level to debug, configure
# [log].filter = rendering:debug.
rendering_verbose_logging =
# Instruct headless browser instance whether to output its debug and error messages into running process of remote rendering service.
# Default is false. This can be useful to enable (true) when troubleshooting.
rendering_dumpio =
# Additional arguments to pass to the headless browser instance. Default is --no-sandbox. The list of Chromium flags can be found
# here (https://peter.sh/experiments/chromium-command-line-switches/). Multiple arguments is separated with comma-character.
rendering_args =
# You can configure the plugin to use a different browser binary instead of the pre-packaged version of Chromium.
# Please note that this is not recommended, since you may encounter problems if the installed version of Chrome/Chromium is not
# compatible with the plugin.
rendering_chrome_bin =
# Instruct how headless browser instances are created. Default is 'default' and will create a new browser instance on each request.
# Mode 'clustered' will make sure that only a maximum of browsers/incognito pages can execute concurrently.
# Mode 'reusable' will have one browser instance and will create a new incognito page on each request.
rendering_mode =
# When rendering_mode = clustered you can instruct how many browsers or incognito pages can execute concurrently. Default is 'browser'
# and will cluster using browser instances.
# Mode 'context' will cluster using incognito pages.
rendering_clustering_mode =
# When rendering_mode = clustered you can define maximum number of browser instances/incognito pages that can execute concurrently..
rendering_clustering_max_concurrency =
# Limit the maxiumum viewport width, height and device scale factor that can be requested.
rendering_viewport_max_width =
rendering_viewport_max_height =
rendering_viewport_max_device_scale_factor =
# Change the listening host and port of the gRPC server. Default host is 127.0.0.1 and default port is 0 and will automatically assign
# a port not in use.
grpc_host =
grpc_port =
[enterprise]
license_path =

View File

@@ -229,9 +229,9 @@
# Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1
;versions_to_keep = 20
# Minimum dashboard refresh interval. When set, this will restrict users to set the refresh interval of a dashboard lower than given interval. Per default this is 5 seconds.
# Minimum dashboard refresh interval. When set, this will restrict users to set the refresh interval of a dashboard lower than given interval. Per default this is not set/unrestricted.
# The interval string is a possibly signed sequence of decimal numbers, followed by a unit suffix (ms, s, m, h, d), e.g. 30s or 1m.
;min_refresh_interval = 5s
;min_refresh_interval =
#################################### Users ###############################
[users]
@@ -297,9 +297,6 @@
# This setting is ignored if multiple OAuth providers are configured.
;oauth_auto_login = false
# OAuth state max age cookie duration. Defaults to 60 seconds.
;oauth_state_cookie_max_age = 60
# limit of api_key seconds to live before expiration
;api_key_max_seconds_to_live = -1
@@ -376,21 +373,6 @@
;allowed_domains =
;allowed_groups =
#################################### Okta OAuth #######################
[auth.okta]
;name = Okta
;enabled = false
;allow_sign_up = true
;client_id = some_id
;client_secret = some_secret
;scopes = openid profile email groups
;auth_url = https://<tenant-id>.okta.com/oauth2/v1/authorize
;token_url = https://<tenant-id>.okta.com/oauth2/v1/token
;api_url = https://<tenant-id>.okta.com/oauth2/v1/userinfo
;allowed_domains =
;allowed_groups =
;role_attribute_path =
#################################### Generic OAuth ##########################
[auth.generic_oauth]
;enabled = false
@@ -413,6 +395,47 @@
;tls_client_key =
;tls_client_ca =
#################################### SAML Auth ###########################
[auth.saml] # Enterprise only
# Defaults to false. If true, the feature is enabled.
;enabled = false
# Base64-encoded public X.509 certificate. Used to sign requests to the IdP
;certificate =
# Path to the public X.509 certificate. Used to sign requests to the IdP
;certificate_path =
# Base64-encoded private key. Used to decrypt assertions from the IdP
;private_key =
;# Path to the private key. Used to decrypt assertions from the IdP
;private_key_path =
# Base64-encoded IdP SAML metadata XML. Used to verify and obtain binding locations from the IdP
;idp_metadata =
# Path to the SAML metadata XML. Used to verify and obtain binding locations from the IdP
;idp_metadata_path =
# URL to fetch SAML IdP metadata. Used to verify and obtain binding locations from the IdP
;idp_metadata_url =
# Duration, since the IdP issued a response and the SP is allowed to process it. Defaults to 90 seconds.
;max_issue_delay = 90s
# Duration, for how long the SP's metadata should be valid. Defaults to 48 hours.
;metadata_valid_duration = 48h
# Friendly name or name of the attribute within the SAML assertion to use as the user's name
;assertion_attribute_name = displayName
# Friendly name or name of the attribute within the SAML assertion to use as the user's login handle
;assertion_attribute_login = mail
# Friendly name or name of the attribute within the SAML assertion to use as the user's email
;assertion_attribute_email = mail
#################################### Basic Auth ##########################
[auth.basic]
;enabled = true
@@ -673,9 +696,6 @@
;server_url =
# If the remote HTTP image renderer service runs on a different server than the Grafana server you may have to configure this to a URL where Grafana is reachable, e.g. http://grafana.domain/.
;callback_url =
# Concurrent render request limit affects when the /render HTTP endpoint is used. Rendering many images at the same time can overload the server,
# which this setting can help protect against by only allowing a certain amount of concurrent requests.
;concurrent_render_request_limit = 30
[panels]
# If set to true Grafana will allow script tags in text panels. Not recommended as it enable XSS vulnerabilities.
@@ -684,68 +704,6 @@
[plugins]
;enable_alpha = false
;app_tls_skip_verify_insecure = false
# Enter a comma-separated list of plugin identifiers to identify plugins that are allowed to be loaded even if they lack a valid signature.
;allow_loading_unsigned_plugins =
#################################### Grafana Image Renderer Plugin ##########################
[plugin.grafana-image-renderer]
# Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert.
# See ICUs metaZones.txt (https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt) for a list of supported
# timezone IDs. Fallbacks to TZ environment variable if not set.
;rendering_timezone =
# Instruct headless browser instance to use a default language when not provided by Grafana, e.g. when rendering panel image of alert.
# Please refer to the HTTP header Accept-Language to understand how to format this value, e.g. 'fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5'.
;rendering_language =
# Instruct headless browser instance to use a default device scale factor when not provided by Grafana, e.g. when rendering panel image of alert.
# Default is 1. Using a higher value will produce more detailed images (higher DPI), but will require more disk space to store an image.
;rendering_viewport_device_scale_factor =
# Instruct headless browser instance whether to ignore HTTPS errors during navigation. Per default HTTPS errors are not ignored. Due to
# the security risk it's not recommended to ignore HTTPS errors.
;rendering_ignore_https_errors =
# Instruct headless browser instance whether to capture and log verbose information when rendering an image. Default is false and will
# only capture and log error messages. When enabled, debug messages are captured and logged as well.
# For the verbose information to be included in the Grafana server log you have to adjust the rendering log level to debug, configure
# [log].filter = rendering:debug.
;rendering_verbose_logging =
# Instruct headless browser instance whether to output its debug and error messages into running process of remote rendering service.
# Default is false. This can be useful to enable (true) when troubleshooting.
;rendering_dumpio =
# Additional arguments to pass to the headless browser instance. Default is --no-sandbox. The list of Chromium flags can be found
# here (https://peter.sh/experiments/chromium-command-line-switches/). Multiple arguments is separated with comma-character.
;rendering_args =
# You can configure the plugin to use a different browser binary instead of the pre-packaged version of Chromium.
# Please note that this is not recommended, since you may encounter problems if the installed version of Chrome/Chromium is not
# compatible with the plugin.
;rendering_chrome_bin =
# Instruct how headless browser instances are created. Default is 'default' and will create a new browser instance on each request.
# Mode 'clustered' will make sure that only a maximum of browsers/incognito pages can execute concurrently.
# Mode 'reusable' will have one browser instance and will create a new incognito page on each request.
;rendering_mode =
# When rendering_mode = clustered you can instruct how many browsers or incognito pages can execute concurrently. Default is 'browser'
# and will cluster using browser instances.
# Mode 'context' will cluster using incognito pages.
;rendering_clustering_mode =
# When rendering_mode = clustered you can define maximum number of browser instances/incognito pages that can execute concurrently..
;rendering_clustering_max_concurrency =
# Limit the maxiumum viewport width, height and device scale factor that can be requested.
;rendering_viewport_max_width =
;rendering_viewport_max_height =
;rendering_viewport_max_device_scale_factor =
# Change the listening host and port of the gRPC server. Default host is 127.0.0.1 and default port is 0 and will automatically assign
# a port not in use.
;grpc_host =
;grpc_port =
[enterprise]
# Path to a valid Grafana Enterprise license.jwt file

View File

@@ -4,6 +4,7 @@ This guide helps you get started developing Grafana.
Before you begin, you might want to read [How to contribute to Grafana as a junior dev](https://medium.com/@ivanahuckova/how-to-contribute-to-grafana-as-junior-dev-c01fe3064502) by [Ivana Huckova](https://medium.com/@ivanahuckova).
## Dependencies
Make sure you have the following dependencies installed before setting up your developer environment:
@@ -20,7 +21,7 @@ We recommend using [Homebrew](https://brew.sh/) for installing any missing depen
```
brew install git
brew install go
brew install node@12
brew install node
npm install -g yarn
```
@@ -51,7 +52,7 @@ After the command has finished, we can start building our source code:
yarn start
```
Once `yarn start` has built the assets, it will continue to do so whenever any of the files change. This means you don't have to manually build the assets every time you change the code.
Once `yarn start` has built the assets, it will continue to do so whenever any of the files change. This means you don't have to manually build the assets whenever every time you change the code.
Next, we'll build the web server that will serve the frontend assets we just built.
@@ -97,35 +98,29 @@ go test -v ./pkg/...
### Run end-to-end tests
The end to end tests in Grafana use [Cypress](https://www.cypress.io/) to run automated scripts in a headless Chromium browser. Read more about our [e2e framework](/contribute/style-guides/e2e.md).
The end to end tests in Grafana use [Cypress](https://www.cypress.io/) to run automated scripts in a headless Chromium browser. Read more about our [e2e framework](/contribute/style-guides/e2e.md).
To run the tests:
```
yarn e2e
yarn e2e-tests
```
By default, the end-to-end tests starts a Grafana instance listening on `localhost:3001`. To use a specific URL, set the `BASE_URL` environment variable:
By default, the end-to-end tests assumes Grafana is available on `localhost:3000`. To use a specific URL, set the `BASE_URL` environment variable:
```
BASE_URL=http://localhost:3333 yarn e2e
BASE_URL=http://localhost:3333 yarn e2e-tests
```
To follow the tests in the browser while they're running, use the `yarn e2e:debug`.
To follow the tests in the browser while they're running, use the `yarn e2e-tests:debug` instead.
```
yarn e2e:debug
```
If you want to pick a test first, use the `yarn e2e:dev`, to pick a test and follow the test in the browser while it runs.
```
yarn e2e:dev
yarn e2e-tests:debug
```
## Configure Grafana for development
The default configuration, `grafana.ini`, is located in the `conf` directory.
The default configuration, `grafana.ini`, is located in the `conf` directory.
To override the default configuration, create a `custom.ini` file in the `conf` directory. You only need to add the options you wish to override.
@@ -135,6 +130,7 @@ Enable the development mode, by adding the following line in your `custom.ini`:
app_mode = development
```
### Add data sources
By now, you should be able to build and test a change you've made to the Grafana source code. In most cases, you need to add at least one data source to verify the change.
@@ -176,7 +172,7 @@ The resulting image will be tagged as grafana/grafana:dev.
1. Build the frontend: `go run build.go build-frontend`.
1. Build the Docker image: `make build-docker-dev`.
**Note:** If you are using Docker for macOS, be sure to set the memory limit to be larger than 2 GiB. Otherwise, `grunt build` may fail. The memory limit settings are available under **Docker Desktop** -> **Preferences** -> **Advanced**.
**Note:** If you are using Docker for macOS, be sure to set the memory limit to be larger than 2 GiB. Otherwise `grunt build` may fail. The memory limit settings are available under **Docker Desktop** -> **Preferences** -> **Advanced**.
## Troubleshooting
@@ -184,7 +180,7 @@ Are you having issues with setting up your environment? Here are some tips that
### Too many open files when running `make run`
Depending on your environment, you may have to increase the maximum number of open files allowed. For the rest of this section, we will assume you are on a Unix like OS (e.g. Linux/MacOS), where you can control the maximum number of open files through the [ulimit](https://ss64.com/bash/ulimit.html) shell command.
Depending on your environment, you may have to increase the maximum number of open files allowed.
To see how many open files are allowed, run:
@@ -204,28 +200,7 @@ The number of files needed may be different on your environment. To determine th
find ./conf ./pkg ./public/views | wc -l
```
Another alternative is to limit the files being watched. The directories that are watched for changes are listed in the `.bra.toml` file in the root directory.
To retain your `ulimit` configuration, i.e. so it will be remembered for future sessions, you need to commit it to your command line shell initialization file. Which file this will be depends on the shell you are using, here are some examples:
* zsh -> ~/.zshrc
* bash -> ~/.bashrc
Commit your ulimit configuration to your shell initialization file as follows ($LIMIT being your chosen limit and $INIT_FILE being the initialization file for your shell):
```
echo ulimit -S -n $LIMIT >> $INIT_FILE
```
Your command shell should read the initialization file in question every time it gets started, and apply your `ulimit` command.
For some people, typically using the bash shell, ulimit fails with an error similar to the following:
```
ulimit: open files: cannot modify limit: Operation not permitted
```
If that happens to you, chances are you've already set a lower limit and your shell won't let you set a higher one. Try looking in your shell initalization files (~/.bashrc typically), if there's already a ulimit command that you can tweak.
Another alternative is to limit the files being watched. The directories that are watched for changes are listed in the `.bra.toml` file in the root directory.
## Next steps

View File

@@ -4,8 +4,6 @@ This style guide applies to all documentation created for Grafana products.
For information about how to write technical documentation, we suggest reviewing the content of the [Google Technical Writing courses](https://developers.google.com/tech-writing).
The [Divio documentation system](https://documentation.divio.com/) site is also a good resource.
## Contributing
The *Documentation style guide* is a living document. Add to it whenever a style decision is made or a question is answered regarding style, grammar, or word choice.
@@ -33,7 +31,6 @@ The following sections provide general guidelines on topics specific to Grafana
- Use: The panel opens. Grafana opens the panel.
* Do not use an ampersand (&) as an abbreviation for "and."
- **Exceptions:** If an ampersand is used in the Grafana UI, then match the UI.
* Avoid using internal slang and jargon in technical documentation.
### File naming conventions
@@ -113,7 +110,7 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
### Word usage
Grafana products has some words, abbreviations, and terms particular to the Grafana discourse community.
Grafana products has some words, abbreviations, and slang particular to this discourse community.
#### checkout, check out
@@ -142,14 +139,6 @@ Two words, not one
* Correct, but passive voice: Your list of active alarms is displayed.
* Incorrect: The list of active alarms displays.
#### drawer
Do not use. This is developer jargon that refers to a UI panel. Refer to the panel or feature by its proper name.
#### intro, introduction
"Introduction" is the preferred word. Use "intro" if there are space constraints (like on the side menu) or you are specifically trying for a less formal, more conversational tone.
#### metadata
One word, not two.

View File

@@ -1,51 +1,19 @@
# End to end test framework
Grafana Labs uses a minimal home grown solution built on top of Cypress for our end to end (e2e) tests.
## Commands
- `yarn e2e` Creates an isolated grafana-server home under `<repo-root>/e2e/tmp` with provisioned data sources and dashboards. This
copies locally build binary and frontend assets from your repo root so you need to have a built backend and frontend
for this to run locally. The server starts on port 3001 so it does not conflict with your normal dev server.
- `yarn e2e:debug` Same as above but runs the tests in chrome and does not shutdown after completion.
- `yarn e2e:dev` Same as above but does not run any tests on startup. It lets you pick a test first.
If you already have a Grafana instance running, you can provide a specific URL by setting the `BASE_URL` environment variable:
```
BASE_URL=http://172.0.10.2:3333 yarn e2e
```
The above commands use some utils scripts under `<repo-root>/e2e` that can also be used for more control.
- `./e2e/start-server` This creates a fresh new grafana server working dir, setup's config and starts the server. It
will also kill any previously started server that is still running using pid file at `<repo-root>/e2e/tmp/pid`.
- `./e2e/wait-for-grafana` waits for `$HOST` and `$PORT` to be available. Per default localhost and 3001.
- `./e2e/run-suite <debug|dev|noarg>` Starts cypress in different modes.
## Test Suites
All the integration tests are located at `e2e/suite<x>/specs`. The page objects and reusable flows are in the
`packages/grafana-e2e` package.
## Basic concepts
Here is a good introduction to e2e best practices: https://martinfowler.com/bliki/PageObject.html.
- `Selector`: A unique identifier that is used from the e2e framework to retrieve an element from the Browser
- `Page`: An abstraction for an object that contains one or more `Selectors` with `visit` function to navigate to the page.
- `Component`: An abstraction for an object that contains one or more `Selectors` but without `visit` function
- `Page`: An abstraction for an object that contains one or more `Selectors`
- `Flow`: An abstraction that contains a sequence of actions on one or more `Pages` that can be reused and shared between tests
## Basic example
Let's start with a simple example with a single selector. For simplicity, all examples are in JSX.
In our example app, we have an input that we want to type some text into during our e2e test.
```jsx harmony
<div>
<input type="text" className="gf-form-input login-form-input" />
<input type="text" className="gf-form-input login-form-input"/>
</div>
```
@@ -53,26 +21,25 @@ We could define a selector using `JQuery` [type selectors](https://api.jquery.co
At Grafana, we use `aria-label` as our preferred way of defining selectors instead of `data-*` attributes. This also aids in accessibility.
Let's add a descriptive `aria-label` to our simple example.
```jsx harmony
<div>
<input type="text" className="gf-form-input login-form-input" aria-label="Username input field" />
<input type="text" className="gf-form-input login-form-input" aria-label="Username input field"/>
</div>
```
Now that we added the `aria-label` we suddenly get more information about this particular field. It's an input field that represents a username, but there it's still not really signaling that it's part of an e2e test.
The next step is to create a `Page` representation in our e2e test framework to glue the test with the real implementation using the `pageFactory` function. For that function we can supply a `url` and `selectors` like in the example below:
```typescript
export const Login = {
url: "/login", // used when called from Login.visit()
username: "Username input field", // used when called from Login.username().type('Hello World')
};
export const Login = pageFactory({
url: '/login', // used when called from Login.visit()
selectors: {
username: 'Username input field', // used when called from Login.username().type('Hello World')
},
});
```
The next step is to add the `Login` page to the exported const `Pages` in `packages/grafana-e2e-selectors/src/selectors/pages.ts` so that it appears when we type `e2e.pages` in our IDE.
The next step is to add the `Login` page to the exported const `Pages` in `packages/grafana-e2e/src/pages/index.ts` so that it appears when we type `e2e.pages` in our IDE.
```ecmascript 6
export const Pages = {
Login,
@@ -82,21 +49,17 @@ export const Pages = {
};
```
Now that we have a `Page` called `Login` in our `Pages` const we can use that to add a selector in our html like shown below and now this really signals to future developers that it is part of an e2e test.
```jsx harmony
<div>
<input type="text" className="gf-form-input login-form-input" aria-label={selectors.pages.Login.username} />
<input type="text" className="gf-form-input login-form-input" aria-label={e2e.pages.Login.selectors.username}/>
</div>
```
The last step in our example is to use our `Login` page as part of a test.
The last step in our example is to use our `Login` page as part of a test. The `pageFactory` function we used before gives us two things:
- The `url` property is used whenever we call the `visit` function and is equivalent to the Cypress function [cy.visit()](https://docs.cypress.io/api/commands/visit.html#Syntax).
> Best practice after calling `visit` is to always call `should` on a selector to prevent flaky tests when you try to access an element that isn't ready. For more information, refer to [Commands vs. assertions](https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions).
- Any defined selector can be accessed from the `Login` page by invoking it. This is equivalent to the result of the Cypress function [cy.get(...)](https://docs.cypress.io/api/commands/get.html#Syntax).
> Best practice after calling `visit` is to always call `should` on a selector to prevent flaky tests when you try to access an element that isn't ready. For more information, refer to [Commands vs. assertions](https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions).
- Any defined selector in the `selectors` property can be accessed from the `Login` page by invoking it. This is equivalent to the result of the Cypress function [cy.get(...)](https://docs.cypress.io/api/commands/get.html#Syntax).
```ecmascript 6
describe('Login test', () => {
it('Should pass', () => {
@@ -110,7 +73,6 @@ describe('Login test', () => {
```
## Advanced example
Let's take a look at an example that uses the same `selector` for multiple items in a list for instance. In this example app we have a list of data sources that we want to click on during an e2e test.
```jsx harmony
@@ -118,35 +80,36 @@ Let's take a look at an example that uses the same `selector` for multiple items
{dataSources.map(dataSource => (
<li className="card-item-wrapper" key={dataSource.id}>
<a className="card-item" href={`datasources/edit/${dataSource.id}`}>
<div className="card-item-name">{dataSource.name}</div>
<div className="card-item-name">
{dataSource.name}
</div>
</a>
</li>
))}
</ul>
```
````
```
Just as before in the basic example we'll start by creating a page abstraction using the `pageFactory` function:
```typescript
export const DataSources = {
export const DataSources = pageFactory({
url: '/datasources',
dataSources: (dataSourceName: string) => `Data source list item ${dataSourceName}`,
};
````
selectors: {
dataSources: (dataSourceName: string) => `Data source list item ${dataSourceName}`,
},
});
```
You might have noticed that instead of a simple `string` as the `selector`, we're using a `function` that takes a string parameter as an argument and returns a formatted string using the argument.
Just as before we need to add the `DataSources` page to the exported const `Pages` in `packages/grafana-e2e-selectors/src/selectors/pages.ts`.
Just as before we need to add the `DataSources` page to the exported const `Pages` in `packages/grafana-e2e/src/pages/index.ts`.
The next step is to use the `dataSources` selector function as in our example below:
```jsx harmony
<ul>
{dataSources.map(dataSource => (
<li className="card-item-wrapper" key={dataSource.id}>
<a className="card-item" href={`datasources/edit/${dataSource.id}`}>
<div className="card-item-name" aria-label={selectors.pages.DataSources.dataSources(dataSource.name)}>
<div className="card-item-name" aria-label={e2e.pages.DataSources.selectors.dataSources(dataSource.name)}>
{dataSource.name}
</div>
</a>
@@ -156,7 +119,6 @@ The next step is to use the `dataSources` selector function as in our example be
```
When this list is rendered with the data sources with names `A`, `B`, `C` the resulting html would become:
```jsx harmony
<div class="card-item-name" aria-label="Data source list item A">
A
@@ -172,9 +134,7 @@ When this list is rendered with the data sources with names `A`, `B`, `C` the re
```
Now we can write our test. The one thing that differs from the `Basic example` is that we pass in which data source we want to click on as an argument to the selector function:
> Best practice after calling `visit` is to always call `should` on a selector to prevent flaky tests when you try to access an element that isn't ready. For more information, refer to [Commands vs. assertions](https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions).
```ecmascript 6
describe('List test', () => {
it('Clicking on data source named B', () => {
@@ -187,18 +147,17 @@ describe('List test', () => {
});
```
## Debugging PhantomJS image rendering
### Common Error
The most common error with PhantomJs image rendering is when a PR introduces an import that has functionality that's not supported by PhantomJs. To quickly identify which new import causes this you can use a tool like `es-check`.
1. Run > `npx es-check es5 './public/build/*.js'`
2. Check the output for files that break es5 compatibility.
3. Lazy load the failing imports if possible.
3. Lazy load the failing imports if possible.
### Debugging
There is no easy or comprehensive way to debug PhantomJS smoke test (image rendering) failures. However, PhantomJS exposes remote debugging interface which can give you a sense of what is going wrong in the smoke test. Before performing the steps described below make sure your local Grafana instance is running:
1. Go to `tools/phantomjs` directory

View File

@@ -8,7 +8,7 @@ Generally we follow the Airbnb [React Style Guide](https://github.com/airbnb/jav
- [Table of Contents](#table-of-contents)
- [Basic rules](#basic-rules)
- [Naming conventions](#naming-conventions)
- [File and directory naming conventions](#file-and-directory-naming-conventions)
- [Files and directories naming conventions](#files-and-directories-naming-conventions)
- [Code organization](#code-organization)
- [Exports](#exports)
- [Comments](#comments)
@@ -172,44 +172,6 @@ const CONSTANT_VALUE = "This string won't change";
_SASS styles are deprecated. Please migrate to Emotion whenever you need to modify SASS styles._
### Typing
In general, you should let Typescript infer the types so that there's no need to explicitly define type for each variable.
There are some exceptions to this:
```typescript
// Typescript needs to know type of arrays or objects otherwise it would infer it as array of any
// bad
const stringArray = [];
// good
const stringArray: string[] = [];
```
Specify function return types explicitly in new code. This improves readability by being able to tell what a function returns just by looking at the signature. It also prevents errors when a function's return type is broader than expected by the author.
> Note: We don't have linting for this enabled because of lots of old code that needs to be fixed first.
```typescript
// bad
function transform(value?: string) {
if (!value) {
return undefined
}
return applyTransform(value)
};
// good
function transform(value?: string): TransformedValue | undefined {
if (!value) {
return undefined
}
return applyTransform(value)
};
```
### File and directory naming conventions
Name files according to the primary export:

View File

@@ -10,7 +10,7 @@ Storybook is:
## How to create stories
Stories for a component should be placed next to the component file. The Storybook file requires the same name as the component file. For example, a story for `SomeComponent.tsx` will have the file name `SomeComponent.story.tsx`. If a story should be internal, not visible in production, name the file `SomeComponent.story.internal.tsx`.
Stories for a component should be placed next to the component file. The Storybook file requires the same name as the component file. For example, a story for `SomeComponent.tsx` will have the file name `SomeComponent.story.tsx`.
### Writing stories
@@ -101,10 +101,7 @@ import { MyComponent } from "./MyComponent";
### MDX file without a relationship to a component
An MDX file can exist by itself without any connection to a story. This can be good for writing things such as a general guidelines page. Two things are required for this to work:
- The file needs to be named `*.story.mdx`
- A `Meta` tag must exist that says where in the hierarchy the component lives. It can look like this:
An MDX file can exist by itself without any connection to a story. This can be good for writing things such as a general guidelines page. Something that is required when the MDX file has no relation to a component is a `Meta` tag that says where in the hierarchy the component will live. It can look like this:
```jsx
<Meta title="Docs Overview/Color Palettes"/>

View File

@@ -23,7 +23,7 @@ Try to *chunk* your content. This means you should organize the document so that
### Chunking example
If I was writing content for a site called *Doggie handbook*, I might organize it like this.
If I was writing a topic called *Doggie handbook*, I might organize it like this.
**Concept**
* What a dog is

View File

@@ -26,7 +26,7 @@ In the case of a long task, then you probably won't need any headings except for
1. Use second-person imperative tense.
1. Basically, "You, do this" with every sentence.
1. Do not use the third-person "user" for steps you want the reader ("you") to perform.
1. Write steps that contain one action, possibly two related actions, such as copy and paste a thing or save and quit the program.
1. Write steps that contain one action, possibly two related actions, such as copy and paste a thing or save and quite the program.
If a sentence is not telling the reader to do something, then it is not a step. You can use nested images or paragraphs like this one to add information if necessary.
In many cases, you should tell the reader what the outcome should be so that they know when they are done.

View File

@@ -36,14 +36,5 @@ make devenv sources=influxdb,prometheus2,elastic5
Some of the blocks support dynamic change of the image version used in the Docker file. The signature looks like this:
```bash
make devenv sources=postgres,openldap,grafana postgres_version=9.2 grafana_version=6.7.0-beta1
make devenv sources=postgres,openldap postgres_version=9.2
```
### Notes per block
#### Grafana
The grafana block is pre-configured with the dev-datasources and dashboards.
#### Jaeger
Jaeger block runs both Jaeger and Loki container. Loki container sends traces to Jaeger and also logs its own logs into itself so it is possible to setup derived field for traceID from Loki to Jaeger. You need to install a docker plugin for the self logging to work, without it the container won't start. See https://github.com/grafana/loki/tree/master/cmd/docker-driver#plugin-installation for installation instructions.

View File

@@ -0,0 +1,168 @@
{
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": null,
"links": [],
"panels": [
{
"alert": {
"conditions": [
{
"evaluator": {
"params": [
65
],
"type": "gt"
},
"operator": {
"type": "and"
},
"query": {
"params": [
"A",
"5m",
"now"
]
},
"reducer": {
"params": [],
"type": "avg"
},
"type": "query"
}
],
"executionErrorState": "alerting",
"frequency": "10s",
"handler": 1,
"name": "bulk alerting",
"noDataState": "no_data",
"notifications": []
},
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-prometheus",
"fill": 1,
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 0
},
"id": 2,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"$$hashKey": "object:117",
"expr": "go_goroutines",
"format": "time_series",
"intervalFactor": 1,
"refId": "A"
}
],
"thresholds": [
{
"colorMode": "critical",
"fill": true,
"line": true,
"op": "gt",
"value": 50
}
],
"timeFrom": null,
"timeShift": null,
"title": "Panel Title",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
}
],
"schemaVersion": 16,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "",
"title": "New dashboard",
"uid": null,
"version": 0
}

View File

@@ -1,170 +0,0 @@
{
alertingDashboard(dashboardCounter, datasourceCounter):: {
title: "alerting-title-" + dashboardCounter,
editable: true,
gnetId: null,
graphTooltip: 0,
id: null,
links: [],
panels: [
{
alert: {
conditions: [
{
evaluator: {
params: [
65
],
type: "gt"
},
operator: {
type: "and"
},
query: {
params: [
"A",
"5m",
"now"
]
},
reducer: {
params: [],
type: "avg"
},
type: "query"
}
],
executionErrorState: "alerting",
frequency: "24h",
handler: 1,
name: "bulk alerting " + dashboardCounter,
noDataState: "no_data",
notifications: []
},
aliasColors: {},
bars: false,
dashLength: 10,
dashes: false,
datasource: "gfdev-bulkalerting-" + datasourceCounter,
fill: 1,
gridPos: {
h: 9,
w: 12,
x: 0,
y: 0
},
id: 1,
legend: {
avg: false,
current: false,
max: false,
min: false,
show: true,
total: false,
values: false
},
lines: true,
linewidth: 1,
nullPointMode: "null",
percentage: false,
pointradius: 5,
points: false,
renderer: "flot",
seriesOverrides: [],
spaceLength: 10,
stack: false,
steppedLine: false,
targets: [
{
expr: "go_goroutines",
format: "time_series",
intervalFactor: 1,
refId: "A"
}
],
thresholds: [
{
colorMode: "critical",
fill: true,
line: true,
op: "gt",
value: 50
}
],
timeFrom: null,
timeShift: null,
title: "Panel Title",
tooltip: {
shared: true,
sort: 0,
value_type: "individual"
},
type: "graph",
xaxis: {
buckets: null,
mode: "time",
name: null,
show: true,
values: []
},
yaxes: [
{
format: "short",
label: null,
logBase: 1,
max: null,
min: null,
show: true
},
{
format: "short",
label: null,
logBase: 1,
max: null,
min: null,
show: true
}
]
}
],
schemaVersion: 16,
style: "dark",
tags: [],
templating: {
list: []
},
time: {
from: "now-6h",
to: "now"
},
timepicker: {
refresh_intervals: [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
time_options: [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
timezone: "",
uid: null,
version: 0
},
}

View File

@@ -1,14 +0,0 @@
local arr = std.range(1, 100);
{
"apiVersion": 1,
"datasources": [
{
"name": 'gfdev-bulkalerting-' + counter,
"type": "prometheus",
"access": "proxy",
"url": "http://localhost:9090"
}
for counter in arr
],
}

View File

@@ -246,29 +246,5 @@ datasources:
access: proxy
url: http://localhost:3100
editable: false
jsonData:
derivedFields:
- name: "traceID"
matcherRegex: "traceID=(\\w+)"
url: "$${__value.raw}"
datasourceUid: gdev-jaeger
- name: "traceID"
matcherRegex: "traceID=(\\w+)"
url: "$${__value.raw}"
datasourceUid: gdev-zipkin
- name: gdev-jaeger
type: jaeger
uid: gdev-jaeger
access: proxy
url: http://localhost:16686
editable: false
- name: gdev-zipkin
type: zipkin
uid: gdev-zipkin
access: proxy
url: http://localhost:9411
editable: false

View File

@@ -1,248 +0,0 @@
apiVersion: 1
datasources:
- name: gdev-graphite
type: graphite
access: proxy
url: http://graphite11:80
jsonData:
graphiteVersion: "1.1"
- name: gdev-prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
- name: gdev-slow-prometheus
type: prometheus
access: proxy
url: http://prometheus:3011
- name: gdev-testdata
isDefault: true
type: testdata
- name: gdev-influxdb
type: influxdb
access: proxy
database: site
user: grafana
url: http://influxdb:8086
jsonData:
timeInterval: "15s"
secureJsonData:
password: grafana
- name: gdev-influxdb-telegraf
type: influxdb
access: proxy
database: telegraf
user: grafana
url: http://telegraf:8086
jsonData:
timeInterval: "10s"
secureJsonData:
password: grafana
- name: gdev-opentsdb
type: opentsdb
access: proxy
url: http://opentsdb:4242
jsonData:
tsdbResolution: 1
tsdbVersion: 1
- name: gdev-elasticsearch-v2-metrics
type: elasticsearch
access: proxy
database: "[metrics-]YYYY.MM.DD"
url: http://elasticsearch:9200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 2
- name: gdev-elasticsearch-v2-logs
type: elasticsearch
access: proxy
database: "[logs-]YYYY.MM.DD"
url: http://elasticsearch:9200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 2
- name: gdev-elasticsearch-v5-metrics
type: elasticsearch
access: proxy
database: "[metrics-]YYYY.MM.DD"
url: http://elasticsearch5:10200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 5
- name: gdev-elasticsearch-v5-logs
type: elasticsearch
access: proxy
database: "[logs-]YYYY.MM.DD"
url: http://elasticsearch5:9200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 5
- name: gdev-elasticsearch-v6-metrics
type: elasticsearch
access: proxy
database: "[metrics-]YYYY.MM.DD"
url: http://elasticsearch6:9200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 60
- name: gdev-elasticsearch-v6-logs
type: elasticsearch
access: proxy
database: "[logs-]YYYY.MM.DD"
url: http://elasticsearch6:9200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 60
- name: gdev-elasticsearch-v6-filebeat
type: elasticsearch
access: proxy
database: "[filebeat-]YYYY.MM.DD"
url: http://elasticsearch6:9200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 60
- name: gdev-elasticsearch-v7-metrics
type: elasticsearch
access: proxy
database: "[metrics-]YYYY.MM.DD"
url: http://elasticsearch7:9200
jsonData:
timeInterval: 10s
interval: Daily
timeField: "@timestamp"
esVersion: 70
- name: gdev-elasticsearch-v7-logs
type: elasticsearch
access: proxy
database: "[logs-]YYYY.MM.DD"
url: http://elasticsearch7:9200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 70
- name: gdev-elasticsearch-v7-filebeat
type: elasticsearch
access: proxy
database: "[filebeat-]YYYY.MM.DD"
url: http://elasticsearch7:9200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 70
timeInterval: "10s"
logMessageField: message
logLevelField: fields.level
- name: gdev-elasticsearch-v7-metricbeat
type: elasticsearch
access: proxy
database: "[metricbeat-]YYYY.MM.DD"
url: http://elasticsearch7:9200
jsonData:
interval: Daily
timeField: "@timestamp"
esVersion: 70
timeInterval: "10s"
- name: gdev-mysql
type: mysql
url: mysql:3306
database: grafana
user: grafana
secureJsonData:
password: password
- name: gdev-mysql-ds-tests
type: mysql
url: mysqltests:3306
database: grafana_ds_tests
user: grafana
secureJsonData:
password: password
- name: gdev-mssql
type: mssql
url: mssql:1433
database: grafana
user: grafana
secureJsonData:
password: Password!
- name: gdev-mssql-ds-tests
type: mssql
url: mssqltests:1433
database: grafanatest
user: grafana
secureJsonData:
password: Password!
- name: gdev-postgres
type: postgres
url: postgres:5432
database: grafana
user: grafana
secureJsonData:
password: password
jsonData:
sslmode: "disable"
- name: gdev-postgres-ds-tests
type: postgres
url: postgrestest:5432
database: grafanadstest
user: grafanatest
secureJsonData:
password: grafanatest
jsonData:
sslmode: "disable"
- name: gdev-cloudwatch
type: cloudwatch
editable: true
jsonData:
authType: credentials
defaultRegion: eu-west-2
# Keep to test old /api/prom API
- name: gdev-loki-0.3
type: loki
access: proxy
url: http://loki0.3:3100
editable: false
# First version with new v1 API (remove once v1 is out)
- name: gdev-loki-0.4
type: loki
access: proxy
url: http://loki0.4:3100
editable: false
- name: gdev-loki
type: loki
access: proxy
url: http://loki:3100
editable: false

View File

@@ -1,195 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1584435937931,
"links": [],
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": null,
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 14,
"w": 19,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 2,
"legend": {
"alignAsTable": true,
"avg": false,
"current": false,
"max": false,
"min": true,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "updatesOnTime: $updatesOnTime",
"refId": "A",
"scenarioId": "random_walk"
},
{
"alias": "dependsOnFirst: $dependsOnFirst",
"refId": "B",
"scenarioId": "random_walk"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Panel Title",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"schemaVersion": 22,
"style": "dark",
"tags": ["gdev", "templating"],
"templating": {
"list": [
{
"allValue": null,
"current": {
"text": "value.1584434137814",
"value": "value.1584434137814"
},
"datasource": "gdev-testdata",
"definition": "value.$__from",
"hide": 0,
"includeAll": false,
"index": -1,
"label": null,
"multi": false,
"name": "updatesOnTime",
"options": [],
"query": "value.$__from",
"refresh": 2,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"tagValuesQuery": "",
"tags": [],
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"allValue": null,
"current": {
"text": "value.value.1584434072074",
"value": "value.value.1584434072074"
},
"datasource": "gdev-testdata",
"definition": "value.$updatesOnTime",
"hide": 0,
"includeAll": false,
"index": -1,
"label": null,
"multi": false,
"name": "dependsOnFirst",
"options": [
{
"selected": true,
"text": "value.value.1584434072074",
"value": "value.value.1584434072074"
}
],
"query": "value.$updatesOnTime",
"refresh": 0,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"tagValuesQuery": "",
"tags": [],
"tagsQuery": "",
"type": "query",
"useTags": false
}
]
},
"time": {
"from": "now-30m",
"to": "now"
},
"timepicker": {
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Templating - Variables That Refresh On Time Change",
"uid": "HeUnbEuZk",
"variables": {
"list": []
},
"version": 13
}

View File

@@ -1,602 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"links": [],
"panels": [
{
"datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 7,
"title": "Cell styles",
"type": "row"
},
{
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {
"align": "center",
"displayMode": "color-background"
},
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "blue",
"value": 20
},
{
"color": "orange",
"value": 60
},
{
"color": "red",
"value": 70
}
]
},
"unit": "degree"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Max"
},
"properties": [
{
"id": "custom.width",
"value": 84
}
]
},
{
"matcher": {
"id": "byName",
"options": "Last"
},
"properties": [
{
"id": "custom.width",
"value": 78
}
]
},
{
"matcher": {
"id": "byName",
"options": "Mean"
},
"properties": [
{
"id": "custom.width",
"value": 74
}
]
},
{
"matcher": {
"id": "byName",
"options": "Field"
},
"properties": [
{
"id": "custom.align",
"value": "left"
}
]
}
]
},
"gridPos": {
"h": 16,
"w": 7,
"x": 0,
"y": 1
},
"id": 4,
"options": {
"showHeader": true,
"sortBy": [
{
"desc": true,
"displayName": "Last"
}
]
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 15,
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "Colored background",
"transformations": [
{
"id": "reduce",
"options": {
"reducers": ["max", "mean", "last"]
}
}
],
"type": "table"
},
{
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {
"align": null
},
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "orange",
"value": null
},
{
"color": "red",
"value": 50
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "custom.displayMode",
"value": "gradient-gauge"
}
]
},
{
"matcher": {
"id": "byName",
"options": "Info"
},
"properties": [
{
"id": "custom.width",
"value": 92
}
]
},
{
"matcher": {
"id": "byName",
"options": "Min"
},
"properties": [
{
"id": "custom.width",
"value": 76
}
]
},
{
"matcher": {
"id": "byName",
"options": "Max"
},
"properties": [
{
"id": "custom.width",
"value": 89
}
]
},
{
"matcher": {
"id": "byName",
"options": "Time"
},
"properties": [
{
"id": "custom.width",
"value": 165
}
]
}
]
},
"gridPos": {
"h": 16,
"w": 8,
"x": 7,
"y": 1
},
"id": 2,
"options": {
"showHeader": true,
"sortBy": [
{
"desc": false,
"displayName": "Min"
}
]
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk_table",
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "Bar gauge cells",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {
"Time": true
},
"indexByName": {
"Info": 1,
"Max": 3,
"Min": 2,
"Time": 0,
"Value": 4
},
"renameByName": {}
}
}
],
"type": "table"
},
{
"datasource": "gdev-testdata",
"description": "",
"fieldConfig": {
"defaults": {
"custom": {
"align": null
},
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 50
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "custom.displayMode",
"value": "lcd-gauge"
},
{
"id": "custom.align",
"value": "center"
}
]
}
]
},
"gridPos": {
"h": 16,
"w": 9,
"x": 15,
"y": 1
},
"id": 5,
"options": {
"showHeader": true,
"sortBy": []
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk_table",
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "Retro LCD cell",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {
"Info": false,
"Max": true,
"Min": true,
"Time": false
},
"indexByName": {
"Info": 1,
"Max": 3,
"Min": 2,
"Time": 0,
"Value": 4
},
"renameByName": {}
}
}
],
"type": "table"
},
{
"collapsed": false,
"datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 17
},
"id": 9,
"panels": [],
"title": "Data links",
"type": "row"
},
{
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {
"align": "center",
"displayMode": "color-text"
},
"decimals": 2,
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "blue",
"value": 20
},
{
"color": "orange",
"value": 50
},
{
"color": "red",
"value": 70
}
]
},
"unit": "percent"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Time"
},
"properties": [
{
"id": "custom.align",
"value": null
}
]
},
{
"matcher": {
"id": "byName",
"options": "{name=\"S1\", server=\"A\"}"
},
"properties": [
{
"id": "links",
"value": [
{
"title": "Details",
"url": "http://detail?serverLabel=${__field.labels.server}&valueNumeric=${__value.numeric}"
}
]
}
]
}
]
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 18
},
"id": 3,
"maxDataPoints": "10",
"options": {
"showHeader": true
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"alias": "S1",
"labels": "server=A",
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 1,
"stringInput": ""
},
{
"alias": "S2",
"labels": "server=B",
"refId": "B",
"scenarioId": "random_walk",
"seriesCount": 1,
"stringInput": ""
},
{
"alias": "S3",
"labels": "server=C",
"refId": "C",
"scenarioId": "random_walk",
"seriesCount": 1,
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "Data link with labels and numeric value",
"transformations": [
{
"id": "seriesToColumns",
"options": {}
}
],
"type": "table"
},
{
"datasource": "gdev-testdata",
"fieldConfig": {
"defaults": {
"custom": {
"align": "center",
"displayMode": "auto"
},
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "blue",
"value": 20
},
{
"color": "orange",
"value": 60
},
{
"color": "red",
"value": 70
}
]
},
"unit": "degree"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 5,
"x": 12,
"y": 18
},
"id": 10,
"options": {
"showHeader": false,
"sortBy": [
{
"desc": true,
"displayName": "Last"
}
]
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"refId": "A",
"scenarioId": "random_walk_table",
"seriesCount": 5,
"stringInput": ""
}
],
"timeFrom": null,
"timeShift": null,
"title": "No header",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {
"Min": true,
"Time": true,
"Value": true
},
"indexByName": {
"Info": 2,
"Max": 4,
"Min": 3,
"Time": 0,
"Value": 1
},
"renameByName": {}
}
}
],
"type": "table"
}
],
"schemaVersion": 25,
"style": "dark",
"tags": ["gdev", "panel-tests"],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {
"refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - React Table",
"uid": "U_bZIMRMk",
"version": 17
}

View File

@@ -1,695 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": 28,
"links": [],
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 4,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"refId": "A",
"scenario": "random_walk",
"scenarioId": "random_walk",
"target": ""
}
],
"thresholds": [],
"timeFrom": "2s",
"timeRegions": [],
"timeShift": null,
"title": "Millisecond res x-axis and tooltip",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 0
},
"hiddenSeries": false,
"id": 3,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"refId": "A",
"scenario": "random_walk",
"scenarioId": "random_walk",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Random walk series",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 7
},
"hiddenSeries": false,
"id": 5,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "B-series",
"yaxis": 2
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"refId": "A",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
},
{
"refId": "B",
"scenarioId": "csv_metric_values",
"stringInput": "2000,3000,4000,1000,3000,10000",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "2 yaxis and axis labels",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "percent",
"label": "Perecent",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": "Pressure",
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 7
},
"hiddenSeries": false,
"id": 9,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "B-series",
"zindex": -3
}
],
"spaceLength": 10,
"stack": true,
"steppedLine": false,
"targets": [
{
"hide": false,
"refId": "B",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,null,null,null,null,null,null,100,10,10,20,30,40,10",
"target": ""
},
{
"alias": "",
"hide": false,
"refId": "A",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,10,20,30,40,40,40,100,10,20,20",
"target": ""
},
{
"alias": "",
"hide": false,
"refId": "C",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,10,20,30,40,40,40,100,10,20,20",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Stacking value ontop of nulls",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 0,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 12,
"x": 0,
"y": 15
},
"hiddenSeries": false,
"id": 21,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [
{
"alias": "C-series",
"steppedLine": true
}
],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "",
"hide": false,
"refId": "B",
"scenarioId": "csv_metric_values",
"stringInput": "1,null,40,null,90,null,null,100,null,null,100,null,null,80,null",
"target": ""
},
{
"alias": "",
"hide": false,
"refId": "C",
"scenarioId": "csv_metric_values",
"stringInput": "20,null40,null,null,50,null,70,null,100,null,10,null,30,null",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Null between points",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "gdev-testdata",
"decimals": 3,
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 12,
"x": 12,
"y": 15
},
"hiddenSeries": false,
"id": 16,
"legend": {
"alignAsTable": true,
"avg": true,
"current": true,
"max": true,
"min": true,
"show": true,
"total": true,
"values": true
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"refId": "A",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
},
{
"refId": "B",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
},
{
"refId": "C",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
},
{
"refId": "D",
"scenarioId": "csv_metric_values",
"stringInput": "1,20,90,30,5,0",
"target": ""
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Legend Table No Scroll Visible",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"refresh": false,
"revision": 8,
"schemaVersion": 25,
"style": "dark",
"tags": ["gdev", "panel-tests", "graph", "table"],
"templating": {
"list": []
},
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {
"refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
},
"timezone": "utc",
"title": "Panel Tests - Time zone support",
"uid": "5SdHCasdf",
"version": 1
}

View File

@@ -1 +0,0 @@
grafana_version=6.6.2

View File

@@ -1,14 +0,0 @@
grafana:
image: grafana/grafana:${grafana_version}
ports:
- "3001:3000"
volumes:
- "./dashboards.yaml:/etc/grafana/provisioning/dashboards/dashboards.yaml"
- "./dev-dashboards:/usr/share/grafana/devenv/dev-dashboards"
- "./datasources_docker.yaml:/etc/grafana/provisioning/datasources/datasources.yaml"
environment:
GF_RENDERING_SERVER_URL: http://renderer:8081/render
GF_RENDERING_CALLBACK_URL: http://grafana:3000/
renderer:
image: grafana/grafana-image-renderer:latest

View File

@@ -10,11 +10,6 @@
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
# For this to work you need to install the logging driver see https://github.com/grafana/loki/tree/master/cmd/docker-driver#plugin-installation
logging:
driver: loki
options:
loki-url: "http://localhost:3100/loki/api/v1/push"
# Optional jaeger tracing
environment:
- JAEGER_AGENT_HOST=jaeger

View File

@@ -1,15 +1,18 @@
prometheus:
build: docker/blocks/prometheus
network_mode: host
ports:
- "9090:9090"
node_exporter:
image: prom/node-exporter
network_mode: host
ports:
- "9100:9100"
fake-prometheus-data:
image: grafana/fake-data-gen
network_mode: host
ports:
- "9091:9091"
environment:
@@ -17,10 +20,12 @@
alertmanager:
image: quay.io/prometheus/alertmanager
network_mode: host
ports:
- "9093:9093"
prometheus-random-data:
build: docker/blocks/prometheus_random_data
network_mode: host
ports:
- "8081:8080"

View File

@@ -15,7 +15,7 @@ alerting:
- scheme: http
static_configs:
- targets:
- "alertmanager:9093"
- "127.0.0.1:9093"
scrape_configs:
- job_name: 'prometheus'
@@ -24,16 +24,16 @@ scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['node_exporter:9100']
- targets: ['127.0.0.1:9100']
- job_name: 'fake-data-gen'
static_configs:
- targets: ['fake-prometheus-data:9091']
- targets: ['127.0.0.1:9091']
- job_name: 'grafana'
static_configs:
- targets: ['grafana:3000']
- targets: ['127.0.0.1:3000']
- job_name: 'prometheus-random-data'
static_configs:
- targets: ['prometheus-random-data:8080']
- targets: ['127.0.0.1:8081']

View File

@@ -1,4 +1,3 @@
FROM prom/prometheus:v2.7.2
ADD prometheus.yml /etc/prometheus/
ADD recording.yml /etc/prometheus/
ADD alert.yml /etc/prometheus/
ADD alert.rules /etc/prometheus/

View File

@@ -0,0 +1,10 @@
# Alert Rules
ALERT AppCrash
IF process_open_fds > 0
FOR 15s
LABELS { severity="critical" }
ANNOTATIONS {
summary = "Number of open fds > 0",
description = "Just testing"
}

View File

@@ -1,11 +0,0 @@
groups:
- name: ALERT
rules:
- alert: AppCrash
expr: process_open_fds > 0
for: 15s
labels:
severity: critical
annotations:
summary: Number of open fds > 0
description: Just testing

View File

@@ -1,15 +1,18 @@
prometheus:
build: docker/blocks/prometheus2
network_mode: host
ports:
- "9090:9090"
node_exporter:
image: prom/node-exporter
network_mode: host
ports:
- "9100:9100"
fake-prometheus-data:
image: grafana/fake-data-gen
network_mode: host
ports:
- "9091:9091"
environment:
@@ -17,10 +20,12 @@
alertmanager:
image: quay.io/prometheus/alertmanager
network_mode: host
ports:
- "9093:9093"
prometheus-random-data:
build: docker/blocks/prometheus_random_data
network_mode: host
ports:
- "8081:8080"

View File

@@ -5,17 +5,17 @@ global:
# scrape_timeout is set to the global default (10s).
# Load and evaluate rules in this file every 'evaluation_interval' seconds.
rule_files:
- "alert.yml"
- "recording.yml"
#rule_files:
# - "alert.rules"
# - "first.rules"
# - "second.rules"
alerting:
alertmanagers:
- scheme: http
static_configs:
- targets:
- "alertmanager:9093"
# alerting:
# alertmanagers:
# - scheme: http
# static_configs:
# - targets:
# - "127.0.0.1:9093"
scrape_configs:
- job_name: 'prometheus'
@@ -24,16 +24,16 @@ scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['node_exporter:9100']
- targets: ['127.0.0.1:9100']
- job_name: 'fake-data-gen'
static_configs:
- targets: ['fake-prometheus-data:9091']
- targets: ['127.0.0.1:9091']
- job_name: 'grafana'
static_configs:
- targets: ['grafana:3000']
- targets: ['127.0.0.1:3000']
- job_name: 'prometheus-random-data'
static_configs:
- targets: ['prometheus-random-data:8080']
- targets: ['127.0.0.1:8081']

View File

@@ -1,16 +0,0 @@
groups:
- name: RECORDING_RULES
rules:
- record: instance_path:requests:rate5m
expr: rate(prometheus_http_requests_total{job="prometheus"}[5m])
- record: path:requests:rate5m
expr: sum without (instance)(instance_path:requests:rate5m{job="prometheus"})
- record: instance_path:reloads_failures:rate5m
expr: rate(prometheus_tsdb_reloads_failures_total{job="prometheus"}[5m])
- record: instance_path:reloads:rate5m
expr: rate(prometheus_tsdb_reloads_total{job="prometheus"}[5m])
- record: instance_path:request_failures_per_requests:ratio_rate5m
expr: |2
instance_path:reloads_failures:rate5m{job="prometheus"}
/
instance_path:reloads:rate5m{job="prometheus"}

View File

@@ -0,0 +1,3 @@
FROM prom/prometheus:v1.8.2
ADD prometheus.yml /etc/prometheus/
ADD alert.rules /etc/prometheus/

View File

@@ -0,0 +1,10 @@
# Alert Rules
ALERT AppCrash
IF process_open_fds > 0
FOR 15s
LABELS { severity="critical" }
ANNOTATIONS {
summary = "Number of open fds > 0",
description = "Just testing"
}

View File

@@ -0,0 +1,26 @@
prometheus:
build: docker/blocks/prometheus_mac
ports:
- "9090:9090"
node_exporter:
image: prom/node-exporter
ports:
- "9100:9100"
fake-prometheus-data:
image: grafana/fake-data-gen
ports:
- "9091:9091"
environment:
FD_DATASOURCE: prom
alertmanager:
image: quay.io/prometheus/alertmanager
ports:
- "9093:9093"
prometheus-random-data:
build: docker/blocks/prometheus_random_data
ports:
- "8081:8080"

View File

@@ -0,0 +1,39 @@
# my global config
global:
scrape_interval: 10s # By default, scrape targets every 15 seconds.
evaluation_interval: 10s # By default, scrape targets every 15 seconds.
# scrape_timeout is set to the global default (10s).
# Load and evaluate rules in this file every 'evaluation_interval' seconds.
rule_files:
- "alert.rules"
# - "first.rules"
# - "second.rules"
alerting:
alertmanagers:
- scheme: http
static_configs:
- targets:
- "alertmanager:9093"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node_exporter'
static_configs:
- targets: ['node_exporter:9100']
- job_name: 'fake-data-gen'
static_configs:
- targets: ['fake-prometheus-data:9091']
- job_name: 'grafana'
static_configs:
- targets: ['host.docker.internal:3000']
- job_name: 'prometheus-random-data'
static_configs:
- targets: ['prometheus-random-data:8080']

View File

@@ -1,7 +1,7 @@
# This Dockerfile builds an image for a client_golang example.
# Builder image, where we build the example.
FROM golang:1.14.1 AS builder
FROM golang:1.13.4 AS builder
# Download prometheus/client_golang/examples/random first
RUN go get github.com/prometheus/client_golang/examples/random
WORKDIR /go/src/github.com/prometheus/client_golang

View File

@@ -1,6 +0,0 @@
# There is no data generator for this so easiest way to get some data here is run this example app
# https://github.com/openzipkin/zipkin-js-example/tree/master/web
zipkin:
image: openzipkin/zipkin:latest
ports:
- "9411:9411"

View File

@@ -35,12 +35,6 @@ Run load test for 10 virtual users:
$ ./run.sh -v 10
```
Run load test and send the results to the database "myDb" in influxDB running locally on port 8086 (with no authentication):
```bash
$ ./run.sh -o influxdb=http://localhost:8086/myDb
```
Run auth token slow test (random query latency between 1 and 30 seconds):
```bash

View File

@@ -8,9 +8,8 @@ run() {
vus='2'
testcase='auth_token_test'
slowQuery=''
out=''
while getopts ":d:u:v:c:s:o:" o; do
while getopts ":d:u:v:c:s:" o; do
case "${o}" in
d)
duration=${OPTARG}
@@ -27,14 +26,11 @@ run() {
s)
slowQuery=${OPTARG}
;;
o) out=${OPTARG}
;;
esac
done
shift $((OPTIND-1))
docker run -t --network=host -v $PWD:/src -e URL=$url -e SLOW_QUERY=$slowQuery -e K6_OUT=$out --rm -i loadimpact/k6:master run --vus $vus --duration $duration src/$testcase.js
docker run -t --network=host -v $PWD:/src -e URL=$url -e SLOW_QUERY=$slowQuery --rm -i loadimpact/k6:master run --vus $vus --duration $duration src/$testcase.js
}
run "$@"

View File

@@ -18,21 +18,14 @@ bulkAlertingDashboard() {
requiresJsonnet
jsonnet -o "bulk_alerting_dashboards/bulk_alerting_datasources.yaml" ./bulk_alerting_dashboards/datasources.jsonnet
COUNTER=1
DS=1
MAX=1000
COUNTER=0
MAX=100
while [ $COUNTER -lt $MAX ]; do
jsonnet -o "bulk_alerting_dashboards/alerting_dashboard${COUNTER}.json" \
-e "local bulkDash = import 'bulk_alerting_dashboards/dashboard.libsonnet'; bulkDash.alertingDashboard(${COUNTER}, ${DS})"
jsonnet -o "bulk_alerting_dashboards/alerting_dashboard${COUNTER}.json" -e "local bulkDash = import 'bulk_alerting_dashboards/bulkdash_alerting.jsonnet'; bulkDash + { uid: 'bd-${COUNTER}', title: 'alerting-title-${COUNTER}' }"
let COUNTER=COUNTER+1
let DS=COUNTER/10
let DS=DS+1
done
ln -s -f ../../../devenv/bulk_alerting_dashboards/bulk_alerting_dashboards.yaml ../conf/provisioning/dashboards/custom.yaml
ln -s -f ../../../devenv/bulk_alerting_dashboards/bulk_alerting_datasources.yaml ../conf/provisioning/datasources/custom.yaml
}
requiresJsonnet() {

View File

@@ -1,11 +1,12 @@
.PHONY: docs docs-test
IMAGE = grafana/docs-base:latest
.PHONY: docs docs-no-pull docs-test
docs:
docker pull ${IMAGE}
docker run -v $(shell pwd)/sources:/hugo/content/docs/grafana/latest -p 3002:3002 --rm -it $(IMAGE) /bin/bash -c 'make server'
docker pull grafana/docs-base:latest
docker run -v $(PWD)/sources:/hugo/content/docs/grafana/latest -p 3002:3002 --rm -it grafana/docs-base:latest /bin/bash -c 'npm i && make webpack && make docs-menu && hugo server -p 3002 -D --ignoreCache --baseUrl http://localhost:3002 --bind 0.0.0.0'
docs-no-pull:
docker run -v $(PWD)/sources:/hugo/content/docs/grafana/latest -p 3002:3002 --rm -it grafana/docs-base:latest /bin/bash -c 'make docs-menu && hugo server -p 3002 -D --ignoreCache --baseUrl http://localhost:3002 --bind 0.0.0.0'
docs-test:
docker pull ${IMAGE}
docker run -v $(shell pwd)/sources:/hugo/content/docs/grafana/latest --rm -it $(IMAGE) /bin/bash -c 'make prod'
docker pull grafana/docs-base:latest
docker run -v $(PWD)/sources:/hugo/content/docs/grafana/latest --rm -it grafana/docs-base:latest /bin/bash -c 'npm i && make prod'

View File

@@ -8,8 +8,7 @@ aliases = ["/docs/grafana/v1.1", "/docs/grafana/latest/guides/reference/admin",
# Grafana documentation
## Installing Grafana
<h2>Installing Grafana</h2>
<div class="nav-cards">
<a href="{{< relref "installation/debian.md" >}}" class="nav-cards__item nav-cards__item--install">
<div class="nav-cards__icon fa fa-linux">
@@ -27,8 +26,8 @@ aliases = ["/docs/grafana/v1.1", "/docs/grafana/latest/guides/reference/admin",
<h5>Install on Windows</h5>
</a>
<a href="{{< relref "installation/docker.md" >}}" class="nav-cards__item nav-cards__item--install">
<img src="/static/img/logos/logo-docker.svg">
<h5>Run Docker image</h5>
<h4>Run Docker image</h4>
<p>Run Grafana on a Docker image.</p>
</a>
<a href="https://grafana.com/cloud/grafana" class="nav-cards__item nav-cards__item--install">
<div class="nav-cards__icon fa fa-cloud">
@@ -42,14 +41,14 @@ aliases = ["/docs/grafana/v1.1", "/docs/grafana/latest/guides/reference/admin",
</a>
</div>
## Guides
<h2>Guides</h2>
<div class="nav-cards">
<a href="{{< relref "getting-started/what-is-grafana.md" >}}" class="nav-cards__item nav-cards__item--guide">
<a href="{{< relref "guides/what-is-grafana.md" >}}" class="nav-cards__item nav-cards__item--guide">
<h4>What is Grafana?</h4>
<p>Get an overview of Grafana's key features.</p>
</a>
<a href="{{< relref "getting-started/getting-started.md" >}}" class="nav-cards__item nav-cards__item--guide">
<a href="{{< relref "guides/getting_started.md" >}}" class="nav-cards__item nav-cards__item--guide">
<h4>Getting started</h4>
<p>Learn the basics of using Grafana.</p>
</a>
@@ -57,7 +56,7 @@ aliases = ["/docs/grafana/v1.1", "/docs/grafana/latest/guides/reference/admin",
<h4>Configure Grafana</h4>
<p>Review the configuration and setup options.</p>
</a>
<a href="{{< relref "getting-started/timeseries.md" >}}" class="nav-cards__item nav-cards__item--guide">
<a href="{{< relref "guides/timeseries.md" >}}" class="nav-cards__item nav-cards__item--guide">
<h4>Intro to time series</h4>
<p>Learn about time series data.</p>
</a>
@@ -72,8 +71,7 @@ aliases = ["/docs/grafana/v1.1", "/docs/grafana/latest/guides/reference/admin",
</div>
## Data source guides
<h2>Data source guides</h2>
<div class="nav-cards">
<a href="{{< relref "features/datasources/graphite.md" >}}" class="nav-cards__item nav-cards__item--ds">
<img src="/img/docs/logos/icon_graphite.svg" >

View File

@@ -112,7 +112,7 @@ grafana-cli --debug plugins install <plugin-id>
`--configOverrides` is a command line argument that acts like an environmental variable override.
For example, you can use it to redirect logging to another file (maybe to log plugin installations in a service like Hosted Grafana) or when resetting the admin password and you have non-default values for some important config value (like where the database is located).
For example, you can use it to redirect logging to another file (maybe to log plugin installs in a service like Hosted Grafana) or when resetting the admin password and you have non-default values for some important config value (like where the database is located).
**Example:**
```bash

View File

@@ -12,7 +12,7 @@ weight = 8
Grafana supports automatic rendering of panels and dashboards as PNG images. This allows Grafana to automatically generate images of your panels to include in [alert notifications]({{< relref "../alerting/notifications.md" >}}).
While an image is being rendered, the PNG image is temporarily written to the file system. When the image is rendered, the PNG image is temporarily written to the `png` folder in the Grafana `data` folder.
When an image is being rendered the PNG-image is temporarily written to the file system. When an image is rendered, the PNG image is temporary written to the `png` folder in the Grafana `data` folder.
A background job runs every 10 minutes and removes temporary images. You can configure how long an image should be stored before being removed by configuring the [temp-data-lifetime]({{< relref "../installation/configuration/#temp-data-lifetime" >}}) setting.
@@ -108,7 +108,7 @@ The following example describes how to build and run the remote HTTP rendering s
## PhantomJS
> Starting from Grafana v7.0.0, all PhantomJS support has been removed. Please use the Grafana Image Renderer plugin or remote rendering service.
> PhantomJS is deprecated since Grafana v6.4 and will be removed in a future release. Please migrate to the Grafana Image Renderer plugin or remote rendering service.
## Troubleshoot image rendering
@@ -156,7 +156,7 @@ libx11-6 libx11-xcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3
**Centos:**
On a minimal Centos installation, the following dependencies have been confirmed as needed for the image rendering to function:
On a minimal Centos install the following dependencies have been confirmed as needed for the image rendering to function:
```bash
libXcomposite libXdamage libXtst cups libXScrnSaver pango atk adwaita-cursor-theme adwaita-icon-theme at at-spi2-atk at-spi2-core cairo-gobject colord-libs dconf desktop-file-utils ed emacs-filesystem gdk-pixbuf2 glib-networking gnutls gsettings-desktop-schemas gtk-update-icon-cache gtk3 hicolor-icon-theme jasper-libs json-glib libappindicator-gtk3 libdbusmenu libdbusmenu-gtk3 libepoxy liberation-fonts liberation-narrow-fonts liberation-sans-fonts liberation-serif-fonts libgusb libindicator-gtk3 libmodman libproxy libsoup libwayland-cursor libwayland-egl libxkbcommon m4 mailx nettle patch psmisc redhat-lsb-core redhat-lsb-submod-security rest spax time trousers xdg-utils xkeyboard-config
@@ -164,7 +164,7 @@ libXcomposite libXdamage libXtst cups libXScrnSaver pango atk adwaita-cursor-the
### Certificate signed by internal certificate authorities
In many cases, Grafana runs on internal servers and uses certificates that have not been signed by a CA ([Certificate Authority](https://en.wikipedia.org/wiki/Certificate_authority)) known to Chrome, and therefore cannot be validated. Chrome internally uses NSS ([Network Security Services](https://en.wikipedia.org/wiki/Network_Security_Services)) for cryptogtraphic operations such as the validation of certificates.
In many cases Grafana, runs on internal servers and uses certificates that have not been signed by a CA ([Certificate Authority](https://en.wikipedia.org/wiki/Certificate_authority)) known to Chrome, and therefore cannot be validated. Chrome internally uses NSS ([Network Security Services](https://en.wikipedia.org/wiki/Network_Security_Services)) for cryptogtraphic operations such as the validation of certificates.
If you are using the Grafana Image Renderer with a Grafana server that uses a certificate signed by such a custom CA (for example a company-internal CA), rendering images will fail and you will see messages like this in the Grafana log:

View File

@@ -1,5 +1,5 @@
+++
title = "Internal Grafana metrics"
title = "Internal metrics"
description = "Internal metrics exposed by Grafana"
keywords = ["grafana", "metrics", "internal metrics"]
type = "docs"
@@ -8,87 +8,8 @@ parent = "admin"
weight = 8
+++
# Internal Grafana metrics
# Internal metrics
Grafana collects some metrics about itself internally. Grafana supports pushing metrics to Graphite or exposing them to be scraped by Prometheus.
Grafana collects some metrics about itself internally. Currently, Grafana supports pushing metrics to Graphite or exposing them to be scraped by Prometheus.
For more information about configuration options related to Grafana metrics, refer to [metrics]({{< relref "../installation/configuration/#metrics" >}}) and [metrics.graphite]({{< relref "../installation/configuration/#metrics-graphite" >}}) in [Configuration]({{< relref "../installation/configuration.md" >}}).
## Available metrics
When enabled, Grafana exposes a number of metrics, including:
* Active Grafana instances
* Number of dashboards, users, and playlists
* HTTP status codes
* Requests by routing group
* Grafana active alerts
* Grafana performance
## Pull metrics from Grafana into Prometheus
These instructions assume you have already added Prometheus as a data source in Grafana.
1. Enable Prometheus to scrape metrics from Grafana. In your configuration file (`grafana.ini` or `custom.ini` depending on your operating system) remove the semicolon to enable the following configuration options:
```
# Metrics available at HTTP API Url /metrics
[metrics]
# Disable / Enable internal metrics
enabled = true
# Disable total stats (stat_totals_*) metrics to be generated
disable_total_stats = false
```
1. (optional) If you want to require authorization to view the metrics endpoint, then uncomment and set the following options:
```
basic_auth_username =
basic_auth_password =
```
1. Restart Grafana. Grafana now exposes metrics at http://localhost:3000/metrics.
1. Add the job to your prometheus.yml file.
Example:
```
- job_name: 'grafana_metrics'
scrape_interval: 15s
scrape_timeout: 5s
static_configs:
- targets: ['localhost:3000']
```
1. Restart Prometheus. Your new job should appear on the Targets tab.
1. In Grafana, hover your mouse over the **Configuration** (gear) icon on the left sidebar and then click **Data Sources**.
1. Select the **Prometheus** data source.
1. On the Dashboards tab, **Import** the Grafana metrics dashboard. All scraped Grafana metrics are available in the dashboard.
## View Grafana metrics in Graphite
These instructions assume you have already added Graphite as a data source in Grafana.
1. Enable sending metrics to Graphite. In your configuration file (`grafana.ini` or `custom.ini` depending on your operating system) remove the semicolon to enable the following configuration options:
```
# Metrics available at HTTP API Url /metrics
[metrics]
# Disable / Enable internal metrics
enabled = true
# Disable total stats (stat_totals_*) metrics to be generated
disable_total_stats = false
```
1. Enable [metrics.graphite] options:
```
# Send internal metrics to Graphite
[metrics.graphite]
# Enable by setting the address setting (ex localhost:2003)
address = <hostname or ip>:<port#>
prefix = prod.grafana.%(instance_name)s.
```
1. Restart Grafana. Grafana now exposes metrics at http://localhost:3000/metrics and sends them to the Graphite location you specified.
To emit internal metrics you have to enable the option under the [metrics] section in your [grafana.ini](http://docs.grafana.org/installation/configuration/#enabled-6) config file. If you want to push metrics to Graphite, you must also configure the [metrics.graphite](http://docs.grafana.org/installation/configuration/#metrics-graphite) section.

View File

@@ -51,7 +51,7 @@ If you have a literal `$` in your value and want to avoid interpolation, `$$` ca
## Configuration Management Tools
Currently we do not provide any scripts/manifests for configuring Grafana. Rather than spending time learning and creating scripts/manifests for each tool, we think our time is better spent making Grafana easier to provision. Therefore, we heavily rely on the expertise of the community.
Currently we do not provide any scripts/manifests for configuring Grafana. Rather than spending time learning and creating scripts/manifests for each tool, we think our time is better spent making Grafana easier to provision. Therefore, we heavily relay on the expertise of the community.
Tool | Project
-----|------------
@@ -93,8 +93,6 @@ datasources:
access: proxy
# <int> org id. will default to orgId 1 if not specified
orgId: 1
# <string> custom UID which can be used to reference this datasource in other parts of the configuration, if not specified will be generated automatically
uid: my_unique_uid
# <string> url
url: http://localhost:8080
# <string> Deprecated, use secureJsonData.password
@@ -162,9 +160,6 @@ Since not all datasources have the same configuration settings we only have the
| tsdbVersion | string | OpenTSDB | Version |
| tsdbResolution | string | OpenTSDB | Resolution |
| sslmode | string | PostgreSQL | SSLmode. 'disable', 'require', 'verify-ca' or 'verify-full' |
| sslRootCertFile | string | PostgreSQL | SSL server root certificate file, must be readable by the Grafana user |
| sslCertFile | string | PostgreSQL | SSL client certificate file, must be readable by the Grafana user |
| sslKeyFile | string | PostgreSQL | SSL client key file, must be readable by *only* the Grafana user |
| encrypt | string | MSSQL | Connection SSL encryption handling. 'disable', 'false' or 'true' |
| postgresVersion | number | PostgreSQL | Postgres version as a number (903/904/905/906/1000) meaning v9.3, v9.4, ..., v10 |
| timescaledb | boolean | PostgreSQL | Enable usage of TimescaleDB extension |
@@ -206,9 +201,9 @@ datasources:
httpHeaderValue2: "Bearer XXXXXXXXX"
```
## Dashboards
### Dashboards
It's possible to manage dashboards in Grafana by adding one or more yaml config files in the [`provisioning/dashboards`]({{< relref "../installation/configuration.md" >}}) directory. Each config file can contain a list of `dashboards providers` that will load dashboards into Grafana from the local filesystem.
It's possible to manage dashboards in Grafana by adding one or more yaml config files in the [`provisioning/dashboards`](/installation/configuration/#provisioning) directory. Each config file can contain a list of `dashboards providers` that will load dashboards into Grafana from the local filesystem.
The dashboard provider config file looks somewhat like this:
@@ -245,9 +240,9 @@ When Grafana starts, it will update/insert all dashboards available in the confi
It's possible to make changes to a provisioned dashboard in the Grafana UI. However, it is not possible to automatically save the changes back to the provisioning source.
If `allowUiUpdates` is set to `true` and you make changes to a provisioned dashboard, you can `Save` the dashboard then changes will be persisted to the Grafana database.
> **Note:**
> **Note.**
> If a provisioned dashboard is saved from the UI and then later updated from the source, the dashboard stored in the database will always be overwritten. The `version` property in the JSON file will not affect this, even if it is lower than the existing dashboard.
>
>
> If a provisioned dashboard is saved from the UI and the source is removed, the dashboard stored in the database will be deleted unless the configuration option `disableDeletion` is set to true.
If `allowUiUpdates` is configured to `false`, you are not able to make changes to a provisioned dashboard. When you click `Save`, Grafana brings up a *Cannot save provisioned dashboard* dialog. The screenshot below illustrates this behavior.
@@ -255,7 +250,7 @@ If `allowUiUpdates` is configured to `false`, you are not able to make changes t
Grafana offers options to export the JSON definition of a dashboard. Either `Copy JSON to Clipboard` or `Save JSON to file` can help you synchronize your dashboard changes back to the provisioning source.
Note: The JSON definition in the input field when using `Copy JSON to Clipboard` or `Save JSON to file` will have the `id` field automatically removed to aid the provisioning workflow.
{{< docs-imagebox img="/img/docs/v51/provisioning_cannot_save_dashboard.png" max-width="500px" class="docs-image--no-shadow" >}}
### Reusable Dashboard URLs
@@ -403,8 +398,6 @@ The following sections detail the supported settings for each alert notification
| Name |
| ---- |
| url |
| basicAuthUser |
| basicAuthPassword |
#### Alert notification `teams`
@@ -422,7 +415,6 @@ The following sections detail the supported settings for each alert notification
| Name |
| ---- |
| singleEmail |
| addresses |
#### Alert notification `hipchat`
@@ -471,3 +463,4 @@ The following sections detail the supported settings for each alert notification
| Name |
| ---- |
| url |

View File

@@ -71,19 +71,14 @@ external image destination if available or fallback to attaching the image to th
Be aware that if you use the `local` image storage email servers and clients might not be
able to access the image.
Setting | Description
---------- | -----------
Single email | Send a single email to all recipients. Disabled per default.
Addresses | Email addresses to recipients. You can enter multiple email addresses using a ";" separator.
### Slack
{{< imgbox max-width="40%" img="/img/docs/v4/slack_notification.png" caption="Alerting Slack Notification" >}}
To set up Slack, you need to configure an incoming Slack webhook URL. You can follow
[Sending messages using Incoming Webhooks](https://api.slack.com/incoming-webhooks) on how to do that. If you want to include screenshots of the
firing alerts in the Slack messages you have to configure either the [external image destination](#external-image-store)
in Grafana or a bot integration via Slack Apps. Follow Slack's guide to set up a bot integration and use the token
To set up Slack, you need to configure an incoming Slack webhook URL. You can follow
[their guide](https://api.slack.com/incoming-webhooks) on how to do that. If you want to include screenshots of the
firing alerts in the Slack messages you have to configure either the [external image destination](#external-image-store)
in Grafana, or a bot integration via Slack Apps. Follow Slack's guide to set up a bot integration and use the token
provided (https://api.slack.com/bot-users), which starts with "xoxb".
Setting | Description
@@ -110,7 +105,7 @@ Integration Key | Integration key for PagerDuty.
Severity | Level for dynamic notifications, default is `critical`
Auto resolve incidents | Resolve incidents in PagerDuty once the alert goes back to ok
**Note:** The tags `Severity`, `Class`, `Group`, and `Component` have special meaning in the [Pagerduty Common Event Format - PD-CEF](https://support.pagerduty.com/docs/pd-cef). If an alert panel defines these tag keys, then they are transposed to the root of the event sent to Pagerduty. This means they will be available within the Pagerduty UI and Filtering tools. A Severity tag set on an alert overrides the global Severity set on the notification channel if it's a valid level.
**Note:** The tags `Class`, `Group`, and `Component` have special meaning in the [Pagerduty Common Event Format - PD-CEF](https://support.pagerduty.com/docs/pd-cef). If an alert panel defines these tag keys they will be transposed to the root of the event sent to Pagerduty. This means they will be available within the Pagerduty UI and Filtering tools.
### Webhook
@@ -203,24 +198,25 @@ Prometheus Alertmanager | `prometheus-alertmanager` | yes, external only | yes
Pushover | `pushover` | yes | no
Sensu | `sensu` | yes, external only | no
Slack | `slack` | yes | no
Squadcast | `webhook` | no | no
Telegram | `telegram` | yes | no
Threema | `threema` | yes, external only | no
VictorOps | `victorops` | yes, external only | no
Webhook | `webhook` | yes, external only | yes
## Enable images in notifications {#external-image-store}
# Enable images in notifications {#external-image-store}
Grafana can render the panel associated with the alert rule as a PNG image and include that in the notification. Read more about the requirements and how to configure
Grafana can render the panel associated with the alert rule as a PNG image and include that in the notification. Read more about the requirements and how to configure
[image rendering]({{< relref "../administration/image_rendering/" >}}).
Most Notification Channels require that this image be publicly accessible (Slack and PagerDuty for example). In order to include images in alert notifications, Grafana can upload the image to an image store. It currently supports
Amazon S3, Webdav, Google Cloud Storage and Azure Blob Storage. So to set that up you need to configure the [external image uploader]({{< relref "../installation/configuration/#external-image-storage" >}}) in your grafana-server ini config file.
Be aware that some notifiers require public access to the image to be able to include it in the notification. So make sure to enable public access to the images. If you're using local image uploader, your Grafana instance need to be accessible by the internet.
Be aware that some notifiers requires public access to the image to be able to include it in the notification. So make sure to enable public access to the images. If you're using local image uploader, your Grafana instance need to be accessible by the internet.
Notification services which need public image access are marked as 'external only'.
## Use alert rule tags in notifications {#alert-rule-tags}
# Use alert rule tags in notifications {#alert-rule-tags}
> Only available in Grafana v6.3+.
@@ -230,7 +226,7 @@ It currently supports only the Prometheus Alertmanager notifier.
This is an optional feature. You can get notifications without using alert rule tags.
## Configure the link back to Grafana from alert notifications
# Configure the link back to Grafana from alert notifications
All alert notifications contain a link back to the triggered alert in the Grafana instance.
This URL is based on the [domain]({{< relref "../installation/configuration/#domain" >}}) setting in Grafana.

View File

@@ -11,7 +11,7 @@ weight = 1
# Alerting Engine and Rules Guide
Alerting in Grafana allows you to attach rules to your dashboard panels. When you save the dashboard,
Alerting in Grafana allows you to attach rules to your dashboard panels. When you save the dashboard
Grafana will extract the alert rules into a separate alert rule storage and schedule them for evaluation.
{{< imgbox max-width="40%" img="/img/docs/v4/drag_handles_gif.gif" caption="Alerting overview" >}}

View File

@@ -122,12 +122,6 @@ only give access to members of the group `example` which has Id `8bab1c86-8fba-3
allowed_groups = 8bab1c86-8fba-33e5-2089-1d1c80ec267d
```
You'll need to ensure that you've [enabled group attributes](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-fed-group-claims#configure-the-azure-ad-application-registration-for-group-attributes) in your Azure AD Application Registration manifest file (Azure Portal -> Azure Active Directory -> Application Registrations -> Select Application -> Manifest)
```json
"groupMembershipClaims": "ApplicationGroup"
```
The `allowed_domains` option limits access to the users belonging to the specific domains. Domains should be separated by space or comma.
```ini

View File

@@ -54,6 +54,24 @@ Check for the presence of a role using the [JMESPath](http://jmespath.org/exampl
See [JMESPath examples](#jmespath-examples) for more information.
## Set up OAuth2 with Okta
First set up Grafana as an OpenId client "webapplication" in Okta. Then set the Base URIs to `https://<grafana domain>/` and set the Login redirect URIs to `https://<grafana domain>/login/generic_oauth`.
Finally set up the generic oauth module like this:
```bash
[auth.generic_oauth]
name = Okta
enabled = true
scopes = openid profile email
client_id = <okta application Client ID>
client_secret = <okta application Client Secret>
auth_url = https://<okta domain>/oauth2/v1/authorize
token_url = https://<okta domain>/oauth2/v1/token
api_url = https://<okta domain>/oauth2/v1/userinfo
```
## Set up OAuth2 with Bitbucket
```bash
@@ -132,6 +150,46 @@ allowed_organizations =
api_url = https://<domain>/userinfo
```
## Set up OAuth2 with Azure Active Directory
1. Log in to portal.azure.com and click "Azure Active Directory" in the side menu, then click the "Properties" sub-menu item.
2. Copy the "Directory ID", this is needed for setting URLs later
3. Click "App Registrations" and add a new application registration:
- Name: Grafana
- Application type: Web app / API
- Sign-on URL: `https://<grafana domain>/login/generic_oauth`
4. Click the name of the new application to open the application details page.
5. Note down the "Application ID", this will be the OAuth client id.
6. Click "Certificates & secrets" and add a new entry under Client secrets
- Description: Grafana OAuth
- Expires: Never
7. Click Add then copy the key value, this will be the OAuth client secret.
8. Configure Grafana as follows:
```bash
[auth.generic_oauth]
name = Azure AD
enabled = true
allow_sign_up = true
client_id = <application id>
client_secret = <key value>
scopes = openid email name
auth_url = https://login.microsoftonline.com/<directory id>/oauth2/authorize
token_url = https://login.microsoftonline.com/<directory id>/oauth2/token
api_url =
team_ids =
allowed_organizations =
```
> Note: It's important to ensure that the [root_url]({{< relref "../installation/configuration/#root-url" >}}) in Grafana is set in your Azure Application Reply URLs (App -> Settings -> Reply URLs)
## Set up OAuth2 with Centrify
1. Create a new Custom OpenID Connect application configuration in the Centrify dashboard.

View File

@@ -92,14 +92,6 @@ member_of = "memberOf"
email = "email"
```
### Using environment variables
You can interpolate variables in the TOML config from environment variables. For instance, you could externalize your `bind_password` that way:
```bash
bind_password = "${LDAP_ADMIN_PASSWORD}"
```
## LDAP Debug View
> Only available in Grafana v6.4+

View File

@@ -1,89 +0,0 @@
+++
title = "Okta OAuth2 authentication"
description = "Grafana Okta OAuth Guide "
keywords = ["grafana", "configuration", "documentation", "oauth"]
type = "docs"
[menu.docs]
name = "Okta"
identifier = "okta_oauth2"
parent = "authentication"
weight = 3
+++
# Okta OAuth2 authentication
> Only available in Grafana v7.0+
The Okta authentication allows your Grafana users to log in by using an external Okta authorization server.
## Create an Okta application
Before you can sign a user in, you need to create an Okta application from the Okta Developer Console.
1. Log in to the [Okta portal](https://login.okta.com/).
1. Go to Admin and then select **Developer Console**.
1. Select **Applications**, then **Add Application**.
1. Pick **Web** as the platform.
1. Enter a name for your application (or leave the default value).
1. Add the **Base URI** of your application, such as https://grafana.example.com.
1. Enter values for the **Login redirect URI**. Use **Base URI** and append it with `/login/okta`, for example: https://grafana.example.com/login/okta.
1. Click **Done** to finish creating the Okta application.
## Enable Okta Oauth in Grafana
1. Add the following to the [Grafana configuration file]({{< relref "../installation/configuration.md#config-file-locations" >}}):
```ini
[auth.okta]
name = Okta
enabled = true
allow_sign_up = true
client_id = some_id
client_secret = some_secret
scopes = openid profile email groups
auth_url = https://<tenant-id>.okta.com/oauth2/v1/authorize
token_url = https://<tenant-id>.okta.com/oauth2/v1/token
api_url = https://<tenant-id>.okta.com/oauth2/v1/userinfo
allowed_domains =
allowed_groups =
role_attribute_path =
```
### Configure allowed groups and domains
To limit access to authenticated users that are members of one or more groups, set `allowed_groups`
to a comma- or space-separated list of Okta groups.
```ini
allowed_groups = Developers, Admins
```
The `allowed_domains` option limits access to the users belonging to the specific domains. Domains should be separated by space or comma.
```ini
allowed_domains = mycompany.com mycompany.org
```
### Map roles
Grafana can attempt to do role mapping through Okta OAuth. In order to achieve this, Grafana checks for the presence of a role using the [JMESPath](http://jmespath.org/examples.html) specified via the `role_attribute_path` configuration option.
Grafana uses JSON obtained from querying the `/userinfo` endpoint for the path lookup. The result after evaluating the `role_attribute_path` JMESPath expression needs to be a valid Grafana role, i.e. `Viewer`, `Editor` or `Admin`. Refer to [Organization roles]({{< relref "../permissions/organization_roles.md" >}}) for more information about roles and permissions in Grafana.
Read about how to [add custom claims](https://developer.okta.com/docs/guides/customize-tokens-returned-from-okta/add-custom-claim/) to the user info in Okta. Also, check Generic OAuth page for [JMESPath examples]({{< relref "generic-oauth.md/#jmespath-examples" >}}).
### Team Sync (Enterprise only)
Map your Okta groups to teams in Grafana so that your users will automatically be added to
the correct teams.
Okta groups can be referenced by group name, like `Admins`.
[Learn more about Team Sync]({{< relref "../enterprise/team-sync.md" >}})

View File

@@ -12,7 +12,7 @@ weight = 5
# Team sync
With Team Sync, you can set up synchronization between your auth provider's teams and teams in Grafana. This enables LDAP or GitHub OAuth users which are members
With the Team Sync it's possible to setup synchronization between your auth providers teams and teams in Grafana. This enables LDAP or GitHub OAuth users which are members
of certain teams/groups to automatically be added/removed as members to certain teams in Grafana. Currently the synchronization will only happen every
time a user logs in, unless LDAP is used together with active background synchronization that was added in Grafana 6.3.
@@ -23,4 +23,4 @@ This mechanism allows Grafana to remove an existing synchronized user from a tea
<div class="clearfix"></div>
> Team Sync is only available in Grafana Enterprise. For more information, refer to [Team sync]({{< relref "../enterprise/team-sync.md" >}}) in [Grafana Enterprise]({{< relref "../enterprise" >}}).
> Team Sync is only available in Grafana Enterprise. For more information, refer to [Team sync]({{< relref "../enterprise/team-sync.md" >}}) in [Grafana Enterprise]({{< relref "../enterprise" >}}).

View File

@@ -1,7 +0,0 @@
+++
title = "Dashboards"
type = "docs"
[menu.docs]
identifier = "dashboards"
weight = 4
+++

View File

@@ -1,4 +1,9 @@
+++
title = "Developers"
title = "Contribute"
description = "Contribute"
type = "docs"
[menu.docs]
name = "Contribute"
identifier = "contribute"
weight = 20
+++

View File

@@ -3,6 +3,9 @@ title = "Contributor License Agreement (CLA)"
description = "Contributor License Agreement (CLA)"
type = "docs"
aliases = ["/docs/grafana/latest/project/cla", "docs/contributing/cla.html"]
[menu.docs]
parent = "contribute"
weight = 1
+++
# Grafana Labs Contributor License Agreement

View File

@@ -1,43 +0,0 @@
+++
title = "Contribute to Grafana"
keywords = ["grafana", "documentation", "developers", "resources"]
type = "docs"
+++
# Contribute to Grafana
This page lists resources for developers who want to contribute to the Grafana software ecosystem or build plugins for Grafana.
##
General resources
These resources are useful for all developers.
* [Contributing to Grafana](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md): Start here to learn how you can contribute your skills to make Grafana even better.
* [Developer guide](https://github.com/grafana/grafana/blob/master/contribute/developer-guide.md): A guide to help you get started developing Grafana software, includes instructions for how to configure Grafana for development.
* [Contributing to documentation](https://github.com/grafana/grafana/blob/master/contribute/documentation.md): A guide to help you contribute to Grafana documentation, includes links to beginner-friendly issues.
* [Architecture guides](https://github.com/grafana/grafana/tree/master/contribute/architecture): These guides explain Grafanas background architecture.
* [Create a pull request](https://github.com/grafana/grafana/blob/master/contribute/create-pull-request.md): A guide for new contributors about how to create your first Grafana pull request.
* [REST APIs](https://grafana.com/docs/grafana/latest/http_api/) allow you to interact programmatically with the Grafana backend.
## Best practices and style
Our [style guides](https://github.com/grafana/grafana/tree/master/contribute/style-guides) outline Grafana style for frontend, backend, documentation, and more, including best practices. Please read through them before you start editing or coding!
* [Backend style guide](https://github.com/grafana/grafana/blob/master/contribute/style-guides/backend.md) explains how we want to write Go code in the future.
* [Documentation style guide](https://github.com/grafana/grafana/blob/master/contribute/style-guides/documentation-style-guide.md) applies to all documentation created for Grafana products.
* [End to end test framework](https://github.com/grafana/grafana/blob/master/contribute/style-guides/e2e.md) provides guidance for Grafana e2e tests.
* [Frontend style guide](https://github.com/grafana/grafana/blob/master/contribute/style-guides/frontend.md) provides rules and guidance on developing in React for Grafana.
* [Redux framework](https://github.com/grafana/grafana/blob/master/contribute/style-guides/redux.md) explains how Grafana handles Redux boilerplate code.
* [Styling Grafana](https://github.com/grafana/grafana/blob/master/contribute/style-guides/styling.md) expands on styling React components with Emotion.
* [Theming Grafana](https://github.com/grafana/grafana/blob/master/contribute/style-guides/themes.md) explains how to use themes and ThemeContext in Grafana code.

View File

@@ -0,0 +1,48 @@
+++
title = "Developer resources"
description = "Resources for Grafana developers"
keywords = ["grafana", "documentation", "developers", "resources"]
type = "docs"
[menu.docs]
name = "Grafana resources"
identifier = "Developer resources"
weight = 30
+++
# Developer resources
This page lists resources for developers who want to contribute to the Grafana software ecosystem or build plugins for Grafana.
##
General resources
These resources are useful for all developers.
* [Contributing to Grafana](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md): Start here to learn how you can contribute your skills to make Grafana even better.
* [Developer guide](https://github.com/grafana/grafana/blob/master/contribute/developer-guide.md): A guide to help you get started developing Grafana software, includes instructions for how to configure Grafana for development.
* [Contributing to documentation](https://github.com/grafana/grafana/blob/master/contribute/documentation.md): A guide to help you contribute to Grafana documentation, includes links to beginner-friendly issues.
* [Architecture guides](https://github.com/grafana/grafana/tree/master/contribute/architecture): These guides explain Grafanas background architecture.
* [Create a pull request](https://github.com/grafana/grafana/blob/master/contribute/create-pull-request.md): A guide for new contributors about how to create your first Grafana pull request.
* [REST APIs](https://grafana.com/docs/grafana/latest/http_api/) allow you to interact programmatically with the Grafana backend.
## Best practices and style
Our [style guides](https://github.com/grafana/grafana/tree/master/contribute/style-guides) outline Grafana style for frontend, backend, documentation, and more, including best practices. Please read through them before you start editing or coding!
* [Backend style guide](https://github.com/grafana/grafana/blob/master/contribute/style-guides/backend.md) explains how we want to write Go code in the future.
* [Documentation style guide](https://github.com/grafana/grafana/blob/master/contribute/style-guides/documentation-style-guide.md) applies to all documentation created for Grafana products.
* [End to end test framework](https://github.com/grafana/grafana/blob/master/contribute/style-guides/e2e.md) provides guidance for Grafana e2e tests.
* [Frontend style guide](https://github.com/grafana/grafana/blob/master/contribute/style-guides/frontend.md) provides rules and guidance on developing in React for Grafana.
* [Redux framework](https://github.com/grafana/grafana/blob/master/contribute/style-guides/redux.md) explains how Grafana handles Redux boilerplate code.
* [Styling Grafana](https://github.com/grafana/grafana/blob/master/contribute/style-guides/styling.md) expands on styling React components with Emotion.
* [Theming Grafana](https://github.com/grafana/grafana/blob/master/contribute/style-guides/themes.md) explains how to use themes and ThemeContext in Grafana code.

View File

@@ -1,67 +0,0 @@
+++
title = "Build a plugin"
type = "docs"
+++
# Build a plugin
For more information on the types of plugins you can build, refer to the [Plugin Overview]({{< relref "../../plugins/_index.md" >}}).
## Get started
The easiest way to start developing Grafana plugins is to use the [Grafana Toolkit](https://www.npmjs.com/package/@grafana/toolkit).
Open the terminal, and run the following command in your [plugin directory]({{< relref "../../installation/configuration/_index.md#plugins" >}}):
```bash
npx @grafana/toolkit plugin:create my-grafana-plugin
```
If you want a more guided introduction to plugin development, check out our tutorials:
- [Build a panel plugin]({{< relref "../../../../../tutorials/build-a-panel-plugin.md" >}})
- [Build a data source plugin]({{< relref "../../../../../tutorials/build-a-data-source-plugin.md" >}})
## Go further
Learn more about specific areas of plugin development.
### Concepts
Deepen your knowledge through a series of high-level overviews of plugin concepts.
- [Data frames]({{< relref "data-frames.md" >}})
- [Authentication for data source plugins]({{< relref "authentication.md" >}})
### UI library
Explore the many UI components in our [Grafana UI library](https://developers.grafana.com/ui).
### Tutorials
If you're looking to build your first plugin, check out these introductory tutorials:
- [Build a panel plugin]({{< relref "../../../../../tutorials/build-a-panel-plugin.md" >}})
- [Build a data source plugin]({{< relref "../../../../../tutorials/build-a-data-source-plugin.md" >}})
Ready to learn more? Check out our other tutorials:
- [Build a panel plugin with D3.js]({{< relref "../../../../../tutorials/build-a-panel-plugin-with-d3.md" >}})
### API reference
Learn more about Grafana options and packages.
#### Metadata
- [Plugin metadata]({{< relref "metadata.md" >}})
#### Typescript
- [Grafana Data]({{< relref "../../packages_api/data/_index.md" >}})
- [Grafana Runtime]({{< relref "../../packages_api/runtime/_index.md" >}})
- [Grafana UI]({{< relref "../../packages_api/ui/_index.md" >}})
#### Go
- [Grafana Plugin SDK](https://pkg.go.dev/mod/github.com/grafana/grafana-plugin-sdk-go?tab=overview)

View File

@@ -1,137 +0,0 @@
+++
title = "Authentication for data source plugins"
type = "docs"
aliases = ["/docs/grafana/latest/plugins/developing/auth-for-datasources/"]
+++
# Authentication for data source plugins
Grafana has a proxy feature that proxies all data requests through the Grafana backend. The main benefit of using the proxy is secure handling of credentials when authenticating against an external/third-party API. The Grafana proxy also adds [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) headers to the proxied requests.
The proxy supports:
- [authentication with HTTP Headers]({{< relref "#api-key-http-header-authentication" >}}).
- [token authentication]({{< relref "#how-token-authentication-works" >}}) and can automatically renew a token for the user when the token expires.
## How the proxy works
The user saves the API key/password on the plugin config page and it is encrypted (using the `secureJsonData` feature) and saved in the Grafana database. When a request from the data source is made, the Grafana proxy will:
1. Intercept the original request sent from the data source plugin.
1. Load the `secureJsonData` data from the database and decrypt the API key or password on the Grafana backend.
1. If using token authentication, carry out authentication and generate an OAuth token that will be added as an `Authorization` HTTP header to the requests (or alternatively it will add a HTTP header with the API key).
1. Renew the token if it has expired.
1. After adding CORS headers and authorization headers, forward the request to the external API.
This means that users that access the data source config page cannot access the API key or password after they have saved it the first time and that no secret keys are sent in plain text through the browser where they can be spied on.
For backend authentication to work, the external/third-party API must either have an OAuth endpoint or that the API accepts an API key as a HTTP header for authentication.
## Encrypting sensitive data
When a user saves a password or secret with your data source plugin's Config page, then you can save data in an encrypted blob in the Grafana database called `secureJsonData`. Any data saved in the blob is encrypted by Grafana and can only be decrypted by the Grafana server on the backend. This means once a password is saved, no sensitive data is sent to the browser. If the password is saved in the `jsonData` blob or the `password` field then it is unencrypted and anyone with Admin access (with the help of Chrome Developer Tools) can read it.
This is an example of using the `secureJsonData` blob to save a property called `password` in a html input:
```html
<input type="password" class="gf-form-input" ng-model="ctrl.current.secureJsonData.password" placeholder="password" />
```
## Plugin routes
A plugin route describes where the intercepted request should be forwarded to and how to authenticate for the external API. You can define multiple routes that can match multiple external API endpoints.
You specify routes in the `plugin.json` file for your data source plugin. [Here is an example](https://github.com/grafana/azure-monitor-datasource/blob/d74c82145c0a4af07a7e96cc8dde231bfd449bd9/src/plugin.json#L30-L95) with lots of routes (though most plugins will just have one route).
When you build your URL to the third-party API in your data source class, the URL should start with the text specified in the path field for a route. The proxy will strip out the path text and replace it with the value in the URL field.
### Simple plugin route example
- If my code makes a call to URL `azuremonitor/foo/bar` with this code:
```js
this.backendSrv.datasourceRequest({
url: url,
method: "GET",
});
```
- and the plugin has this route:
```json
"routes": [{
"path": "azuremonitor",
"method": "GET",
"url": "https://management.azure.com"
}]
```
- then the Grafana proxy will transform the URL from the original request into `https://management.azure.com/foo/bar`
- finally, it will add CORS headers and forward the request to the new URL. This example does not do any authentication.
The `method` parameter is optional. It can be set to a specific HTTP verb to provide more fine-grained control. For example you might have two plugin routes, one for GET requests and one for POST requests.
### Dynamic routes
When using routes, you can also reference a variable stored in JsonData or SecureJsonData which is interpolated (replacing the variable text with a value) when the data source makes a request to the proxy. These are variables that were entered by the user on the data source configuration page and saved in the Grafana database.
In this example, the value for `dynamicUrl` comes from the JsonData blob and the api key's value is set from the SecureJsonData blob. The `urlParams` field is for query string parameters for HTTP GET requests.
```json
"routes": [
{
"path": "custom/api/v5/*",
"method": "GET",
"url": "{{.JsonData.dynamicUrl}}",
"urlParams": [
{"name": "apiKey", "content": "{{.SecureJsonData.apiKey}}"}
]
}
]
```
Given that:
- `JsonData.dynamicUrl` has the value `http://example.com/api`
- `SecureJsonData.apiKey` has the value `secretKey`
a call to the URL: `custom/api/v5/some/path`
will be proxied to the following URL: `http://example.com/api/some/path?apiKey=secretKey`
An app using this feature can be found [here](https://github.com/grafana/kentik-app).
## API key/HTTP header authentication
Some third-party API's accept a HTTP Header for authentication. The [example](https://github.com/grafana/azure-monitor-datasource/blob/d74c82145c0a4af07a7e96cc8dde231bfd449bd9/src/plugin.json#L91-L93) below has a `headers` section that defines the name of the HTTP Header that the API expects and it uses the `SecureJSONData` blob to fetch an encrypted API key. The Grafana server proxy will decrypt the key, add the `X-API-Key` header to the request and forward it to the third-party API.
```json
{
"path": "appinsights",
"method": "GET",
"url": "https://api.applicationinsights.io",
"headers": [{ "name": "X-API-Key", "content": "{{.SecureJsonData.appInsightsApiKey}}" }]
}
```
## How token authentication works
The token auth section in the `plugin.json` file looks like this:
```json
"tokenAuth": {
"url": "https://login.microsoftonline.com/{{.JsonData.tenantId}}/oauth2/token",
"params": {
"grant_type": "client_credentials",
"client_id": "{{.JsonData.clientId}}",
"client_secret": "{{.SecureJsonData.clientSecret}}",
"resource": "https://management.azure.com/"
}
}
```
This interpolates in data from both `jsonData` and `secureJsonData` to generate the token request to the third-party API. It is common for tokens to have a short expiry period (30 minutes). The Grafana proxy automatically renews the token if it has expired.
## Always restart the Grafana server after route changes
The plugin.json files are only loaded when the Grafana server starts so when a route is added or changed then the Grafana server has to be restarted for the changes to take effect.

View File

@@ -1,285 +0,0 @@
+++
title = "Backend plugins"
keywords = ["grafana", "plugins", "backend", "plugin", "backend-plugins", "documentation"]
type = "docs"
aliases = ["/docs/grafana/latest/plugins/developing/backend-plugins-guide/"]
+++
# Backend plugins
Grafana added support for plugins in Grafana 3.0 and this enabled the Grafana community to create panel plugins and data source plugins. It was wildly successful and has made Grafana much more useful as you can integrate it with anything and do any type of custom visualization that you want. However, these plugin hooks are on the frontend only and we also want to provide hooks into the Grafana backend to allow the community to extend and improve Grafana in new ways.
Once Grafana introduced the alerting feature, external data source plugins needed a backend component for the Grafana server to execute queries for evaluating alert rules (as the alerting engine cannot call frontend JavaScript code). So the obvious first backend plugin type is the **Datasource backend plugin** and it is a new component for an existing data source plugin. This new plugin type will enable alerting for external data source plugins but can also be used for achieving different goals such as query caching, request proxying, custom authentication methods, and more.
## Grafana's Backend Plugin System
The backend plugin feature is implemented with the [HashiCorp plugin system](https://github.com/hashicorp/go-plugin) which is a Go plugin system over RPC. Grafana server launches each plugin as a subprocess and communicates with it over RPC. This approach has a number of benefits:
- Plugins can't crash your grafana process: a panic in a plugin doesn't panic the server.
- Plugins are easy to develop: just write a Go application and `go build` (or use any other language which supports gRPC).
- Plugins can be relatively secure: The plugin only has access to the interfaces and args given to it, not to the entire memory space of the process.
## Data source plugin interface
The plugin interface is very simple and described as a Go interface type in [Grafana](https://github.com/grafana/grafana/blob/6724aaeff9a332dc73b4ee0f8abe0621f7253142/pkg/tsdb/query_endpoint.go#L10-L12) and as a general [RPC service](https://github.com/grafana/grafana-plugin-model/blob/84176c64269d8060f99e750ee8aba6f062753336/datasource.proto#L96-L98) in the corresponding `.proto` (protocol buffer file):
```go
type TsdbQueryEndpoint interface {
Query(ctx context.Context, ds *models.DataSource, query *TsdbQuery) (*Response, error)
}
```
```protobuf
service DatasourcePlugin {
rpc Query(DatasourceRequest) returns (DatasourceResponse);
}
```
Thus, a datasource plugin should only implement the `Query()` method.
## Introduction to building a backend component for a plugin
The [Simple JSON backend](https://github.com/grafana/simple-json-backend-datasource) data source is a good example of writing a simple backend plugin in Go. Let's take a look at some key points.
### Metadata
The plugin needs to know it has a backend component, this is done in the `plugin.json` file by setting two fields: `backend` and `executable`. If you want to enable alerting for your data source, set the `alerting` field to `true` as well.
```json
{
"id": "grafana-simple-json-backend-datasource",
"name": "Simple Json backend",
"type": "datasource",
"metrics": true,
"annotations": true,
"backend": true,
"alerting": true,
"executable": "simple-json-plugin",
...
}
```
`executable` should be the the the first part of the binary filename. The actual binary filename has 3 possible endings:
- \_linux_amd64
- \_darwin_amd64
- \_windows_amd64.exe
When Grafana loads the plugin binary, it uses the executable field plus the current OS (Grafana knows which OS it is running on) to load in the correct version of the plugin. So in Simple JSON the executable field is `simple-json-plugin` and the 3 binaries are named:
- `simple-json-plugin_darwin_amd64`
- `simple-json-plugin_linux_amd64`
- `simple-json-plugin_windows_amd64.exe`
The resulting plugin directory will look like this:
```text
simple-json-backend-datasource/
|-- dist/
| |-- partials/
| |-- module.js
| |-- plugin.json
| |-- simple-json-plugin_linux_amd64
| |-- simple-json-plugin_darwin_amd64
| |-- simple-json-plugin_windows_amd64.exe
...
```
### Plugin code
A `pkg/` directory contains three `.go` files:
- `plugin.go` - an entry point of the plugin. This file would be very similar for your data source - you just need to change some details like the plugin name etc.
- `datasource.go` - contains `Query()` method implementation and other plugin logic.
- `models.go` - types for request and response specific to your data source.
The data source type is declared in [`datasource.go`](https://github.com/grafana/simple-json-backend-datasource/blob/7927ff0db60c3402dbf954a454f19d7230e18deb/pkg/datasource.go#L21-L24):
```go
package main
import (
plugin "github.com/hashicorp/go-plugin"
)
type JsonDatasource struct {
plugin.NetRPCUnsupportedPlugin
}
```
The only requirement for the plugin type is that it should extend `plugin.NetRPCUnsupportedPlugin`. You can include more fields into your struct if you want to add some data source-specific features, like logging, cache etc:
```go
type JsonDatasource struct {
plugin.NetRPCUnsupportedPlugin
logger hclog.Logger
}
```
The main method you should implement is the [`Query()`](https://github.com/grafana/simple-json-backend-datasource/blob/7927ff0db60c3402dbf954a454f19d7230e18deb/pkg/datasource.go#L26):
```go
func (t *JsonDatasource) Query(ctx context.Context, tsdbReq *datasource.DatasourceRequest) (*datasource.DatasourceResponse, error) {
...
```
#### Request format
In order to call this method from the [frontend part of your data source](https://github.com/grafana/simple-json-backend-datasource/blob/7927ff0db60c3402dbf954a454f19d7230e18deb/src/datasource.ts#L116), use the `/api/tsdb/query` endpoint:
```js
class SimpleJSONDatasource {
...
doTsdbRequest(options) {
const tsdbRequest = {
from: options.range.from.valueOf().toString(),
to: options.range.to.valueOf().toString(),
queries: options.targets,
};
return this.backendSrv.datasourceRequest({
url: '/api/tsdb/query',
method: 'POST',
data: tsdbRequest
});
}
}
```
This endpoint gets data in the following format (see [pkg/api/metrics.go](https://github.com/grafana/grafana/blob/7b63913dc1d79da07f0329cf19dc4c2704ec488f/pkg/api/metrics.go#L16) and [pkg/api/dtos/models.go](https://github.com/grafana/grafana/blob/7b63913dc1d79da07f0329cf19dc4c2704ec488f/pkg/api/dtos/models.go#L43-L47)):
```js
{
from: "1555324640782", // Optional, time range from
to: "1555328240782", // Optional, time range to
queries: [
{
datasourceId: 42, // Required
refId: "A", // Optional, default is "A"
maxDataPoints: 100, // Optional, default is 100
intervalMs: 1000, // Optional, default is 1000
myFieldFoo: "bar", // Any other fields,
myFieldBar: "baz", // defined by user
...
},
...
]
}
```
There is only one query function but it is possible to move all your queries to the backend. In order to achieve this, you could add a kind of `queryType` field to your query model and check this type in the backend code. The Stackdriver and Cloudwatch core plugins have examples of supporting multiple types of queries if you need/want to do this:
- Stackdriver: [pkg/tsdb/stackdriver/stackdriver.go](https://github.com/grafana/grafana/blob/6724aaeff9a332dc73b4ee0f8abe0621f7253142/pkg/tsdb/stackdriver/stackdriver.go#L75-L88)
- Cloudwatch: [pkg/tsdb/cloudwatch/cloudwatch.go](https://github.com/grafana/grafana/blob/7b63913dc1d79da07f0329cf19dc4c2704ec488f/pkg/tsdb/cloudwatch/cloudwatch.go#L62-L74)
#### Response format
Go types for the query response can be found in Grafana tsdb models ([pkg/tsdb/models.go](https://github.com/grafana/grafana/blob/7b63913dc1d79da07f0329cf19dc4c2704ec488f/pkg/tsdb/models.go#L22-L34)) or in the corresponding protocol buffer file ([datasource.proto](https://github.com/grafana/grafana-plugin-model/blob/84176c64269d8060f99e750ee8aba6f062753336/datasource.proto#L26-L36))
```protobuf
// datasource.proto
message DatasourceResponse {
repeated QueryResult results = 1;
}
message QueryResult {
string error = 1;
string refId = 2;
string metaJson = 3;
repeated TimeSeries series = 4;
repeated Table tables = 5;
}
```
```go
// pkg/tsdb/models.go
type Response struct {
Results map[string]*QueryResult `json:"results"`
Message string `json:"message,omitempty"`
}
type QueryResult struct {
Error error `json:"-"`
ErrorString string `json:"error,omitempty"`
RefId string `json:"refId"`
Meta *simplejson.Json `json:"meta,omitempty"`
Series TimeSeriesSlice `json:"series"`
Tables []*Table `json:"tables"`
}
```
The resulting JSON response which the frontend will receive looks like this:
```js
results: {
A: {
refId: "A",
series: [
{ name: "series_1", points: [...] },
{ name: "series_2", points: [...] },
...
],
tables: null,
// Request metadata (any arbitrary JSON).
// Optional, empty field will be omitted.
meta: {},
// Error message. Optional, empty field will be omitted.
error: "Request failed",
}
}
```
### Logging
Logs from the plugin will be automatically sent to the Grafana server and will appear in its log flow. Grafana server reads logs from the plugin's `stderr` stream, so with the standard `log` package you have to set output to `os.Stderr` first:
```go
func main() {
log.SetOutput(os.Stderr)
log.Println("from plugin!")
...
}
```
Another option for logging - using [go-hclog](https://github.com/hashicorp/go-hclog) package:
```go
package main
import (
hclog "github.com/hashicorp/go-hclog"
)
var pluginLogger = hclog.New(&hclog.LoggerOptions{
Name: "simple-json-backend-datasource",
Level: hclog.LevelFromString("DEBUG"),
})
func main() {
pluginLogger.Debug("Running Simple JSON backend datasource")
...
}
```
### Building the backend binary
Building the binary depends on which OS you are using.
For a Linux distro, the build command would be:
```sh
go build -o ./dist/simple-json-plugin_linux_amd64 ./pkg
```
On Windows, the command would be:
```sh
go build -o ./dist/simple-json-plugin_windows_amd64.exe ./pkg
```
Restart your Grafana server and then check the Grafana logs to make sure your plugin is loaded properly.

View File

@@ -1,181 +0,0 @@
+++
title = "Data frames"
type = "docs"
+++
# Data frames
Grafana supports a variety of different data sources, each with its own data model. To make this possible, Grafana consolidates the query results from each of these data sources into one unified data structure called a _data frame_.
The data frame structure is a concept that's borrowed from data analysis tools like the [R programming language](https://www.r-project.org), and [Pandas](https://pandas.pydata.org/).
> Data frames are available in Grafana 7.0+, and replaced the Time series and Table structures with a more generic data structure that can support a wider range of data types.
This document gives an overview of the data frame structure, and of how data is handled within Grafana.
## The data frame
A data frame is a columnar-oriented table structure, which means it stores data by column and not by row. To understand what this means, lets look at the TypeScript definition used by Grafana:
```ts
interface DataFrame {
name?: string;
// reference to query that create the frame
refId?: string;
fields: []Field;
}
```
In essence, a data frame is a collection of _fields_, where each field corresponds to a column. Each field, in turn, consists of a collection of values, along with meta information, such as the data type of those values.
```ts
interface Field {
name: string;
// Prometheus like Labels / Tags
labels?: Record<string, string>;
// For example string, number, time (or more specific primitives in the backend)
type: FieldType;
// Array of values all of the same type
values: Vector<T>;
// Optional display data for the field (e.g. unit, name over-ride, etc)
config: FieldConfig;
}
```
Let's look an example. The table below demonstrates a data frame with two fields, _time_ and _temperature_.
| time | temperature |
|---------------------|-------------|
| 2020-01-02 03:04:00 | 45.0 |
| 2020-01-02 03:05:00 | 47.0 |
| 2020-01-02 03:06:00 | 48.0 |
Each field has three values, and each value in a field must share the same type. In this case, all values in the time field are timestamps, and all values in the temperature field are numbers.
One restriction on data frames is that all fields in the frame must be of the same length to be a valid data frame.
### Field configuration
Each field in a data frame contains optional information about the values in the field, such as units, scaling, and so on.
By adding field configurations to a data frame, Grafana can configure visualizations automatically. For example, you could configure Grafana to automatically set the unit provided by the data source.
## Transformations
Along with the type information, field configs enables _data transformations_ within Grafana.
A data transformation is any function that accepts a data frame as input, and returns another data frame as output. By using data frames in your plugin, you get a range of transformations for free.
## Data frames as time series
A data frame with at least one time field is considered a _time series_.
For more information on time series, refer to our [Introduction to time series](https://grafana.com/docs/grafana/latest/guides/timeseries/).
### Wide format
When a collection of time series share the same _time index_—the time fields in each time series are identical—they can be stored together, in a _wide_ format. By reusing the time field, we can reduce the amount of data being sent to the browser.
In this example, the `cpu` usage from each host share the time index, so we can store them in the same data frame.
```text
Name: Wide
Dimensions: 3 fields by 2 rows
+---------------------+-----------------+-----------------+
| Name: time | Name: cpu | Name: cpu |
| Labels: | Labels: host=a | Labels: host=b |
| Type: []time.Time | Type: []float64 | Type: []float64 |
+---------------------+-----------------+-----------------+
| 2020-01-02 03:04:00 | 3 | 4 |
| 2020-01-02 03:05:00 | 6 | 7 |
+---------------------+-----------------+-----------------+
```
However, if the two time series don't share the same time values, they are represented as two distinct data frames.
```text
Name: cpu
Dimensions: 2 fields by 2 rows
+---------------------+-----------------+
| Name: time | Name: cpu |
| Labels: | Labels: host=a |
| Type: []time.Time | Type: []float64 |
+---------------------+-----------------+
| 2020-01-02 03:04:00 | 3 |
| 2020-01-02 03:05:00 | 6 |
+---------------------+-----------------+
Name: cpu
Dimensions: 2 fields by 2 rows
+---------------------+-----------------+
| Name: time | Name: cpu |
| Labels: | Labels: host=b |
| Type: []time.Time | Type: []float64 |
+---------------------+-----------------+
| 2020-01-02 03:04:01 | 4 |
| 2020-01-02 03:05:01 | 7 |
+---------------------+-----------------+
```
The wide format can typically be used when multiple time series are collected by the same process. In this case, every measurement is made at the same interval and will therefore share the same time values.
### Long format
Some data sources return data in a _long_ format (also called _narrow_ format). This is common format returned by, for example, SQL databases.
In long format, string values are represented as separate fields rather than as labels. As a result, a data form in long form may have duplicated time values.
Grafana can detect and convert data frames in long format into wide format.
> Note: Long format is currently only supported in the backend: [Grafana Issue #22219](https://github.com/grafana/grafana/issues/22219).
For example, the following data frame in long format:
```text
Name: Long
Dimensions: 4 fields by 4 rows
+---------------------+-----------------+-----------------+----------------+
| Name: time | Name: aMetric | Name: bMetric | Name: host |
| Labels: | Labels: | Labels: | Labels: |
| Type: []time.Time | Type: []float64 | Type: []float64 | Type: []string |
+---------------------+-----------------+-----------------+----------------+
| 2020-01-02 03:04:00 | 2 | 10 | foo |
| 2020-01-02 03:04:00 | 5 | 15 | bar |
| 2020-01-02 03:05:00 | 3 | 11 | foo |
| 2020-01-02 03:05:00 | 6 | 16 | bar |
+---------------------+-----------------+-----------------+----------------+
```
can be converted into a data frame in wide format:
```text
Name: Wide
Dimensions: 5 fields by 2 rows
+---------------------+------------------+------------------+------------------+------------------+
| Name: time | Name: aMetric | Name: bMetric | Name: aMetric | Name: bMetric |
| Labels: | Labels: host=foo | Labels: host=foo | Labels: host=bar | Labels: host=bar |
| Type: []time.Time | Type: []float64 | Type: []float64 | Type: []float64 | Type: []float64 |
+---------------------+------------------+------------------+------------------+------------------+
| 2020-01-02 03:04:00 | 2 | 10 | 5 | 15 |
| 2020-01-02 03:05:00 | 3 | 11 | 6 | 16 |
+---------------------+------------------+------------------+------------------+------------------+
```
## Technical references
This section contains links to technical reference and implementations of data frames.
### Apache Arrow
The data frame structure is inspired by, and uses the [Apache Arrow Project](https://arrow.apache.org/). Javascript Data frames use Arrow Tables as the underlying structure, and the backend Go code serializes its Frames in Arrow Tables for transmission.
### Javascript
The Javascript implementation of data frames is in the [`/src/dataframe` folder](https://github.com/grafana/grafana/tree/master/packages/grafana-data/src/dataframe) and [`/src/types/dataframe.ts`](https://github.com/grafana/grafana/blob/master/packages/grafana-data/src/types/dataFrame.ts) of the [`@grafana/data` package](https://github.com/grafana/grafana/tree/master/packages/grafana-data).
### Go
For documentation on the Go implementation of data frames, refer to the [github.com/grafana/grafana-plugin-sdk-go/data package](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go/data?tab=doc).

View File

@@ -1,132 +0,0 @@
+++
title = "Legacy plugins"
type = "docs"
aliases = ["/docs/grafana/latest/plugins/development/", "/docs/grafana/latest/plugins/datasources/", "/docs/grafana/latest/plugins/apps/", "/docs/grafana/latest/plugins/panels/", "/docs/grafana/latest/plugins/developing/development/"]
+++
# Legacy plugins
> **Note**: Since Grafana 7.0, writing plugins using Angular is no longer recommended. If you're looking to build a new plugin, refer to [Plugins]({{< relref "../_index.md" >}}).
You can extend Grafana by writing your own plugins and then share them with other users in [our plugin repository](https://grafana.com/plugins).
Grafana already has a strong community of contributors and plugin developers. By making it easier to develop and install plugins with resources such as this guide, we hope that the community can grow even stronger and develop new plugins that we would never think about.
## Short version
1. [Set up Grafana](https://github.com/grafana/grafana/blob/master/contribute/developer-guide.md)
2. Clone an example plugin into ```/var/lib/grafana/plugins``` or `data/plugins` (relative to grafana git repo if you're running development version from source dir)
3. Use one of our example plugins as a starting point
Example plugins
- ["Hello World" panel using Angular](https://github.com/grafana/simple-angular-panel)
- ["Hello World" panel using React](https://github.com/grafana/simple-react-panel)
- [Simple json data source](https://github.com/grafana/simple-json-datasource)
- [Clock panel](https://github.com/grafana/clock-panel)
- [Pie chart panel](https://github.com/grafana/piechart-panel)
You might also be interested in the available tutorials around authoring a plugin.
- [Grafana Tutorials](https://grafana.com/tutorials/)
## What languages?
Since everything turns into JavaScript, it's up to you to choose which language you want. That said, it's probably a good idea to choose es6 or TypeScript, because we use es6 classes in Grafana. So it's easier to get inspiration from the Grafana repo if you choose one of those languages.
## Buildscript
You can use any build system that supports systemjs. All the built content should end up in a folder named ```dist``` and be committed to the repository. By committing the dist folder, the person who installs your plugin does not have to run any build script. All of our example plugins have a build script configured.
## Keep your plugin up to date
New versions of Grafana can sometimes cause plugins to break. Check out our [PLUGIN_DEV.md](https://github.com/grafana/grafana/blob/master/PLUGIN_DEV.md) doc for changes in
Grafana that can impact your plugin.
## Metadata
See the [coding styleguide]({{< relref "style-guide.md" >}}) for details on the metadata.
## module.(js|ts)
This is the entry point for every plugin. This is the place where you should export
your plugin implementation. Depending on what kind of plugin you are developing you
will be expected to export different things. You can find what's expected for [datasource]({{< relref "data-sources.md" >}}), [panels]({{< relref "panels.md" >}})
and [apps]({{< relref "apps.md" >}}) plugins in the documentation.
The Grafana SDK is quite small so far and can be found here:
- [SDK file in Grafana](https://github.com/grafana/grafana/blob/master/public/app/plugins/sdk.ts)
The SDK contains three different plugin classes: PanelCtrl, MetricsPanelCtrl and QueryCtrl. For plugins of the panel type, the module.js file should export one of these. There are some extra classes for [data sources]({{< relref "data-sources.md" >}}).
Example:
```javascript
import {ClockCtrl} from './clock_ctrl';
export {
ClockCtrl as PanelCtrl
};
```
The module class is also where css for the dark and light themes is imported:
```javascript
import {loadPluginCss} from 'app/plugins/sdk';
import WorldmapCtrl from './worldmap_ctrl';
loadPluginCss({
dark: 'plugins/grafana-worldmap-panel/css/worldmap.dark.css',
light: 'plugins/grafana-worldmap-panel/css/worldmap.light.css'
});
export {
WorldmapCtrl as PanelCtrl
};
```
## Start developing your plugin
There are three ways that you can start developing a Grafana plugin.
1. Set up a Grafana development environment. [(described here)](https://github.com/grafana/grafana/blob/master/contribute/developer-guide.md) and place your plugin in the ```data/plugins``` folder.
2. Install Grafana and place your plugin in the plugins directory which is set in your [config file](/installation/configuration). By default this is `/var/lib/grafana/plugins` on Linux systems.
3. Place your plugin directory anywhere you like and specify it grafana.ini.
We encourage people to set up the full Grafana environment so that you can get inspiration from the rest of the Grafana code base.
When Grafana starts, it scans the plugin folders and mounts every folder that contains a plugin.json file unless
the folder contains a subfolder named dist. In that case, Grafana mounts the dist folder instead.
This makes it possible to have both built and src content in the same plugin Git repo.
## Grafana Events
There are a number of Grafana events that a plugin can hook into:
- `init-edit-mode` can be used to add tabs when editing a panel
- `panel-teardown` can be used for clean up
- `data-received` is an event in that is triggered on data refresh and can be hooked into
- `data-snapshot-load` is an event triggered to load data when in snapshot mode.
- `data-error` is used to handle errors on dashboard refresh.
If a panel receives data and hooks into the `data-received` event then it should handle snapshot mode too. Otherwise the panel will not work if saved as a snapshot. [Getting Plugins to work in Snapshot Mode]({{< relref "snapshot-mode.md" >}}) describes how to add support for this.
## Examples
We have three different examples that you can fork/download to get started developing your Grafana plugin.
- [simple-json-datasource](https://github.com/grafana/simple-json-datasource) (small data source plugin for querying json data from backends)
- [simple-app-plugin](https://github.com/grafana/simple-app-plugin)
- [clock-panel](https://github.com/grafana/clock-panel)
- [singlestat-panel](https://github.com/grafana/grafana/tree/master/public/app/plugins/panel/singlestat)
- [piechart-panel](https://github.com/grafana/piechart-panel)
## Other Articles
- [Getting Plugins to work in Snapshot Mode]({{< relref "snapshot-mode.md" >}})
- [Plugin Defaults and Editor Mode]({{< relref "defaults-and-editor-mode.md" >}})
- [Grafana Plugin Code Styleguide]({{< relref "style-guide.md" >}})
- [Grafana Apps]({{< relref "apps.md" >}})
- [Grafana Data Sources]({{< relref "data-sources.md" >}})
- [plugin.json Schema]({{< relref "metadata.md" >}})

View File

@@ -1,189 +0,0 @@
+++
title = "Legacy data source plugins"
keywords = ["grafana", "plugins", "documentation"]
type = "docs"
aliases = ["/docs/grafana/latest/plugins/developing/datasources/"]
+++
# Legacy data source plugins
Data source plugins enable people to develop plugins for any database that
communicates over HTTP. Its up to the plugin to transform the data into
time series data so that any grafana panel can then show it.
## Data source development
> Our goal is not to have a very extensive documentation but rather have actual
> code that people can look at. Example implementations of a data source can be
> found in these repos:
> - [simple-json-datasource](https://github.com/grafana/simple-json-datasource)
> - [simple-datasource](https://github.com/grafana/simple-datasource)
> - [simple-json-backend-datasource](https://github.com/grafana/simple-json-backend-datasource)
To interact with the rest of grafana the plugins module file can export 4 different components.
- Datasource (Required)
- QueryCtrl (Required)
- ConfigCtrl (Required)
- AnnotationsQueryCtrl
## Plugin json
There are two data source specific settings for the plugin.json
```json
"metrics": true,
"annotations": false,
```
These settings indicate what kind of data the plugin can deliver. At least one of them has to be true.
## Data source
The javascript object that communicates with the database and transforms data to times series.
The Data source should contain the following functions:
```javascript
query(options) // used by panels to get data
testDatasource() // used by data source configuration page to make sure the connection is working
annotationQuery(options) // used by dashboards to get annotations
metricFindQuery(options) // used by query editor to get metric suggestions.
```
### testDatasource
When a user clicks on the *Save & Test* button when adding a new data source, the details are first saved to the database and then the `testDatasource` function that is defined in your data source plugin will be called. It is recommended that this function makes a query to the data source that will also test that the authentication details are correct. This is so the data source is correctly configured when the user tries to write a query in a new dashboard.
### Query
Request object passed to datasource.query function:
```json
{
"range": { "from": "2015-12-22T03:06:13.851Z", "to": "2015-12-22T06:48:24.137Z" },
"interval": "5s",
"targets": [
{ "refId": "B", "target": "upper_75" },
{ "refId": "A", "target": "upper_90" }
],
"format": "json",
"maxDataPoints": 2495 // decided by the panel
}
```
There are two different kinds of results for data sources:
time series and table. Time series is the most common format and is supported by all data sources and panels. Table format is only supported by the InfluxDB data source and table panel. But we might see more of this in the future.
Time series response from datasource.query.
An array of:
```json
[
{
"target":"upper_75",
"datapoints":[
[622, 1450754160000],
[365, 1450754220000]
]
},
{
"target":"upper_90",
"datapoints":[
[861, 1450754160000],
[767, 1450754220000]
]
}
]
```
Table response from datasource.query.
An array of:
```json
[
{
"columns": [
{
"text": "Time",
"type": "time",
"sort": true,
"desc": true,
},
{
"text": "mean",
},
{
"text": "sum",
}
],
"rows": [
[
1457425380000,
null,
null
],
[
1457425370000,
1002.76215352,
1002.76215352
],
],
"type": "table"
}
]
```
### Annotation Query
Request object passed to datasource.annotationQuery function:
```json
{
"range": { "from": "2016-03-04T04:07:55.144Z", "to": "2016-03-04T07:07:55.144Z" },
"rangeRaw": { "from": "now-3h", to: "now" },
"annotation": {
"datasource": "generic datasource",
"enable": true,
"name": "annotation name"
},
"dashboard": DashboardModel
}
```
Expected result from datasource.annotationQuery:
```json
[
{
"annotation": {
"name": "annotation name", //should match the annotation name in grafana
"enabled": true,
"datasource": "generic datasource"
},
"title": "Cluster outage",
"time": 1457075272576,
"text": "Joe causes brain split",
"tags": ["joe", "cluster", "failure"]
}
]
```
## QueryCtrl
A JavaScript class that will be instantiated and treated as an Angular controller when the user edits metrics in a panel. This class has to inherit from the `app/plugins/sdk.QueryCtrl` class.
Requires a static template or `templateUrl` variable which will be rendered as the view for this controller.
## ConfigCtrl
A JavaScript class that will be instantiated and treated as an Angular controller when a user tries to edit or create a new data source of this type.
Requires a static template or `templateUrl` variable which will be rendered as the view for this controller.
## AnnotationsQueryCtrl
A JavaScript class that will be instantiated and treated as an Angular controller when the user chooses this type of data source in the templating menu in the dashboard.
Requires a static template or `templateUrl` variable which will be rendered as the view for this controller. The fields that are bound to this controller are then sent to the Database objects annotationQuery function.

View File

@@ -1,28 +0,0 @@
+++
title = "Legacy panel plugins"
keywords = ["grafana", "plugins", "panel", "documentation"]
type = "docs"
aliases = ["/docs/grafana/latest/plugins/developing/panels/"]
+++
# Legacy panel plugins
Panels are the main building blocks of dashboards.
## Panel development
### Scrolling
The grafana dashboard framework controls the panel height. To enable a scrollbar within the panel the PanelCtrl needs to set the scrollable static variable:
```javascript
export class MyPanelCtrl extends PanelCtrl {
static scrollable = true;
...
```
In this case, make sure the template has a single `<div>...</div>` root. The plugin loader will modify that element adding a scrollbar.
### Examples
- [clock-panel](https://github.com/grafana/clock-panel)
- [singlestat-panel](https://github.com/grafana/grafana/tree/master/public/app/plugins/panel/singlestat)

View File

@@ -1,175 +0,0 @@
+++
title = "Legacy review guidelines"
type = "docs"
aliases = ["/docs/grafana/latest/plugins/developing/plugin-review-guidelines/"]
+++
# Legacy review guidelines
The Grafana team reviews all plugins that are published on Grafana.com. There are two areas we review, the metadata for the plugin and the plugin functionality.
## Metadata
The plugin metadata consists of a `plugin.json` file and the README.md file. The `plugin.json` file is used by Grafana to load the plugin, and the README.md file is shown in the plugins section of Grafana and the plugins section of https://grafana.com.
### README.md
The README.md file is shown on the plugins page in Grafana and the plugin page on Grafana.com. There are some differences between the GitHub markdown and the markdown allowed in Grafana/Grafana.com:
- Cannot contain inline HTML.
- Any image links should be absolute links. For example: https://raw.githubusercontent.com/grafana/azure-monitor-datasource/master/dist/img/grafana_cloud_install.png
The README should:
- describe the purpose of the plugin.
- contain steps on how to get started.
### Plugin.json
The `plugin.json` file is the same concept as the `package.json` file for an npm package. When the Grafana server starts it will scan the plugin folders (all folders in the data/plugins subfolder) and load every folder that contains a `plugin.json` file unless the folder contains a subfolder named `dist`. In that case, the Grafana server will load the `dist` folder instead.
A minimal `plugin.json` file:
```json
{
"type": "panel",
"name": "Clock",
"id": "yourorg-clock-panel",
"info": {
"description": "Clock panel for grafana",
"author": {
"name": "Author Name",
"url": "http://yourwebsite.com"
},
"keywords": ["clock", "panel"],
"version": "1.0.0",
"updated": "2018-03-24"
},
"dependencies": {
"grafanaVersion": "3.x.x",
"plugins": [ ]
}
}
```
- The convention for the plugin id is **[grafana.com username/org]-[plugin name]-[datasource|app|panel]** and it has to be unique. The org **cannot** be `grafana` unless it is a plugin created by the Grafana core team.
Examples:
- raintank-worldping-app
- ryantxu-ajax-panel
- alexanderzobnin-zabbix-app
- hawkular-datasource
- The `type` field should be either `datasource` `app` or `panel`.
- The `version` field should be in the form: x.x.x e.g. `1.0.0` or `0.4.1`.
The full file format for the `plugin.json` file is described [here](http://docs.grafana.org/plugins/developing/plugin.json/).
## Plugin Language
JavaScript, TypeScript, ES6 (or any other language) are all fine as long as the contents of the `dist` subdirectory are transpiled to JavaScript (ES5).
## File and Directory Structure Conventions
Here is a typical directory structure for a plugin.
```bash
johnnyb-awesome-datasource
|-- dist
|-- src
| |-- img
| | |-- logo.svg
| |-- partials
| | |-- annotations.editor.html
| | |-- config.html
| | |-- query.editor.html
| |-- datasource.js
| |-- module.js
| |-- plugin.json
| |-- query_ctrl.js
|-- Gruntfile.js
|-- LICENSE
|-- package.json
|-- README.md
```
Most JavaScript projects have a build step. The generated JavaScript should be placed in the `dist` directory and the source code in the `src` directory. We recommend that the plugin.json file be placed in the src directory and then copied over to the dist directory when building. The `README.md` can be placed in the root or in the dist directory.
Directories:
- `src/` contains plugin source files.
- `src/partials` contains html templates.
- `src/img` contains plugin logos and other images.
- `dist/` contains built content.
## HTML and CSS
For the HTML on editor tabs, we recommend using the inbuilt Grafana styles rather than defining your own. This makes plugins feel like a more natural part of Grafana. If done correctly, the html will also be responsive and adapt to smaller screens. The `gf-form` css classes should be used for labels and inputs.
Below is a minimal example of an editor row with one form group and two fields, a dropdown and a text input:
```html
<div class="editor-row">
<div class="section gf-form-group">
<h5 class="section-heading">My Plugin Options</h5>
<div class="gf-form">
<label class="gf-form-label width-10">Label1</label>
<div class="gf-form-select-wrapper max-width-10">
<select class="input-small gf-form-input" ng-model="ctrl.panel.mySelectProperty" ng-options="t for t in ['option1', 'option2', 'option3']" ng-change="ctrl.onSelectChange()"></select>
</div>
<div class="gf-form">
<label class="gf-form-label width-10">Label2</label>
<input type="text" class="input-small gf-form-input width-10" ng-model="ctrl.panel.myProperty" ng-change="ctrl.onFieldChange()" placeholder="suggestion for user" ng-model-onblur />
</div>
</div>
</div>
</div>
```
Use the `width-x` and `max-width-x` classes to control the width of your labels and input fields. Try to get labels and input fields to line up neatly by having the same width for all the labels in a group and the same width for all inputs in a group if possible.
## Data Sources
A basic guide for data sources can be found [here](http://docs.grafana.org/plugins/developing/datasources/).
### Config Page Guidelines
- It should be as easy as possible for a user to configure a URL. If the data source is using the `datasource-http-settings` component, it should use the `suggest-url` attribute to suggest the default URL or a URL that is similar to what it should be (especially important if the URL refers to a REST endpoint that is not common knowledge for most users e.g. `https://yourserver:4000/api/custom-endpoint`).
```html
<datasource-http-settings
current="ctrl.current"
suggest-url="http://localhost:8080">
</datasource-http-settings>
```
- The `testDatasource` function should make a query to the data source that will also test that the authentication details are correct. This is so the data source is correctly configured when the user tries to write a query in a new dashboard.
#### Password Security
If possible, any passwords or secrets should be be saved in the `secureJsonData` blob. To encrypt sensitive data, the Grafana server's proxy feature must be used. The Grafana server has support for token authentication (OAuth) and HTTP Header authentication. If the calls have to be sent directly from the browser to a third-party API, this will not be possible and sensitive data will not be encrypted.
Read more here about how [authentication for data sources]({{< relref "../authentication.md" >}}) works.
If using the proxy feature, the Config page should use the `secureJsonData` blob like this:
- good: `<input type="password" class="gf-form-input" ng-model='ctrl.current.secureJsonData.password' placeholder="password"></input>`
- bad: `<input type="password" class="gf-form-input" ng-model='ctrl.current.password' placeholder="password"></input>`
### Query Editor
Each query editor is unique and can have a unique style. It should be adapted to what the users of the data source are used to.
- Should use the Grafana CSS `gf-form` classes.
- Should be neat and tidy. Labels and fields in columns should be aligned and should be the same width if possible.
- The data source should be able to handle when a user toggles a query (by clicking on the eye icon) and not execute the query. This is done by checking the `hide` property - an [example](https://github.com/grafana/grafana/blob/e75840737e81f70b6d169df21eca86a624d4bdc4/public/app/plugins/datasource/postgres/datasource.ts#L73).
- Should not execute queries if fields in the Query Editor are empty and the query will throw an exception (defensive programming).
- Should handle errors. There are two main ways to do this:
- use the notification system in Grafana to show a toaster popup with the error message. Example [here](https://github.com/alexanderzobnin/grafana-zabbix/blob/fdbbba2fb03f5f2a4b3b0715415e09d5a4cf6cde/src/panel-triggers/triggers_panel_ctrl.js#L467-L471).
- provide an error notification in the query editor like the MySQL/Postgres data sources do. Example code in the `query_ctrl` [here](https://github.com/grafana/azure-monitor-datasource/blob/b184d077f082a69f962120ef0d1f8296a0d46f03/src/query_ctrl.ts#L36-L51) and in the [html](https://github.com/grafana/azure-monitor-datasource/blob/b184d077f082a69f962120ef0d1f8296a0d46f03/src/partials/query.editor.html#L190-L193).

View File

@@ -1,179 +0,0 @@
+++
title = "Legacy code style guide"
type = "docs"
aliases = ["/docs/grafana/latest/plugins/developing/code-styleguide/"]
+++
# Legacy code style guide
This guide has two parts. The first part describes the metadata and the second part is a styleguide for HTML/CSS and JavaScript in Grafana plugins and applies if you are using ES6 in your plugin. If using TypeScript then the [Angular TypeScript styleguide](https://angular.io/styleguide) is recommended.
## Metadata
The plugin metadata consists of a plugin.json file and the README.md file. These two files are used by Grafana and Grafana.com.
### Plugin.json (mandatory)
The plugin.json file is the same concept as the package.json file for an npm package. When Grafana starts it will scan the plugin folders and mount every folder that contains a plugin.json file unless the folder contains a subfolder named `dist`. In that case grafana will mount the `dist` folder instead.
The most important fields are the first three, especially the id. The convention for the plugin id is **[github username/org]-[plugin name]-[datasource|app|panel]** and it has to be unique.
Examples:
```bash
raintank-worldping-app
grafana-simple-json-datasource
grafana-piechart-panel
mtanda-histogram-panel
```
The full file format for plugin.json is described [here]({{< relref "metadata.md" >}}).
Minimal plugin.json:
```javascript
{
"type": "panel",
"name": "Clock",
"id": "yourorg-clock-panel",
"info": {
"description": "Clock panel for grafana",
"author": {
"name": "Grafana Labs",
"url": "https://grafana.com"
},
"keywords": ["clock", "panel"],
"version": "1.0.0",
"updated": "2015-03-24"
},
"dependencies": {
"grafanaVersion": "3.x.x",
"plugins": [ ]
}
}
```
### README.md
The README.md file is rendered both in the grafana.com plugins page, and within the Grafana application. The only difference from how GitHub renders markdown is that html is not allowed.
## File and Directory Structure Conventions
Here is a typical directory structure for a plugin.
```bash
johnnyb-awesome-datasource
|-- dist
|-- spec
| |-- datasource_spec.js
| |-- query_ctrl_spec.js
| |-- test-main.js
|-- src
| |-- img
| | |-- logo.svg
| |-- partials
| | |-- annotations.editor.html
| | |-- config.html
| | |-- query.editor.html
| |-- datasource.js
| |-- module.js
| |-- plugin.json
| |-- query_ctrl.js
|-- Gruntfile.js
|-- LICENSE
|-- package.json
|-- README.md
```
Most JavaScript projects have a build step and most Grafana plugins are built using Babel and ES6. The generated JavaScript should be placed in the `dist` directory and the source code in the `src` directory. We recommend that the plugin.json file be placed in the src directory and then copied over to the dist directory when building. The `README.md` can be placed in the root or in the dist directory.
Directories:
- `src/` contains plugin source files.
- `src/partials` contains html templates.
- `src/img` contains plugin logos and other images.
- `spec/` contains tests (optional).
- `dist/` contains built content.
## HTML and CSS
For the HTML on editor tabs, we recommend using the inbuilt Grafana styles rather than defining your own. This makes plugins feel like a more natural part of Grafana. If done correctly, the html will also be responsive and adapt to smaller screens. The `gf-form` css classes should be used for labels and inputs.
Below is a minimal example of an editor row with one form group and two fields, a dropdown and a text input:
```html
<div class="editor-row">
<div class="section gf-form-group">
<h5 class="section-heading">My Plugin Options</h5>
<div class="gf-form">
<label class="gf-form-label width-10">Label1</label>
<div class="gf-form-select-wrapper max-width-10">
<select class="input-small gf-form-input" ng-model="ctrl.panel.mySelectProperty" ng-options="t for t in ['option1', 'option2', 'option3']" ng-change="ctrl.onSelectChange()"></select>
</div>
<div class="gf-form">
<label class="gf-form-label width-10">Label2</label>
<input type="text" class="input-small gf-form-input width-10" ng-model="ctrl.panel.myProperty" ng-change="ctrl.onFieldChange()" placeholder="suggestion for user" ng-model-onblur />
</div>
</div>
</div>
</div>
```
Use the `width-x` and `max-width-x` classes to control the width of your labels and input fields. Try to get labels and input fields to line up neatly by having the same width for all the labels in a group and the same width for all inputs in a group if possible.
## Build Scripts
Our recommendation is to use whatever you usually use - Grunt, Gulp or npm scripts. Most plugins seems to use Grunt so that is probably the easiest to get started with if you do not have a preferred build system. The only requirement is that it supports systemjs which is required by Grafana to load plugins.
## Linting
We recommend that you use a linter for your JavaScript. For ES6, the standard linter is [eslint](http://eslint.org/). Rules for linting are described in an .eslintrc that is placed in the root directory. [Here is an example](https://github.com/grafana/worldmap-panel/blob/master/.eslintrc) of linting rules in a plugin.
### ES6 features
1. Use `const` if a variable is not going to be reassigned.
2. Prefer to use `let` instead `var` ([Exploring ES6](http://exploringjs.com/es6/ch_core-features.html#_from-var-to-letconst))
3. Use arrow functions, which dont shadow `this` ([Exploring ES6](http://exploringjs.com/es6/ch_core-features.html#_from-function-expressions-to-arrow-functions)):
```js
testDatasource() {
return this.getServerStatus()
.then(status => {
return this.doSomething(status);
})
}
```
better than
```js
testDatasource() {
var self = this;
return this.getServerStatus()
.then(function(status) {
return self.doSomething(status);
})
}
```
4. Use native _Promise_ object:
```js
metricFindQuery(query) {
if (!query) {
return Promise.resolve([]);
}
}
```
better than
```js
metricFindQuery(query) {
if (!query) {
return this.$q.when([]);
}
}
```
5. If using Lodash, then be consistent and prefer that to the native ES6 array functions.

View File

@@ -1,36 +0,0 @@
+++
title = "plugin.json"
keywords = ["grafana", "plugins", "documentation"]
type = "docs"
aliases = ["/docs/grafana/latest/plugins/developing/plugin.json/"]
+++
# plugin.json
The plugin.json file is mandatory for all plugins. When Grafana starts it will scan the plugin folders and mount every folder that contains a plugin.json file unless the folder contains a subfolder named `dist`. In that case grafana will mount the `dist` folder instead.
## Schema
| Property | Description |
|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------|
| id | Unique name of the plugin. |
| type | One of `app`, `datasource`, `panel` |
| name | Human-readable name of the plugin |
| dependencies.grafanaVersion | Required Grafana version for this plugin |
| dependencies.plugins | An array of required plugins on which this plugin depends |
| info.author.name | Author's name |
| info.author.url | Link to author's website |
| info.description | Description of plugin. Used for search on grafana.com |
| info.keywords | Array of plugin keywords. Used for search on grafana.com |
| info.links | An array of link objects to be displayed on this plugin's project page in the form `{name: 'foo', url: 'http://example.com'}` |
| info.logos.small | Link to the "small" version of the plugin logo, which must be an SVG image. "Large" and "small" logos can be the same image. |
| info.logos.large | Link to the "large" version of the plugin logo, which must be an SVG image. "Large" and "small" logos can be the same image. |
| info.screenshots | An array of screenshot objects in the form `{name: 'bar', path: 'img/screenshot.png'}` |
| info.updated | Date when this plugin was built. Use `%TODAY%` for Grafana to autopopulate this value. |
| info.version | Project version of this commit. Use `%VERSION%` for Grafana to autopopulate this value. |
## Plugin.json Example
Here's an example of an up-to-date plugin.json file:
https://github.com/grafana/clock-panel/blob/master/src/plugin.json

View File

@@ -1,7 +1,7 @@
+++
title = "Grafana Enterprise"
description = "Grafana Enterprise overview"
keywords = ["grafana", "documentation", "datasource", "permissions", "ldap", "licensing", "enterprise", "insights", "reporting"]
keywords = ["grafana", "documentation", "datasource", "permissions", "ldap", "licensing", "enterprise"]
type = "docs"
[menu.docs]
name = "Grafana Enterprise"
@@ -50,18 +50,10 @@ Supported auth providers:
[Reporting]({{< relref "reporting.md" >}}) allows you to take any dashboard, generate a PDF report, and set up a schedule to have it emailed to whoever you choose.
## Export dashboard as PDF
[Export dashboard as PDF]({{< relref "export-pdf.md" >}}) allows you to export a dashboard as a PDF document.
## White labeling
[White labeling]({{< relref "white-labeling.md" >}}) allows you to replace the Grafana brand and logo with your own corporate brand and logo. You can also change footer links to point to your custom resources.
## Usage insights
[Usage insights]({{< relref "usage-insights.md" >}}) allow you to understand how your Grafana instance is used. You can see who is looking at a dashboard, how often a dashboard is seen, and which dashboards are prone to errors. You'll also be able to discover what are the least and the most used dashboards.
## Enterprise plugins
With a Grafana Enterprise license, you get access to premium plugins, including:
@@ -72,7 +64,6 @@ With a Grafana Enterprise license, you get access to premium plugins, including:
* [Dynatrace](https://grafana.com/plugins/grafana-dynatrace-datasource)
* [New Relic](https://grafana.com/plugins/grafana-newrelic-datasource)
* [Oracle Database](https://grafana.com/plugins/grafana-oracle-datasource)
* [ServiceNow](https://grafana.com/grafana/plugins/grafana-servicenow-datasource)
* [Splunk](https://grafana.com/plugins/grafana-splunk-datasource)
## Try Grafana Enterprise

View File

@@ -1,20 +0,0 @@
+++
title = "Export dashboard as PDF"
description = ""
keywords = ["grafana", "export", "pdf", "share"]
type = "docs"
[menu.docs]
parent = "enterprise"
weight = 900
+++
# Export dashboard as PDF
You can generate PDFs from any of your dashboards and save it to file.
> Only available in Grafana Enterprise v6.7+.
1. In the upper right corner of the dashboard that you want to export as PDF, click the **Share dashboard** icon.
1. On the PDF tab, select the layout option for exported dashboard: **Portrait** or **Landscape**.
1. Click **Save as PDF** to render dashboard as a PDF document.
Grafana opens the PDF in a new window or browser tab.

View File

@@ -28,104 +28,36 @@ Any changes you make to a dashboard used in a report are reflected the next time
Currently only Organization Admins can create reports.
1. Click on the reports icon in the side menu. The Reports tab allows you to view, create, and update your reports.
1. Click on the reports icon in the side menu. The Reports tab allow you to view, create, and update your reports.
1. Enter report information. All fields are required unless otherwise indicated.
* **Name -** Name of the report as you want it to appear in the Reports list.
* **Choose dashboard -** Select the dashboard to generate the report from.
* **Recipients -** Enter the emails of the people or teams that you want to receive the report.
* **Reply to -** (optional) The address that will appear in the **Reply to** field of the email.
* **Custom message -** (optional) Message body in the email with the report.
1. **Preview** the report to make sure it appears as you expect. Update if necessary
1. Select the layout option for generated report: **Portrait** or **Landscape**.
1. **Preview** the report to make sure it appears as you expect. Update if necessary.
1. Enter scheduling information. Options vary depending on the frequency you select.
1. **Save** the report.
1. **Send test mail** after saving the report to verify that the whole configuration is working as expected.
{{< docs-imagebox img="/img/docs/enterprise/reports_create_new.png" max-width="500px" class="docs-image--no-shadow" >}}
### Scheduling
Scheduled reports can be sent on a weekly, daily, or hourly basis. You may also disable scheduling for when you either want to pause a report or send it via the API.
All scheduling indicates when the reporting service will start rendering the dashboard. It can take a few minutes to render a dashboard with a lot of panels.
#### Hourly
Hourly reports are generated once per hour. All fields are required.
* **At minute -** The number of minutes after full hour when the report should be generated.
* **Time zone -** Time zone to determine the offset of the full hour. Does not currently change the time in the rendered report.
#### Daily
Daily reports are generated once per day. All fields are required.
* **Time -** Time of day in 24 hours format when the report should be sent.
* **Time zone -** Time zone for the **Time** field.
#### Weekly
Weekly reports are generated once per week. All fields are required.
* **Day -** Weekday which the report should be sent on.
* **Time -** Time of day in 24 hours format when the report should be sent.
* **Time zone -** Time zone for the **Time** field.
#### Never
> Only available in Grafana Enterprise v7.0+.
Reports which are scheduled to never be sent have no parameter and will not be sent to the scheduler. They may be manually generated from the **Send test email** prompt or via the API.
### Send test mail
> Only available in Grafana Enterprise v7.0+.
1. In the report, click **Send test mail**.
1. In the Email field, enter the email address or addresses that you want to test, separated by 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.
{{< docs-imagebox img="/img/docs/enterprise/reports_send_test_mail.png" max-width="500px" class="docs-image--no-shadow" >}}
## Send report via the API
You can send reports programmatically with the [send report]({{< relref "../http_api/reporting.md#send-report" >}}) endpoint in the [HTTP APIs]({{< relref "../http_api" >}}).
## Rendering configuration
When generating reports, each panel renders separately before being collected in a PDF. The per panel rendering timeout and number of concurrently rendered panels can be configured.
To modify the panels' clarity you can set a scale factor for the rendered images. A higher scale factor is more legible but will increase the file size of the generated PDF.
These options are available in the [configuration]({{< relref "../installation/configuration.md">}}) file.
When Grafana generates a report, it will render each panel separately and then put them together in a PDF file. You can configure the per-panel rendering request timeout and the maximum number of concurrent calls to the rendering service. These options are available in the [configuration]({{< relref "../installation/configuration.md">}}) file.
```ini
[reporting]
# Set timeout for each panel rendering request
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
concurrent_render_limit = 10
```
## Report time range
Reports use the saved time range of the dashboard. Changing the time range of the report is done by saving a modified time range to the dashboard.
The page header of the report displays the time range for the dashboard's data queries. Dashboards set to use the browser's time zone will use the time zone on the Grafana server.
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. We advise always setting the time zone to UTC for dashboards when using a remote renderer to avoid this.
## Troubleshoot reporting
To troubleshoot and get more log information, enable debug logging in the configuration file. Refer to [Configuration]({{< relref "../installation/configuration.md#filters" >}}) for more information.
```bash
[log]
filters = report:debug
filters = saml.auth:debug
```

View File

@@ -12,7 +12,7 @@ weight = 500
# SAML authentication
SAML authentication integration allows your Grafana users to log in by using an external SAML 2.0 Identity Provider (IdP). To enable this, Grafana becomes a Service Provider (SP) in the authentication flow, interacting with the IdP to exchange user information.
SAML authentication integration allows your Grafana users to log in by using an external SAML Identity Provider (IdP). To enable this, Grafana becomes a Service Provider (SP) in the authentication flow, interacting with the IdP to exchange user information.
The SAML single-sign-on (SSO) standard is varied and flexible. Our implementation contains the subset of features needed to provide a smooth authentication experience into Grafana.
@@ -20,7 +20,7 @@ The SAML single-sign-on (SSO) standard is varied and flexible. Our implementatio
## Supported SAML
Grafana supports the following SAML 2.0 bindings:
Grafana supports the following SAML integrations.
* From the Service Provider (SP) to the Identity Provider (IdP):
- `HTTP-POST` binding
@@ -65,7 +65,7 @@ The SAML SSO standard uses asymmetric encryption to exchange information between
Grafana supports two ways of specifying both the `certificate` and `private_key`.
* Without a suffix (`certificate` or `private_key`), the configuration assumes you've supplied the base64-encoded file contents.
* With the `_path` suffix (`certificate_path` or `private_key_path`), then Grafana treats the value entered as a file path and attempts to read the file from the file system.
* With the `_path` suffix (`certificate_path` or `private_key_path`), then Grafana treats the value entered as a file path and attempt to read the file from the file system.
You can only use one form of each configuration option. Using multiple forms, such as both `certificate` and `certificate_path`, results in an error.

View File

@@ -46,7 +46,6 @@ If you have already grouped some users into a team, then you can synchronize tha
## Supported providers
* [Auth Proxy]({{< relref "../auth/auth-proxy.md#team-sync-enterprise-only">}})
* [Azure AD]({{< relref "../auth/azuread.md#team-sync-enterprise-only" >}})
* [GitHub OAuth]({{< relref "../auth/github.md#team-sync-enterprise-only" >}})
* [GitLab OAuth]({{< relref "../auth/gitlab.md#team-sync-enterprise-only" >}})
* [LDAP]({{< relref "enhanced_ldap.md#ldap-group-synchronization-for-teams" >}})

View File

@@ -1,57 +0,0 @@
+++
title = "Usage-insights"
description = "Usage-insights"
keywords = ["grafana", "usage-insights", "enterprise"]
aliases = ["/docs/grafana/latest/enterprise/usage-insights/"]
type = "docs"
[menu.docs]
name = "Usage-insights"
parent = "enterprise"
weight = 700
+++
# Usage insights
Usage insights allow you to have a better understanding of how your Grafana instance is used. The collected data are the number of:
- Dashboard views (aggregated and per user)
- Data source errors
- Data source queries
> Only available in Grafana Enterprise v7.0+.
## Presence indicator
The presence indicator is visible to all signed-in users on all dashboards. It shows the avatars of users who interacted with the dashboard recently (last 10 minutes by default). You can see the user's name by hovering your cursor over the user's avatar. The avatars come from [Gravatar](https://gravatar.com) based on the user's email.
When more users are active on a dashboard than can fit in the presence indicator section, click on the `+X` icon that opens [dashboard insights]({{< relref "#dashboard-insights" >}}) to see more details about recent user activity.
{{< docs-imagebox img="/img/docs/enterprise/presence_indicators.png" max-width="400px" class="docs-image--no-shadow" >}}
You can choose your own definition of "recent" by setting it in the [configuration]({{< relref "../installation/configuration.md">}}) file.
```ini
[analytics.views]
# Set age for recent active users
recent_users_age = 10m
```
## Dashboard insights
You can see dashboard usage information by clicking on the `Dashboard insights` button in the top bar.
{{< docs-imagebox img="/img/docs/enterprise/dashboard_insights_button.png" max-width="400px" class="docs-image--no-shadow" >}}
It shows two kinds of information:
- **Stats:** Shows the daily query count and error count for the last 30 days.
- **Users & activity:** Shows the daily view count for the last 30 days; last activities on the dashboard and recent users (with a limit of 20).
{{< docs-imagebox img="/img/docs/enterprise/dashboard_insights_stats.png" max-width="400px" class="docs-image--no-shadow" >}}{{< docs-imagebox img="/img/docs/enterprise/dashboard_insights_users.png" max-width="400px" class="docs-image--no-shadow" >}}
## Improved dashboard search
In the search view, you can sort dashboards using these insights data. It helps you find unused or broken dashboards or discover most viewed ones.
{{< docs-imagebox img="/img/docs/enterprise/improved_search.png" max-width="650px" class="docs-image--no-shadow" >}}

View File

@@ -16,7 +16,7 @@ White labeling allows you to replace the Grafana brand and logo with your own co
> Only available in Grafana Enterprise v6.6+.
Grafana Enterprise has white labeling options in the `grafana.ini` file. As with all configuration options, you can also set them with environment variables.
Grafana Enterprise has white labeling options in the `grafana.ini` file. As with all configuration options, you can also be set set them with environment variables.
You can change the following elements:
@@ -26,9 +26,6 @@ You can change the following elements:
- Side menu top logo
- Footer and help menu links
- Fav icon (shown in browser tab)
- Login title (will not appear if a login logo is set, Grafana v7.0+)
- Login subtitle (will not appear if a login logo is set, Grafana v7.0+)
- Login box background (Grafana v7.0+)
> You will have to host your logo and other images used by the white labeling feature separately. Make sure Grafana can access the URL where the assets are stored.
@@ -42,22 +39,13 @@ The configuration file in Grafana Enterprise contains the following options. Eac
# Set to your company name to override application title
;app_title =
# Set to main title on the login page (Will not appear if a login logo is set)
;login_title =
# Set to login subtitle (Will not appear if a login logo is set)
;login_subtitle =
# Set to complete URL to override login logo
;login_logo =
# Set to complete CSS background expression to override login background
# Set to complete css background expression to override login background
# example: login_background = url(http://www.bhmpics.com/wallpapers/starfield-1920x1080.jpg)
;login_background =
# Set to complete CSS background expression to override login box background
;login_box_background =
# Set to complete URL to override menu logo
;menu_logo =
@@ -85,5 +73,5 @@ GF_WHITE_LABELING_FOOTER_LINKS=support guides
GF_WHITE_LABELING_FOOTER_LINKS_SUPPORT_TEXT=Support
GF_WHITE_LABELING_FOOTER_LINKS_SUPPORT_URL=http://your.support.site
GF_WHITE_LABELING_FOOTER_LINKS_GUIDES_TEXT=Guides
GF_WHITE_LABELING_FOOTER_LINKS_GUIDES_URL=http://your.guides.site
GF_WHITE_LABELING_FOOTER_LINKS_GUIDES_URL=http://your.guides.site
```

View File

@@ -18,7 +18,7 @@ A *dashboard* is a set of one or more panels organized and arranged into one or
1. Zoom out time range
2. Time picker dropdown. Here you can access relative time range options, auto refresh options and set custom absolute time ranges.
3. Manual refresh button. Will cause all panels to refresh (fetch new data).
4. Dashboard panel. Click the panel title to edit panels.
4. Dashboard panel. You edit panels by clicking the panel title.
5. Graph legend. You can change series colors, y-axis and series visibility directly from the legend.
## Dashboard header
@@ -30,7 +30,7 @@ Click the new Dashboard link on the right side of the Dashboard picker. You now
The image above shows you the top header for a Dashboard.
1. Side menubar toggle: This toggles the side menu, allowing you to focus on the data presented in the dashboard. The side menu provides access to features unrelated to a Dashboard such as Users, Organizations, and Data Sources.
2. Dashboard dropdown: This dropdown shows you which Dashboard you are currently viewing, and allows you to easily switch to a new Dashboard. From here you can also create a new Dashboard or folder, import existing Dashboards, and manage Dashboard playlists.
2. Dashboard dropdown: This dropdown shows you which Dashboard you are currently viewing, and allows you to easily switch to a new Dashboard. From here you can also create a new Dashboard or folder, Import existing Dashboards, and manage Dashboard playlists.
3. Add Panel: Adds a new panel to the current Dashboard
4. Star Dashboard: Star (or unstar) the current Dashboard. Starred Dashboards will show up on your own Home Dashboard by default, and are a convenient way to mark Dashboards that you're interested in.
5. Share Dashboard: Share the current dashboard by creating a link or create a static Snapshot of it. Make sure the Dashboard is saved before sharing.
@@ -41,7 +41,7 @@ The image above shows you the top header for a Dashboard.
The time period for the dashboard can be controlled by the [Time range controls]({{< relref "../../reference/timerange.md" >}}) in the upper right of the dashboard.
Dashboards can use [templating]({{< relref "../../variables/templates-and-variables.md" >}}) to make them more dynamic and interactive.
Dashboards can use [templating]({{< relref "../../reference/templating.md" >}}) to make them more dynamic and interactive.
Dashboards can use [annotations]({{< relref "../../reference/annotations.md" >}}) to display event data across panels. This can help correlate the time series data in the panel with other events.
@@ -61,4 +61,4 @@ We use a unit abstraction so that Grafana looks great on all screens sizes.
Collapse a row by clicking on the row title. If you save a dashboard with a row collapsed, then it saves in that state and does not load those graphs until you expand the row.
Use the [repeating rows]({{< relref "../../variables/templates-and-variables.md#repeating-rows" >}}) functionality to dynamically create or remove entire rows, which can be filled with panels, based on the template variables selected.
Use the [repeating rows]({{< relref "../../reference/templating.md#repeating-rows" >}}) functionality to dynamically create or remove entire rows, which can be filled with panels, based on the template variables selected.

View File

@@ -1,126 +0,0 @@
+++
title = "Add navigation links"
description = ""
keywords = ["grafana", "linking", "create links", "link panels", "link dashboards", "navigate"]
type = "docs"
aliases = ["/docs/grafana/latest/features/navigation-links/"]
[menu.docs]
identifier = "dashboards"
parent = "features"
weight = 1
+++
# Add navigation links
You can use links to navigate between commonly-used dashboards or to connect others to your visualizations. Links let you create shortcuts to other dashboards, panels, and even external websites.
Grafana supports three types of links: Dashboard Links, Panel Links, and Data Links. They are all available from your dashboard.
{{< docs-imagebox img="/assets/img/blog/dashboard_links.png" max-width="800px" caption="Links Supported in Grafana" >}}
## Which link should you use?
Start by figuring out how you're currently navigating between dashboards. If you're often jumping between a set of dashboards and struggling to find the same context in each, links can help optimize your workflow.
The next step is to figure out which link type is right for your workflow. Even though all the link types in Grafana are used to create shortcuts to other dashboards or external websites, they work in different contexts.
- If the link relates to most if not all of the panels in the dashboard, use a _dashboard link_.
- If you want to drill down into specific panels, use a _panel link_.
- If you want to drill down into a specific series, or even a single measurement, use a _data link_.
## Dashboard links
When you create a dashboard link, you can include the time range and current template variables to directly jump to the same context in another dashboard. This way, you dont have to worry whether the person you send the link to is looking at the right data.
Dashboard links can also be used as shortcuts to external systems, such as submitting [a GitHub issue with the current dashboard name](https://github.com/grafana/grafana/issues/new?title=Dashboard%3A%20HTTP%20Requests).
To see an example of dashboard links in action, check out [this demo](https://play.grafana.org/d/rUpVRdamz/dashboard-links-with-variables?orgId=1).
Once you've added a dashboard link, it appears in the upper right corner of your dashboard.
### Add links to dashboards
Add links to other dashboards at the top of your current dashboard.
1. While viewing the dashboard you want to link, click the gear at the top of the screen to open **Dashboard settings**.
1. Click **Links** and then click **Add Dashboard Link** or **New**.
1. In **Type**, select **dashboards**.
1. Select link options:
- **With tags** Enter tags to limit the linked dashboards to only the ones with the tags you enter. Otherwise, Grafana includes links to all other dashboards.
- **As dropdown** If you are linking to lots of dashboards, then you probably want to select this option and add an optional title to the dropdown. Otherwise, Grafana displays the dashboard links side by side across the top of your dashboard.
- **Time range** Select this option to include the dashboard time range in the link. When the user clicks the link, the linked dashboard opens with the indicated time range already set. **Example:** https://play.grafana.org/d/000000010/annotations?orgId=1&from=now-3h&to=now
- **Variable values** Select this option to include template variables currently used as query parameters in the link. When the user clicks the link, any matching templates in the linked dashboard are set to the values from the link. **Example:** https://play.grafana.org/d/000000074/alerting?var-app=backend&var-server=backend_01&var-server=backend_03&var-interval=1h
- **Open in new tab** Select this option if you want the dashboard link to open in a new tab or window.
1. Click **Add**.
### Add a link to a URL
Add a link to a URL at the top of your current dashboard. You can link to any available URL, including dashboards, panels, or external sites. You can even [control the time range](https://grafana.com/docs/grafana/latest/reference/timerange/#controlling-time-range-using-url) to ensure the user is zoomed in on the right data in Grafana.
1. While viewing the dashboard you want to link, click the gear at the top of the screen to open **Dashboard settings**.
1. Click **Links** and then click **Add Dashboard Link** or **New**.
1. In **Type**, select **link**.
1. Select link options:
- **Url** Enter the URL you want to link to. Depending on the target, you might want to include field values. **Example:** https://github.com/grafana/grafana/issues/new?title=Dashboard%3A%20HTTP%20Requests
- **Title** Enter the title you want the link to display.
- **Tooltip** Enter the tooltip you want the link to display when the user hovers their mouse over it.
- **Icon** Choose the icon you want displayed with the link.
- **Time range** Select this option to include the dashboard time range in the link. When the user clicks the link, the linked dashboard opens with the indicated time range already set. **Example:** https://play.grafana.org/d/000000010/annotations?orgId=1&from=now-3h&to=now
- **Variable values** Select this option to include template variables currently used as query parameters in the link. When the user clicks the link, any matching templates in the linked dashboard are set to the values from the link. **Example:** https://play.grafana.org/d/000000074/alerting?var-app=backend&var-server=backend_01&var-server=backend_03&var-interval=1h
- **Open in new tab** Select this option if you want the dashboard link to open in a new tab or window.
1. Click **Add**.
### Update a dashboard link
To change or update an existing dashboard link, follow this procedure.
1. In Dashboard Settings, on the Links tab, click the existing link that you want to edit.
1. Change the settings and then click **Update**.
### Delete a dashboard link
To delete an existing dashboard link, click the red **X** next to the existing link that you want to delete.
## Panel links
Each panel can have its own set of links that are shown in the upper left corner of the panel. You can link to any available URL, including dashboards, panels, or external sites. You can even [control the time range](https://grafana.com/docs/grafana/latest/reference/timerange/#controlling-time-range-using-url) to ensure the user is zoomed in on the right data in Grafana.
Click the icon on the top left corner of a panel to see available panel links. To see an example of panel links in action, check out [this demo](https://play.grafana.org/d/000000156/dashboard-with-panel-link?orgId=1).
### Add a panel link
1. Hover your cursor over the panel that you want to add a link to and then press `e`. Or click the dropdown arrow next to the panel title and then click **Edit**.
2. Open the **General** tab in the panel settings and then scroll down to the Panel links section.
3. Click **Add link**.
4. Enter a **Title**.
5. If you want the link to open in a new tab, then select **Open in a new tab**.
6. Enter the **URL** you want to link to.
You can even add one of the template variables that are available. Press Ctrl+Space in the **URL** field to see the available variables. By adding template variables to your panel ink, the link sends the user to the right context, with the relevant variables already set.
### Update or delete a panel link
On the panel settings General tab, in the Panel links section, find the panel link that you want to make changes to or delete. Make any necessary changes, or click the **X** to the right of the title to delete the link.
## Data links
Data links allow you to provide more granular context to your links. You can create links that include the series name or even the value under the cursor. For example, if your visualization showed four servers, you could add a data link to one or two of them.
Click directly on the panel to see the data link. It appears on the context menu under **Add annotation**.
To see an example of data links in action, check out [this demo](https://play.grafana.org/d/ZvPm55mWk/new-features-in-v6-3?orgId=1&fullscreen&panelId=27).
## Add a data link to a panel
Currently, data links are only supported in the Graph, Stat, Gauge, and Bar Gauge visualizations.
1. Hover your cursor over the panel that you want to add a link to and then press `e`. Or click the dropdown arrow next to the panel title and then click **Edit**.
1. Open the **Visualization** tab in the panel settings and then scroll down to the Data links section.
1. Click **Add link**.
1. Enter a **Title**.
1. If you want the link to open in a new tab, then select **Open in a new tab**.
1. Enter the **URL** you want to link to.
You can even add one of the template variables that are available. Press Ctrl+Space in the **URL** field to see the available variables. By adding template variables to your panel ink, the link sends the user to the right context, with the relevant variables already set.
### Update or delete a panel link
On the panel settings General tab, in the Panel links section, find the panel link that you want to make changes to or delete. Make any necessary changes, or click the **X** to the right of the title to delete the link.

View File

@@ -38,4 +38,4 @@ The following data sources are officially supported:
## Data source plugins
Since Grafana 3.0 you can install data sources as plugins. Check out [Grafana.com/plugins](https://grafana.com/plugins) for more data sources.
Since Grafana 3.0 you can install data sources as plugins. Check out [Grafana.net](https://grafana.com/plugins) for more data sources.

View File

@@ -12,10 +12,8 @@ weight = 2
Before you create your first dashboard, you need to add your data source. Following are the list of instructions to create one.
> Only users with the Admin role can add data sources.
1. Move your cursor to the cog on the side menu which will show you the configuration menu. If the side menu is not visible click the Grafana icon in the upper left corner. Click on **Configuration** > **Data Sources** in the side menu and you'll be taken to the data sources page
where you can add and edit data sources. You can also click the cog.
where you can add add and edit data sources. You can also click the cog.
{{< docs-imagebox img="/img/docs/v52/sidemenu-datasource.png" max-width="250px" class="docs-image--no-shadow">}}
1. Click **Add data source** and you will come to the settings page of your new data source.
@@ -26,6 +24,6 @@ Before you create your first dashboard, you need to add your data source. Follow
{{< docs-imagebox img="/img/docs/v52/datasource-settings.png" max-width="700px" class="docs-image--no-shadow">}}
1. In the **Type**, select the type of data source. See [Supported data sources]({{< relref "../../features/datasources/#supported-data-sources/" >}}) for more information and how to configure your data source settings.
1. In the **Type**, select the type of data source. See [Supported data sources]({{< relref "../../features/datasources/#supported-data-sources/" >}}) for more information and how to configure your data source.
1. Click **Save & Test**.
1. Click **Save & Test**.

View File

@@ -79,7 +79,7 @@ In the query editor for a panel, after choosing your Azure Monitor data source,
The query editor will change depending on which one you pick. Azure Monitor is the default.
## Querying the Azure Monitor service
## Querying the Azure Monitor Service
The Azure Monitor service provides metrics for all the Azure services that you have running. It helps you understand how your applications on Azure are performing and to proactively find issues affecting your applications.
@@ -93,7 +93,7 @@ Examples of metrics that you can get from the service are:
{{< docs-imagebox img="/img/docs/v60/azuremonitor-service-query-editor.png" class="docs-image--no-shadow" caption="Azure Monitor Query Editor" >}}
### Formatting legend keys with aliases for Azure Monitor
### Formatting Legend Keys with Aliases for the Azure Monitor Service
The default legend formatting for the Azure Monitor API is:
@@ -106,7 +106,7 @@ Azure Monitor Examples:
- `dimension: {{dimensionvalue}}`
- `{{resourcegroup}} - {{resourcename}}`
### Alias patterns for Azure Monitor
### Alias Patterns for Azure Monitor
- `{{resourcegroup}}` = replaced with the value of the Resource Group
- `{{namespace}}` = replaced with the value of the Namespace (e.g. Microsoft.Compute/virtualMachines)
@@ -115,9 +115,9 @@ Azure Monitor Examples:
- `{{dimensionname}}` = replaced with dimension key/label (e.g. blobtype)
- `{{dimensionvalue}}` = replaced with dimension value (e.g. BlockBlob)
### Templating with variables for Azure Monitor
### Templating with Variables for the Azure Monitor Service
Instead of hard-coding things like server, application and sensor name in your metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns make it easy to change the data being displayed in your dashboard.
Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns makes it easy to change the data being displayed in your dashboard.
Note that the Azure Monitor service does not support multiple values yet. If you want to visualize multiple time series (for example, metrics for server1 and server2) then you have to add multiple queries to able to view them on the same graph or in the same table.
@@ -146,14 +146,14 @@ Examples:
{{< docs-imagebox img="/img/docs/v60/azuremonitor-service-variables.png" class="docs-image--no-shadow" caption="Nested Azure Monitor Template Variables" >}}
Check out the [Templating]({{< relref "../../variables/templates-and-variables.md" >}}) documentation for an introduction to the templating feature and the different
Check out the [Templating]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
types of template variables.
### Azure Monitor metrics whitelist
### Azure Monitor Metrics Whitelist
Not all metrics returned by the Azure Monitor API have values. The Grafana data source has a whitelist to only return metric names if it is possible they might have values. This whitelist is updated regularly as new services and metrics are added to the Azure cloud. You can find the current whitelist [here](https://github.com/grafana/grafana/blob/master/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/supported_namespaces.ts).
### Azure Monitor alerting
### Azure Monitor Alerting
Grafana alerting is supported for the Azure Monitor service. This is not Azure Alerts support. Read more about how alerting in Grafana works [here]({{< relref "../../alerting/rules.md" >}}).
@@ -163,7 +163,7 @@ Grafana alerting is supported for the Azure Monitor service. This is not Azure A
{{< docs-imagebox img="/img/docs/v60/appinsights-service-query-editor.png" class="docs-image--no-shadow" caption="Application Insights Query Editor" >}}
### Formatting legend keys with aliases for Application Insights
### Formatting Legend Keys with Aliases for the Application Insights Service
The default legend formatting is:
@@ -177,13 +177,13 @@ Application Insights Examples:
- `city: {{groupbyvalue}}`
- `{{groupbyname}}: {{groupbyvalue}}`
### Alias patterns for Application Insights
### Alias Patterns for Application Insights
- `{{groupbyvalue}}` = replaced with the value of the group by
- `{{groupbyname}}` = replaced with the name/label of the group by
- `{{metric}}` = replaced with metric name (e.g. requests/count)
### Filter expressions for Application Insights
### Filter Expressions for Application Insights
The filter field takes an OData filter expression.
@@ -194,11 +194,11 @@ Examples:
- `client/city ne 'Boydton' and client/city ne 'Dublin'`
- `client/city eq 'Boydton' or client/city eq 'Dublin'`
### Templating with variables for Application Insights
### Templating with Variables for Application Insights
Use the one of the following queries in the `Query` field in the Variable edit view.
Check out the [Templating]({{< relref "../../variables/templates-and-variables.md" >}}) documentation for an introduction to the templating feature and the different
Check out the [Templating]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
types of template variables.
| Name | Description |
@@ -214,13 +214,13 @@ Examples:
{{< docs-imagebox img="/img/docs/v60/appinsights-service-variables.png" class="docs-image--no-shadow" caption="Nested Application Insights Template Variables" >}}
### Application Insights alerting
### Application Insights Alerting
Grafana alerting is supported for Application Insights. This is not Azure Alerts support. Read more about how alerting in Grafana works [here]({{< relref "../../alerting/rules.md" >}}).
{{< docs-imagebox img="/img/docs/v60/azuremonitor-alerting.png" class="docs-image--no-shadow" caption="Azure Monitor Alerting" >}}
## Querying the Azure Log Analytics service
## Querying the Azure Log Analytics Service
Queries are written in the new [Azure Log Analytics (or KustoDB) Query Language](https://docs.loganalytics.io/index). A Log Analytics Query can be formatted as Time Series data or as Table data.
@@ -246,7 +246,7 @@ If your credentials give you access to multiple subscriptions then choose the ap
{{< docs-imagebox img="/img/docs/v60/azureloganalytics-service-query-editor.png" class="docs-image--no-shadow" caption="Azure Log Analytics Query Editor" >}}
### Azure Log Analytics macros
### Azure Log Analytics Macros
To make writing queries easier there are several Grafana macros that can be used in the where clause of a query:
@@ -268,17 +268,17 @@ To make writing queries easier there are several Grafana macros that can be used
If using the `All` option, then check the `Include All Option` checkbox and in the `Custom all value` field type in the following value: `all`. If `$myVar` has value `all` then the macro will instead expand to `1 == 1`. For template variables with a lot of options, this will increase the query performance by not building a large where..in clause.
### Azure Log Analytics builtin variables
### Azure Log Analytics Builtin Variables
There are also some Grafana variables that can be used in Azure Log Analytics queries:
- `$__interval` - Grafana calculates the minimum time grain that can be used to group by time in queries. More details on how it works [here]({{< relref "../../variables/templates-and-variables.md#interval-variables" >}}). It returns a time grain like `5m` or `1h` that can be used in the bin function. E.g. `summarize count() by bin(TimeGenerated, $__interval)`
- `$__interval` - Grafana calculates the minimum time grain that can be used to group by time in queries. More details on how it works [here]({{< relref "../../reference/templating.md#interval-variables" >}}). It returns a time grain like `5m` or `1h` that can be used in the bin function. E.g. `summarize count() by bin(TimeGenerated, $__interval)`
### Templating with variables for Azure Log Analytics
### Templating with Variables for Azure Log Analytics
Any Log Analytics query that returns a list of values can be used in the `Query` field in the Variable edit view. There is also one Grafana function for Log Analytics that returns a list of workspaces.
Refer to the [Variables]({{< relref "../../variables/templates-and-variables.md" >}}) documentation for an introduction to the templating feature and the different
Refer to the [Variables]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
types of template variables.
| Name | Description |
@@ -313,25 +313,11 @@ Perf
| order by TimeGenerated asc
```
### Deep linking from Grafana panels to the Log Analytics query editor in Azure Portal
### Azure Log Analytics Alerting
> Only available in Grafana v7.0+.
Not implemented yet.
{{< docs-imagebox img="/img/docs/v70/azure-log-analytics-deep-linking.png" max-width="500px" class="docs-image--right" caption="Azure Log Analytics deep linking" >}}
Click on a time series in the panel to see a context menu with a link to `View in Azure Portal`. Clicking that link opens the Azure Log Analytics query editor in the Azure Portal and runs the query from the Grafana panel there.
If you're not currently logged in to the Azure Portal, then the link opens the login page. The provided link is valid for any account, but it only displays the query if your account has access to the Azure Log Analytics workspace specified in the query.
<div class="clearfix"></div>
### Azure Log Analytics alerting
> Only available in Grafana v7.0+.
Grafana alerting is supported for Application Insights. This is not Azure Alerts support. Read more about how alerting in Grafana works in [Alerting rules]({{< relref "../../alerting/rules.md" >}}).
### Writing analytics queries For the Application Insights service
### Writing Analytics Queries For the Application Insights Service
If you change the service type to "Application Insights", the menu icon to the right adds another option, "Toggle Edit Mode". Once clicked, the query edit mode changes to give you a full text area in which to write log analytics queries. (This is identical to how the InfluxDB data source lets you write raw queries.)
@@ -346,34 +332,3 @@ There are some important caveats to remember:
- Currently, four default dashboard variables are supported: `$__timeFilter()`, `$__from`, `$__to`, and `$__interval`. If you're searching in timestamped data, replace the beginning of your where clause to `where $__timeFilter()`. Dashboard changes by time region are handled as you'd expect, as long as you leave the name of the `timestamp` column alone. Likewise, `$__interval` will automatically change based on the dashboard's time region _and_ the width of the chart being displayed. Use it in bins, so `bin(timestamp,$__interval)` changes into something like `bin(timestamp,1s)`. Use `$__from` and `$__to` if you just want the formatted dates to be inserted.
- Templated dashboard variables are not yet supported! They will come in a future version.
## Configure the data source with provisioning
It's now possible to configure data sources using config files with Grafana's provisioning system. You can read more about how it works and all the settings you can set for data sources on the [provisioning docs page]({{< relref "../../administration/provisioning/#datasources" >}})
Here are some provisioning examples for this data source.
```yaml
# config file version
apiVersion: 1
datasources:
- name: Azure Monitor
type: grafana-azure-monitor-datasource
access: proxy
jsonData:
appInsightsAppId: <app-insights-app-id>
clientId: <client-id>
cloudName: azuremonitor
subscriptionId: <subscription-id>
tenantId: <tenant-id>
logAnalyticsClientId: <log-analytics-client-id>
logAnalyticsDefaultWorkspace: <log-analytics-default-workspace>
logAnalyticsSubscriptionId: <log-analytics-subscription-id>
logAnalyticsTenantId: <log-analytics-tenant-id>
secureJsonData:
clientSecret: <client-secret>
appInsightsApiKey: <app-insights-api-key>
logAnalyticsClientSecret: <log-analytics-client-secret>
version: 1
```

View File

@@ -43,7 +43,7 @@ server is running on AWS you can use IAM Roles and authentication will be handle
See the AWS documentation on [IAM Roles](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
> NOTE: AWS Role Switching as described [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-cli.html) is not supported at the moment.
> NOTE: AWS Role Switching as described [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-cli.html) it not supported at the moment.
## IAM Policies
@@ -62,8 +62,6 @@ Here is a minimal policy example:
"Effect": "Allow",
"Action": [
"cloudwatch:DescribeAlarmsForMetric",
"cloudwatch:DescribeAlarmHistory",
"cloudwatch:DescribeAlarms",
"cloudwatch:ListMetrics",
"cloudwatch:GetMetricStatistics",
"cloudwatch:GetMetricData"
@@ -182,9 +180,9 @@ To import the pre-configured dashboards, go to the configuration page of your Cl
## Templated queries
Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns make it easy to change the data being displayed in your dashboard.
Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns makes it easy to change the data being displayed in your dashboard.
See the [Templating]({{< relref "../../variables/templates-and-variables.md" >}}) documentation for an introduction to the templating feature and the different types of template variables.
See the [Templating]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different types of template variables.
### Query variable

View File

@@ -17,6 +17,6 @@ Each data source has a specific query editor that is customized for the features
Use the query editor to build one or more queries in your time series database. The panel instantly updates, allowing you to effectively explore your data in real time and build a perfect query for that particular panel.
You can use [template variables]({{< relref "../../variables/templates-and-variables.md" >}}) in the query editor within the queries themselves. This provides a powerful way to explore data dynamically based on the templating variables selected on the dashboard.
You can use [template variables]({{< relref "../../reference/templating.md" >}}) in the query editor within the queries themselves. This provides a powerful way to explore data dynamically based on the templating variables selected on the dashboard.
Grafana allows you to reference queries in the query editor by the row that theyre on. If you add a second query to graph, you can reference the first query by typing in #A. This provides an easy and convenient way to build compound queries.

View File

@@ -116,11 +116,11 @@ Some metric aggregations are called Pipeline aggregations, for example, *Moving
## Templating
Instead of hard-coding things like server, application and sensor name in your metric queries you can use variables in their place.
Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns make it easy to change the data
Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place.
Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns makes it easy to change the data
being displayed in your dashboard.
Check out the [Templating]({{< relref "../../variables/templates-and-variables.md" >}}) documentation for an introduction to the templating feature and the different
Check out the [Templating]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
types of template variables.
### Query variable
@@ -172,7 +172,7 @@ Example dashboard:
## Annotations
[Annotations]({{< relref "../../reference/annotations.md" >}}) allow you to overlay rich event information on top of graphs. You add annotation
[Annotations]({{< relref "../../reference/annotations.md" >}}) allows you to overlay rich event information on top of graphs. You add annotation
queries via the Dashboard menu / Annotations view. Grafana can query any Elasticsearch index
for annotation events.

View File

@@ -47,7 +47,7 @@ All requests will be made from the browser directly to the data source and may b
### Navigate metric segments
Click the ``Select metric`` link to start navigating the metric space. Once you start you can continue using the mouse
Click the ``Select metric`` link to start navigating the metric space. One you start you can continue using the mouse
or keyboard arrow keys. You can select a wildcard and still continue.
{{< docs-imagebox img="/img/docs/v45/graphite_query1_still.png"
@@ -87,11 +87,11 @@ this consolidation is done using `avg` function. You can control how Graphite co
## Templating
Instead of hard-coding things like server, application and sensor name in your metric queries you can use variables in their place.
Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns make it easy to change the data
Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place.
Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns makes it easy to change the data
being displayed in your dashboard.
Check out the [Templating]({{< relref "../../variables/templates-and-variables.md" >}}) documentation for an introduction to the templating feature and the different
Check out the [Templating]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
types of template variables.
Graphite 1.1 introduced tags and Grafana added support for Graphite queries with tags in version 5.0. To create a variable using tag values, then you need to use the Grafana functions `tags` and `tag_values`.
@@ -132,6 +132,7 @@ TagValues
tag_values(server, server=~${__searchFilter:regex})
```
### Variable Usage
You can use a variable in a metric node path or as a parameter to a function.
@@ -158,20 +159,16 @@ Example of a tag expression with regex formatting and using the Equal Tilde oper
server=~${servers:regex}
```
Check out the [Advanced Formatting Options section in the Variables]({{< relref "../../variables/templates-and-variables.md#advanced-formatting-options" >}}) documentation for examples and details.
Check out the [Advanced Formatting Options section in the Variables]({{< relref "../../reference/templating.md#advanced-formatting-options" >}}) documentation for examples and details.
## Annotations
[Annotations]({{< relref "../../reference/annotations.md" >}}) allow you to overlay rich event information on top of graphs. You add annotation
[Annotations]({{< relref "../../reference/annotations.md" >}}) allows you to overlay rich event information on top of graphs. You add annotation
queries via the Dashboard menu / Annotations view.
Graphite supports two ways to query annotations. A regular metric query, for this you use the `Graphite query` textbox. A Graphite events query, use the `Graphite event tags` textbox,
specify a tag or wildcard (leave empty should also work)
## Getting Grafana metrics into Graphite
Grafana exposes metrics for Graphite on the `/metrics` endpoint. For detailed instructions, refer to [Internal Grafana metrics]({{< relref "../../administration/metrics.md">}}).
## Configure the data source with provisioning
It's now possible to configure data sources using config files with Grafana's provisioning system. You can read more about how it works and all the settings you can set for data sources on the [provisioning docs page]({{< relref "../../administration/provisioning/#datasources" >}})

View File

@@ -140,11 +140,11 @@ To add a filter click the plus icon to the right of the `Measurements/Fields` bu
## Templating
Instead of hard-coding things like server, application and sensor name in your metric queries you can use variables in their place.
Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns make it easy to change the data
Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place.
Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns makes it easy to change the data
being displayed in your dashboard.
Check out the [Templating]({{< relref "../../variables/templates-and-variables.md" >}}) documentation for an introduction to the templating feature and the different
Check out the [Templating]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
types of template variables.
### Query variable

View File

@@ -39,16 +39,14 @@ Just add it as a data source and you are ready to query your log data in [Explor
### Derived fields
The Derived Fields configuration allows you to:
* Add fields parsed from the log message.
* Add a link that uses the value of the field.
You can use this functionality to link to your tracing backend directly from your logs, or link to a user profile page if a userId is present in the log line. These links appear in the [log details](/features/explore/#labels-and-parsed-fields).
You can use this functionality to link to your tracing backend directly from your logs, or link to a user profile page if a userId is present in the log line. These links will be shown in the [log details](/features/explore/#labels-and-parsed-fields).
{{< docs-imagebox img="/img/docs/v65/loki_derived_fields.png" class="docs-image--no-shadow" caption="Screenshot of the derived fields configuration" >}}
Each derived field consists of:
- **Name:** Shown in the log details as a label.
- **Regex:** A Regex pattern that runs on the log message and captures part of it as the value of the new field. Can only contain a single capture group.
- **Regex:** A Regex pattern that runs on the log message and captures part of it to as the value of the new field. Can only contain capture a single group.
- **URL**: A URL template used to construct a link next to the field value in log details. Use special `${__value.raw}` value in your template to interpolate the real field value into your URL template.
You can use a debug section to see what your fields extract and how the URL is interpolated. Click **Show example log message** to show the text area where you can enter a log message.
@@ -71,7 +69,7 @@ Once the result is returned, the log panel shows a list of log rows and a bar ch
<div class="medium-6 columns">
<video width="800" height="500" controls>
<source src="/assets/videos/explore_loki.mp4" type="video/mp4">
<source src="https://grafana.com/static/assets/videos/explore_loki.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
@@ -98,7 +96,7 @@ Examples:
The [same rules that apply for Prometheus Label Selectors](https://prometheus.io/docs/prometheus/latest/querying/basics/#instant-vector-selectors) apply for Loki Log Stream Selectors.
Another way to add a label selector is in the table section. Click **Filter** beside a label to add the label to the query expression. This even works for multiple queries and will add the label selector to each query.
Another way to add a label selector, is in the table section, clicking on the **Filter** button beside a label will add the label to the query expression. This even works for multiple queries and will the label selector to each query.
### Search Expression
@@ -127,7 +125,7 @@ The following filter types are currently supported:
## Live tailing
Loki supports Live tailing which displays logs in real-time. This feature is supported in [Explore]({{< relref "../explore/#loki-specific-features" >}}).
Loki supports Live tailing which displays logs in real-time. This feature is supported in [Explore]({{< relref "../explore/#loki-specific-features" >}}) and in dashboards with a Live toggle in the query editor.
Note that Live Tailing relies on two Websocket connections: one between the browser and the Grafana server, and another between the Grafana server and the Loki server. If you run any reverse proxies, please configure them accordingly.
@@ -146,7 +144,7 @@ log message you're interested in.
Instead of hard-coding things like server, application and sensor name in your metric queries, you can use variables in their place. Variables are shown as drop-down select boxes at the top of the dashboard. These drop-down boxes make it easy to change the data being displayed in your dashboard.
Check out the [Templating]({{< relref "../../variables/templates-and-variables" >}}) documentation for an introduction to the templating feature and the different types of template variables.
Check out the [Templating]({{< relref "../../reference/templating" >}}) documentation for an introduction to the templating feature and the different types of template variables.
## Annotations
@@ -189,16 +187,8 @@ datasources:
jsonData:
maxLines: 1000
derivedFields:
# Field with internal link pointing to data source in Grafana.
# Right now, Grafana supports only Jaeger and Zipkin data sources as link targets.
- datasourceUid: my_jaeger_uid
- datasourceName: Jaeger
matcherRegex: "traceID=(\\w+)"
name: TraceID
# url will be interpreted as query for the datasource
url: "$${__value.raw}"
# Field with external link.
- matcherRegex: "traceID=(\\w+)"
name: TraceID
url: "http://localhost:16686/trace/$${__value.raw}"
```

View File

@@ -39,7 +39,7 @@ Name | Description
### Min time interval
A lower limit for the [$__interval]({{< relref "../../variables/templates-and-variables/#the-interval-variable" >}}) and [$__interval_ms]({{< relref "../../variables/templates-and-variables/#the-interval-ms-variable" >}}) variables.
A lower limit for the [$__interval]({{< relref "../../reference/templating/#the-interval-variable" >}}) and [$__interval_ms]({{< relref "../../reference/templating/#the-interval-ms-variable" >}}) variables.
Recommended to be set to write frequency, for example `1m` if your data is written every minute.
This option can also be overridden/configured in a dashboard panel under data source options. It's important to note that this value **needs** to be formatted as a
number followed by a valid time identifier, e.g. `1m` (1 minute) or `30s` (30 seconds). The following time identifiers are supported:
@@ -80,7 +80,7 @@ If possible, we recommend you to use the latest service pack available for optim
{{< docs-imagebox img="/img/docs/v51/mssql_query_editor.png" class="docs-image--no-shadow" >}}
You will find the MSSQL query editor in the metrics tab in Graph, Singlestat or Table panel's edit mode. You enter edit mode by clicking the
You find the MSSQL query editor in the metrics tab in Graph, Singlestat or Table panel's edit mode. You enter edit mode by clicking the
panel title, then edit. The editor allows you to define a SQL query to select data to be visualized.
1. Select *Format as* `Time series` (for use in Graph or Singlestat panel's among others) or `Table` (for use in Table panel among others).
@@ -97,24 +97,24 @@ To simplify syntax and to allow for dynamic parts, like date range filters, the
Macro example | Description
------------ | -------------
*`$__time(dateColumn)`* | Will be replaced by an expression to rename the column to *time*. For example, *dateColumn as time*
*`$__timeEpoch(dateColumn)`* | Will be replaced by an expression to convert a DATETIME column type to Unix timestamp and rename it to *time*. <br/>For example, *DATEDIFF(second, '1970-01-01', dateColumn) AS time*
*`$__timeFilter(dateColumn)`* | Will be replaced by a time range filter using the specified column name. <br/>For example, *dateColumn BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:06:17Z'*
*`$__timeFrom()`* | Will be replaced by the start of the currently active time selection. For example, *'2017-04-21T05:01:17Z'*
*`$__timeTo()`* | Will be replaced by the end of the currently active time selection. For example, *'2017-04-21T05:06:17Z'*
*`$__timeGroup(dateColumn,'5m'[, fillvalue])`* | Will be replaced by an expression usable in GROUP BY clause. Providing a *fillValue* of *NULL* or *floating value* will automatically fill empty series in timerange with that value. <br/>For example, *CAST(ROUND(DATEDIFF(second, '1970-01-01', time_column)/300.0, 0) as bigint)\*300*.
*`$__timeGroup(dateColumn,'5m', 0)`* | Same as above but with a fill parameter so missing points in that series will be added by grafana and 0 will be used as value.
*`$__timeGroup(dateColumn,'5m', NULL)`* | Same as above but NULL will be used as value for missing points.
*`$__timeGroup(dateColumn,'5m', previous)`* | Same as above but the previous value in that series will be used as fill value if no value has been seen yet NULL will be used (only available in Grafana 5.3+).
*`$__timeGroupAlias(dateColumn,'5m')`* | Will be replaced identical to $__timeGroup but with an added column alias (only available in Grafana 5.3+).
*`$__unixEpochFilter(dateColumn)`* | Will be replaced by a time range filter using the specified column name with times represented as Unix timestamp. For example, *dateColumn > 1494410783 AND dateColumn < 1494497183*
*`$__unixEpochFrom()`* | Will be replaced by the start of the currently active time selection as Unix timestamp. For example, *1494410783*
*`$__unixEpochTo()`* | Will be replaced by the end of the currently active time selection as Unix timestamp. For example, *1494497183*
*`$__unixEpochNanoFilter(dateColumn)`* | Will be replaced by a time range filter using the specified column name with times represented as nanosecond timestamp. For example, *dateColumn > 1494410783152415214 AND dateColumn < 1494497183142514872*
*`$__unixEpochNanoFrom()`* | Will be replaced by the start of the currently active time selection as nanosecond timestamp. For example, *1494410783152415214*
*`$__unixEpochNanoTo()`* | Will be replaced by the end of the currently active time selection as nanosecond timestamp. For example, *1494497183142514872*
*`$__unixEpochGroup(dateColumn,'5m', [fillmode])`* | Same as $__timeGroup but for times stored as Unix timestamp (only available in Grafana 5.3+).
*`$__unixEpochGroupAlias(dateColumn,'5m', [fillmode])`* | Same as above but also adds a column alias (only available in Grafana 5.3+).
*$__time(dateColumn)* | Will be replaced by an expression to rename the column to *time*. For example, *dateColumn as time*
*$__timeEpoch(dateColumn)* | Will be replaced by an expression to convert a DATETIME column type to Unix timestamp and rename it to *time*. <br/>For example, *DATEDIFF(second, '1970-01-01', dateColumn) AS time*
*$__timeFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name. <br/>For example, *dateColumn BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:06:17Z'*
*$__timeFrom()* | Will be replaced by the start of the currently active time selection. For example, *'2017-04-21T05:01:17Z'*
*$__timeTo()* | Will be replaced by the end of the currently active time selection. For example, *'2017-04-21T05:06:17Z'*
*$__timeGroup(dateColumn,'5m'[, fillvalue])* | Will be replaced by an expression usable in GROUP BY clause. Providing a *fillValue* of *NULL* or *floating value* will automatically fill empty series in timerange with that value. <br/>For example, *CAST(ROUND(DATEDIFF(second, '1970-01-01', time_column)/300.0, 0) as bigint)\*300*.
*$__timeGroup(dateColumn,'5m', 0)* | Same as above but with a fill parameter so missing points in that series will be added by grafana and 0 will be used as value.
*$__timeGroup(dateColumn,'5m', NULL)* | Same as above but NULL will be used as value for missing points.
*$__timeGroup(dateColumn,'5m', previous)* | Same as above but the previous value in that series will be used as fill value if no value has been seen yet NULL will be used (only available in Grafana 5.3+).
*$__timeGroupAlias(dateColumn,'5m')* | Will be replaced identical to $__timeGroup but with an added column alias (only available in Grafana 5.3+).
*$__unixEpochFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name with times represented as Unix timestamp. For example, *dateColumn > 1494410783 AND dateColumn < 1494497183*
*$__unixEpochFrom()* | Will be replaced by the start of the currently active time selection as Unix timestamp. For example, *1494410783*
*$__unixEpochTo()* | Will be replaced by the end of the currently active time selection as Unix timestamp. For example, *1494497183*
*$__unixEpochNanoFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name with times represented as nanosecond timestamp. For example, *dateColumn > 1494410783152415214 AND dateColumn < 1494497183142514872*
*$__unixEpochNanoFrom()* | Will be replaced by the start of the currently active time selection as nanosecond timestamp. For example, *1494410783152415214*
*$__unixEpochNanoTo()* | Will be replaced by the end of the currently active time selection as nanosecond timestamp. For example, *1494497183142514872*
*$__unixEpochGroup(dateColumn,'5m', [fillmode])* | Same as $__timeGroup but for times stored as Unix timestamp (only available in Grafana 5.3+).
*$__unixEpochGroupAlias(dateColumn,'5m', [fillmode])* | Same as above but also adds a column alias (only available in Grafana 5.3+).
We plan to add many more macros. If you have suggestions for what macros you would like to see, please [open an issue](https://github.com/grafana/grafana) in our GitHub repo.
@@ -293,14 +293,14 @@ GROUP BY
ORDER BY 1
```
When the above query is used in a graph panel, the result is two series named `Metric A` and `Metric B` with a sum of `valueTwo` plotted over `time`.
When above query are used in a graph panel the result will be two series named `Metric A` and `Metric B` with a sum of `valueTwo` plotted over `time`.
Any series lacking a value in a 3 minute window will have a value of zero which you'll see rendered in the graph to the right.
## Templating
Instead of hard-coding things like server, application and sensor name in your metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns make it easy to change the data being displayed in your dashboard.
Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns makes it easy to change the data being displayed in your dashboard.
Check out the [Templating]({{< relref "../../variables/templates-and-variables.md" >}}) documentation for an introduction to the templating feature and the different types of template variables.
Check out the [Templating]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different types of template variables.
### Query Variable
@@ -319,7 +319,7 @@ A query can return multiple columns and Grafana will automatically create a list
SELECT [host].[hostname], [other_host].[hostname2] FROM host JOIN other_host ON [host].[city] = [other_host].[city]
```
Another option is a query that can create a key/value variable. The query should return two columns that are named `__text` and `__value`. The `__text` column value should be unique (if it is not unique then the first value is used). The options in the dropdown will have a text and value that allow you to have a friendly name as text and an id as the value. An example query with `hostname` as the text and `id` as the value:
Another option is a query that can create a key/value variable. The query should return two columns that are named `__text` and `__value`. The `__text` column value should be unique (if it is not unique then the first value is used). The options in the dropdown will have a text and value that allows you to have a friendly name as text and an id as the value. An example query with `hostname` as the text and `id` as the value:
```sql
SELECT hostname __text, id __value FROM host
@@ -370,18 +370,18 @@ Grafana automatically creates a quoted, comma-separated string for multi-value v
`${servers:csv}`
Read more about variable formatting options in the [Variables]({{< relref "../../variables/templates-and-variables.md#advanced-formatting-options" >}}) documentation.
Read more about variable formatting options in the [Variables]({{< relref "../../reference/templating.md#advanced-formatting-options" >}}) documentation.
## Annotations
[Annotations]({{< relref "../../reference/annotations.md" >}}) allow you to overlay rich event information on top of graphs. You add annotation queries via the Dashboard menu / Annotations view.
[Annotations]({{< relref "../../reference/annotations.md" >}}) allows you to overlay rich event information on top of graphs. You add annotation queries via the Dashboard menu / Annotations view.
**Columns:**
Name | Description
------------ | -------------
time | The name of the date/time field. Could be a column with a native SQL date/time data type or epoch value.
timeend | Optional name of the end date/time field. Could be a column with a native SQL date/time data type or epoch value. (Grafana v6.6+)
timeend | Optional name of the end date/time field. Could be a column with a native SQL date/time data type or epoch value.
text | Event description field.
tags | Optional field name to use for event tags as a comma separated string.
@@ -411,23 +411,6 @@ WHERE
ORDER BY 1
```
**Example region query using time and timeend columns with epoch values:**
> Only available in Grafana v6.6+.
```sql
SELECT
time_sec as time,
time_end_sec as timeend,
description as [text],
tags
FROM
[events]
WHERE
$__unixEpochFilter(time_sec)
ORDER BY 1
```
**Example query using time column of native SQL date/time data type:**
```sql
@@ -444,7 +427,7 @@ ORDER BY 1
## Stored procedure support
Stored procedures have been verified to work. However, please note that we haven't done anything special to support this, so there might be edge cases where it won't work as you would expect.
Stored procedures have been verified to work. However, please note that we haven't done anything special to support this why there may exist edge cases where it won't work as you would expect.
Stored procedures should be supported in table, time series and annotation queries as long as you use the same naming of columns and return data in the same format as describe above under respective section.
Please note that any macro function will not work inside a stored procedure.
@@ -452,7 +435,7 @@ Please note that any macro function will not work inside a stored procedure.
### Examples
{{< docs-imagebox img="/img/docs/v51/mssql_metrics_graph.png" class="docs-image--no-shadow docs-image--right" >}}
For the following examples the database table is defined in [Time series queries](#time-series-queries). Let's say that we want to visualize 4 series in a graph panel, i.e. all combinations of columns `valueOne`, `valueTwo` and `measurement`. Graph panel to the right visualizes what we want to achieve. To solve this we actually need to use two queries:
For the following examples the database table defined in [Time series queries](#time-series-queries). Let's say that we want to visualize 4 series in a graph panel, i.e. all combinations of columns `valueOne`, `valueTwo` and `measurement`. Graph panel to the right visualizes what we want to achieve. To solve this we actually need to use two queries:
**First query:**
@@ -491,7 +474,7 @@ We can define a stored procedure that will return all data we need to render 4 s
In this case the stored procedure accepts two parameters `@from` and `@to` of `int` data types which should be a timerange (from-to) in epoch format
which will be used to filter the data to return from the stored procedure.
We're mimicking the `$__timeGroup(time, '5m')` in the select and group by expressions, and that's why there are a lot of lengthy expressions needed -
We're mimicking the `$__timeGroup(time, '5m')` in the select and group by expressions and that's why there's a lot of lengthy expressions needed -
these could be extracted to MSSQL functions, if wanted.
```sql

View File

@@ -15,7 +15,7 @@ weight = 7
>
> Starting from Grafana v5.1 you can name the time column *time* in addition to earlier supported *time_sec*. Usage of *time_sec* will eventually be deprecated.
Grafana ships with a built-in MySQL data source plugin that allows you to query and visualize
Grafana ships with a built-in MySQL data source plugin that allow you to query any visualize
data from a MySQL compatible database.
## Adding the data source
@@ -41,7 +41,7 @@ Name | Description
### Min time interval
A lower limit for the [$__interval]({{< relref "../../variables/templates-and-variables/#the-interval-variable" >}}) and [$__interval_ms]({{< relref "../../variables/templates-and-variables/#the-interval-ms-variable" >}}) variables.
A lower limit for the [$__interval]({{< relref "../../reference/templating/#the-interval-variable" >}}) and [$__interval_ms]({{< relref "../../reference/templating/#the-interval-ms-variable" >}}) variables.
Recommended to be set to write frequency, for example `1m` if your data is written every minute.
This option can also be overridden/configured in a dashboard panel under data source options. It's important to note that this value **needs** to be formatted as a
number followed by a valid time identifier, e.g. `1m` (1 minute) or `30s` (30 seconds). The following time identifiers are supported:
@@ -131,28 +131,28 @@ To simplify syntax and to allow for dynamic parts, like date range filters, the
Macro example | Description
------------ | -------------
*`$__time(dateColumn)`* | Will be replaced by an expression to convert to a UNIX timestamp and rename the column to `time_sec`. For example, *UNIX_TIMESTAMP(dateColumn) as time_sec*
*`$__timeEpoch(dateColumn)`* | Will be replaced by an expression to convert to a UNIX timestamp and rename the column to `time_sec`. For example, *UNIX_TIMESTAMP(dateColumn) as time_sec*
*`$__timeFilter(dateColumn)`* | Will be replaced by a time range filter using the specified column name. For example, *dateColumn BETWEEN FROM_UNIXTIME(1494410783) AND FROM_UNIXTIME(1494410983)*
*`$__timeFrom()`* | Will be replaced by the start of the currently active time selection. For example, *FROM_UNIXTIME(1494410783)*
*`$__timeTo()`* | Will be replaced by the end of the currently active time selection. For example, *FROM_UNIXTIME(1494410983)*
*`$__timeGroup(dateColumn,'5m')`* | Will be replaced by an expression usable in GROUP BY clause. For example, *cast(cast(UNIX_TIMESTAMP(dateColumn)/(300) as signed)*300 as signed),*
*`$__timeGroup(dateColumn,'5m', 0)`* | Same as above but with a fill parameter so missing points in that series will be added by grafana and 0 will be used as value.
*`$__timeGroup(dateColumn,'5m', NULL)`* | Same as above but NULL will be used as value for missing points.
*`$__timeGroup(dateColumn,'5m', previous)`* | Same as above but the previous value in that series will be used as fill value if no value has been seen yet NULL will be used (only available in Grafana 5.3+).
*`$__timeGroupAlias(dateColumn,'5m')`* | Will be replaced identical to $__timeGroup but with an added column alias (only available in Grafana 5.3+).
*`$__unixEpochFilter(dateColumn)`* | Will be replaced by a time range filter using the specified column name with times represented as Unix timestamp. For example, *dateColumn > 1494410783 AND dateColumn < 1494497183*
*`$__unixEpochFrom()`* | Will be replaced by the start of the currently active time selection as Unix timestamp. For example, *1494410783*
*`$__unixEpochTo()`* | Will be replaced by the end of the currently active time selection as Unix timestamp. For example, *1494497183*
*`$__unixEpochNanoFilter(dateColumn)`* | Will be replaced by a time range filter using the specified column name with times represented as nanosecond timestamp. For example, *dateColumn > 1494410783152415214 AND dateColumn < 1494497183142514872*
*`$__unixEpochNanoFrom()`* | Will be replaced by the start of the currently active time selection as nanosecond timestamp. For example, *1494410783152415214*
*`$__unixEpochNanoTo()`* | Will be replaced by the end of the currently active time selection as nanosecond timestamp. For example, *1494497183142514872*
*`$__unixEpochGroup(dateColumn,'5m', [fillmode])`* | Same as $__timeGroup but for times stored as Unix timestamp (only available in Grafana 5.3+).
*`$__unixEpochGroupAlias(dateColumn,'5m', [fillmode])`* | Same as above but also adds a column alias (only available in Grafana 5.3+).
*$__time(dateColumn)* | Will be replaced by an expression to convert to a UNIX timestamp and rename the column to `time_sec`. For example, *UNIX_TIMESTAMP(dateColumn) as time_sec*
*$__timeEpoch(dateColumn)* | Will be replaced by an expression to convert to a UNIX timestamp and rename the column to `time_sec`. For example, *UNIX_TIMESTAMP(dateColumn) as time_sec*
*$__timeFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name. For example, *dateColumn BETWEEN FROM_UNIXTIME(1494410783) AND FROM_UNIXTIME(1494410983)*
*$__timeFrom()* | Will be replaced by the start of the currently active time selection. For example, *FROM_UNIXTIME(1494410783)*
*$__timeTo()* | Will be replaced by the end of the currently active time selection. For example, *FROM_UNIXTIME(1494410983)*
*$__timeGroup(dateColumn,'5m')* | Will be replaced by an expression usable in GROUP BY clause. For example, *cast(cast(UNIX_TIMESTAMP(dateColumn)/(300) as signed)*300 as signed),*
*$__timeGroup(dateColumn,'5m', 0)* | Same as above but with a fill parameter so missing points in that series will be added by grafana and 0 will be used as value.
*$__timeGroup(dateColumn,'5m', NULL)* | Same as above but NULL will be used as value for missing points.
*$__timeGroup(dateColumn,'5m', previous)* | Same as above but the previous value in that series will be used as fill value if no value has been seen yet NULL will be used (only available in Grafana 5.3+).
*$__timeGroupAlias(dateColumn,'5m')* | Will be replaced identical to $__timeGroup but with an added column alias (only available in Grafana 5.3+).
*$__unixEpochFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name with times represented as Unix timestamp. For example, *dateColumn > 1494410783 AND dateColumn < 1494497183*
*$__unixEpochFrom()* | Will be replaced by the start of the currently active time selection as Unix timestamp. For example, *1494410783*
*$__unixEpochTo()* | Will be replaced by the end of the currently active time selection as Unix timestamp. For example, *1494497183*
*$__unixEpochNanoFilter(dateColumn)* | Will be replaced by a time range filter using the specified column name with times represented as nanosecond timestamp. For example, *dateColumn > 1494410783152415214 AND dateColumn < 1494497183142514872*
*$__unixEpochNanoFrom()* | Will be replaced by the start of the currently active time selection as nanosecond timestamp. For example, *1494410783152415214*
*$__unixEpochNanoTo()* | Will be replaced by the end of the currently active time selection as nanosecond timestamp. For example, *1494497183142514872*
*$__unixEpochGroup(dateColumn,'5m', [fillmode])* | Same as $__timeGroup but for times stored as Unix timestamp (only available in Grafana 5.3+).
*$__unixEpochGroupAlias(dateColumn,'5m', [fillmode])* | Same as above but also adds a column alias (only available in Grafana 5.3+).
We plan to add many more macros. If you have suggestions for what macros you would like to see, please [open an issue](https://github.com/grafana/grafana) in our GitHub repo.
The query editor has a link named `Generated SQL` that shows up after a query has been executed, while in panel edit mode. Click on it and it will expand and show the raw interpolated SQL string that was executed.
The query editor has a link named `Generated SQL` that show up after a query as been executed, while in panel edit mode. Click on it and it will expand and show the raw interpolated SQL string that was executed.
## Table queries
@@ -236,9 +236,9 @@ This is something we plan to add.
This feature is currently available in the nightly builds and will be included in the 5.0.0 release.
Instead of hard-coding things like server, application and sensor name in your metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns make it easy to change the data being displayed in your dashboard.
Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns makes it easy to change the data being displayed in your dashboard.
Check out the [Templating]({{< relref "../../variables/templates-and-variables.md" >}}) documentation for an introduction to the templating feature and the different types of template variables.
Check out the [Templating]({{< relref "../../reference/templating.md" >}}) documentation for an introduction to the templating feature and the different types of template variables.
### Query Variable
@@ -251,7 +251,7 @@ For example, you can have a variable that contains all values for the `hostname`
SELECT hostname FROM my_host
```
A query can return multiple columns and Grafana will automatically create a list from them. For example, the query below will return a list with values from `hostname` and `hostname2`.
A query can returns multiple columns and Grafana will automatically create a list from them. For example, the query below will return a list with values from `hostname` and `hostname2`.
```sql
SELECT my_host.hostname, my_other_host.hostname2 FROM my_host JOIN my_other_host ON my_host.city = my_other_host.city
@@ -331,7 +331,7 @@ Grafana automatically creates a quoted, comma-separated string for multi-value v
`${servers:csv}`
Read more about variable formatting options in the [Variables]({{< relref "../../variables/templates-and-variables.md#advanced-formatting-options" >}}) documentation.
Read more about variable formatting options in the [Variables]({{< relref "../../reference/templating.md#advanced-formatting-options" >}}) documentation.
## Annotations
@@ -350,22 +350,6 @@ WHERE
$__unixEpochFilter(epoch_time)
```
**Example region query using time and timeend columns with epoch values:**
> Only available in Grafana v6.6+.
```sql
SELECT
epoch_time as time,
epoch_timeend as timeend,
metric1 as text,
CONCAT(tag1, ',', tag2) as tags
FROM
public.test_data
WHERE
$__unixEpochFilter(epoch_time)
```
**Example query using time column of native SQL date/time data type:**
```sql
@@ -382,13 +366,13 @@ WHERE
Name | Description
------------ | -------------
time | The name of the date/time field. Could be a column with a native SQL date/time data type or epoch value.
timeend | Optional name of the end date/time field. Could be a column with a native SQL date/time data type or epoch value. (Grafana v6.6+)
timeend | Optional name of the end date/time field. Could be a column with a native SQL date/time data type or epoch value.
text | Event description field.
tags | Optional field name to use for event tags as a comma separated string.
## Alerting
Time series queries should work in alerting conditions. Table formatted queries are not yet supported in alert rule conditions.
Time series queries should work in alerting conditions. Table formatted queries is not yet supported in alert rule conditions.
## Configure the data source with provisioning

Some files were not shown because too many files have changed in this diff Show More