mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
plugin change: make interval, cache timeout & max data points options in plugin.json, remove query.options component feature, add help markdown feature and toggle for data sources
This commit is contained in:
parent
9b60a63778
commit
84d4958a3c
@ -209,7 +209,7 @@ func (hs *HttpServer) registerRoutes() {
|
|||||||
|
|
||||||
r.Get("/plugins", wrap(GetPluginList))
|
r.Get("/plugins", wrap(GetPluginList))
|
||||||
r.Get("/plugins/:pluginId/settings", wrap(GetPluginSettingById))
|
r.Get("/plugins/:pluginId/settings", wrap(GetPluginSettingById))
|
||||||
r.Get("/plugins/:pluginId/readme", wrap(GetPluginReadme))
|
r.Get("/plugins/:pluginId/markdown/:name", wrap(GetPluginMarkdown))
|
||||||
|
|
||||||
r.Group("/plugins", func() {
|
r.Group("/plugins", func() {
|
||||||
r.Get("/:pluginId/dashboards/", wrap(GetPluginDashboards))
|
r.Get("/:pluginId/dashboards/", wrap(GetPluginDashboards))
|
||||||
|
@ -147,15 +147,16 @@ func GetPluginDashboards(c *middleware.Context) Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPluginReadme(c *middleware.Context) Response {
|
func GetPluginMarkdown(c *middleware.Context) Response {
|
||||||
pluginId := c.Params(":pluginId")
|
pluginId := c.Params(":pluginId")
|
||||||
|
name := c.Params(":name")
|
||||||
|
|
||||||
if content, err := plugins.GetPluginReadme(pluginId); err != nil {
|
if content, err := plugins.GetPluginMarkdown(pluginId, name); err != nil {
|
||||||
if notfound, ok := err.(plugins.PluginNotFoundError); ok {
|
if notfound, ok := err.(plugins.PluginNotFoundError); ok {
|
||||||
return ApiError(404, notfound.Error(), nil)
|
return ApiError(404, notfound.Error(), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiError(500, "Could not get readme", err)
|
return ApiError(500, "Could not get markdown file", err)
|
||||||
} else {
|
} else {
|
||||||
return Respond(200, content)
|
return Respond(200, content)
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,24 @@
|
|||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import "encoding/json"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
type DataSourcePlugin struct {
|
type DataSourcePlugin struct {
|
||||||
FrontendPluginBase
|
FrontendPluginBase
|
||||||
Annotations bool `json:"annotations"`
|
Annotations bool `json:"annotations"`
|
||||||
Metrics bool `json:"metrics"`
|
Metrics bool `json:"metrics"`
|
||||||
Alerting bool `json:"alerting"`
|
Alerting bool `json:"alerting"`
|
||||||
BuiltIn bool `json:"builtIn"`
|
MinInterval bool `json:"minInterval,omitempty"`
|
||||||
Mixed bool `json:"mixed"`
|
CacheTimeout bool `json:"cacheTimeout,omitempty"`
|
||||||
Routes []*AppPluginRoute `json:"routes"`
|
MaxDataPoints bool `json:"maxDataPoints,omitempty"`
|
||||||
|
BuiltIn bool `json:"builtIn,omitempty"`
|
||||||
|
Mixed bool `json:"mixed,omitempty"`
|
||||||
|
HasHelp bool `json:"hasHelp,omitempty"`
|
||||||
|
|
||||||
|
Routes []*AppPluginRoute `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *DataSourcePlugin) Load(decoder *json.Decoder, pluginDir string) error {
|
func (p *DataSourcePlugin) Load(decoder *json.Decoder, pluginDir string) error {
|
||||||
@ -21,6 +30,15 @@ func (p *DataSourcePlugin) Load(decoder *json.Decoder, pluginDir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// look for help markdown
|
||||||
|
helpPath := filepath.Join(p.PluginDir, "HELP.md")
|
||||||
|
if _, err := os.Stat(helpPath); os.IsNotExist(err) {
|
||||||
|
helpPath = filepath.Join(p.PluginDir, "help.md")
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(helpPath); err == nil {
|
||||||
|
p.HasHelp = true
|
||||||
|
}
|
||||||
|
|
||||||
DataSources[p.Id] = p
|
DataSources[p.Id] = p
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,8 @@ type PluginBase struct {
|
|||||||
Includes []*PluginInclude `json:"includes"`
|
Includes []*PluginInclude `json:"includes"`
|
||||||
Module string `json:"module"`
|
Module string `json:"module"`
|
||||||
BaseUrl string `json:"baseUrl"`
|
BaseUrl string `json:"baseUrl"`
|
||||||
HideFromList bool `json:"hideFromList"`
|
HideFromList bool `json:"hideFromList,omitempty"`
|
||||||
State string `json:"state"`
|
State string `json:"state,omitempty"`
|
||||||
|
|
||||||
IncludedInAppId string `json:"-"`
|
IncludedInAppId string `json:"-"`
|
||||||
PluginDir string `json:"-"`
|
PluginDir string `json:"-"`
|
||||||
@ -48,9 +48,6 @@ type PluginBase struct {
|
|||||||
|
|
||||||
GrafanaNetVersion string `json:"-"`
|
GrafanaNetVersion string `json:"-"`
|
||||||
GrafanaNetHasUpdate bool `json:"-"`
|
GrafanaNetHasUpdate bool `json:"-"`
|
||||||
|
|
||||||
// cache for readme file contents
|
|
||||||
Readme []byte `json:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pb *PluginBase) registerPlugin(pluginDir string) error {
|
func (pb *PluginBase) registerPlugin(pluginDir string) error {
|
||||||
|
@ -3,6 +3,7 @@ package plugins
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -166,30 +167,24 @@ func (scanner *PluginScanner) loadPluginJson(pluginJsonFilePath string) error {
|
|||||||
return loader.Load(jsonParser, currentDir)
|
return loader.Load(jsonParser, currentDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPluginReadme(pluginId string) ([]byte, error) {
|
func GetPluginMarkdown(pluginId string, name string) ([]byte, error) {
|
||||||
plug, exists := Plugins[pluginId]
|
plug, exists := Plugins[pluginId]
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, PluginNotFoundError{pluginId}
|
return nil, PluginNotFoundError{pluginId}
|
||||||
}
|
}
|
||||||
|
|
||||||
if plug.Readme != nil {
|
path := filepath.Join(plug.PluginDir, fmt.Sprintf("%s.md", strings.ToUpper(name)))
|
||||||
return plug.Readme, nil
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
path = filepath.Join(plug.PluginDir, fmt.Sprintf("%s.md", strings.ToLower(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
readmePath := filepath.Join(plug.PluginDir, "README.md")
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
if _, err := os.Stat(readmePath); os.IsNotExist(err) {
|
return make([]byte, 0), nil
|
||||||
readmePath = filepath.Join(plug.PluginDir, "readme.md")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(readmePath); os.IsNotExist(err) {
|
if data, err := ioutil.ReadFile(path); err != nil {
|
||||||
plug.Readme = make([]byte, 0)
|
|
||||||
return plug.Readme, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if readmeBytes, err := ioutil.ReadFile(readmePath); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
plug.Readme = readmeBytes
|
return data, nil
|
||||||
return plug.Readme, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import {DashboardModel} from '../dashboard/model';
|
import {DashboardModel} from '../dashboard/model';
|
||||||
|
import Remarkable from 'remarkable';
|
||||||
|
|
||||||
export class MetricsTabCtrl {
|
export class MetricsTabCtrl {
|
||||||
dsName: string;
|
dsName: string;
|
||||||
@ -14,9 +15,16 @@ export class MetricsTabCtrl {
|
|||||||
panelDsValue: any;
|
panelDsValue: any;
|
||||||
addQueryDropdown: any;
|
addQueryDropdown: any;
|
||||||
queryTroubleshooterOpen: boolean;
|
queryTroubleshooterOpen: boolean;
|
||||||
|
helpOpen: boolean;
|
||||||
|
hasHelp: boolean;
|
||||||
|
helpHtml: string;
|
||||||
|
hasMinInterval: boolean;
|
||||||
|
hasCacheTimeout: boolean;
|
||||||
|
hasMaxDataPoints: boolean;
|
||||||
|
animateStart: boolean;
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor($scope, private uiSegmentSrv, private datasourceSrv) {
|
constructor($scope, private $sce, private datasourceSrv, private backendSrv, private $timeout) {
|
||||||
this.panelCtrl = $scope.ctrl;
|
this.panelCtrl = $scope.ctrl;
|
||||||
$scope.ctrl = this;
|
$scope.ctrl = this;
|
||||||
|
|
||||||
@ -34,6 +42,14 @@ export class MetricsTabCtrl {
|
|||||||
this.addQueryDropdown = {text: 'Add Query', value: null, fake: true};
|
this.addQueryDropdown = {text: 'Add Query', value: null, fake: true};
|
||||||
// update next ref id
|
// update next ref id
|
||||||
this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
|
this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
|
||||||
|
this.updateDatasourceOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDatasourceOptions() {
|
||||||
|
this.hasHelp = this.current.meta.hasHelp;
|
||||||
|
this.hasMinInterval = this.current.meta.minInterval === true;
|
||||||
|
this.hasCacheTimeout = this.current.meta.cacheTimeout === true;
|
||||||
|
this.hasMaxDataPoints = this.current.meta.maxDataPoints === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getOptions(includeBuiltin) {
|
getOptions(includeBuiltin) {
|
||||||
@ -51,6 +67,7 @@ export class MetricsTabCtrl {
|
|||||||
|
|
||||||
this.current = option.datasource;
|
this.current = option.datasource;
|
||||||
this.panelCtrl.setDatasource(option.datasource);
|
this.panelCtrl.setDatasource(option.datasource);
|
||||||
|
this.updateDatasourceOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
addMixedQuery(option) {
|
addMixedQuery(option) {
|
||||||
@ -67,6 +84,19 @@ export class MetricsTabCtrl {
|
|||||||
this.panelCtrl.addQuery({isNew: true});
|
this.panelCtrl.addQuery({isNew: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleHelp() {
|
||||||
|
this.animateStart = false;
|
||||||
|
this.helpOpen = !this.helpOpen;
|
||||||
|
this.backendSrv.get(`/api/plugins/${this.current.meta.id}/markdown/help`).then(res => {
|
||||||
|
var md = new Remarkable();
|
||||||
|
this.helpHtml = this.$sce.trustAsHtml(md.render(res));
|
||||||
|
|
||||||
|
this.$timeout(() => {
|
||||||
|
this.animateStart = true;
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
toggleQueryTroubleshooter() {
|
toggleQueryTroubleshooter() {
|
||||||
this.queryTroubleshooterOpen = !this.queryTroubleshooterOpen;
|
this.queryTroubleshooterOpen = !this.queryTroubleshooterOpen;
|
||||||
}
|
}
|
||||||
|
@ -11,41 +11,90 @@
|
|||||||
on-change="ctrl.datasourceChanged($option)">
|
on-change="ctrl.datasourceChanged($option)">
|
||||||
</gf-form-dropdown>
|
</gf-form-dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form" ng-if="ctrl.hasMinInterval">
|
||||||
<label class="gf-form-label">Min auto interval</label>
|
<label class="gf-form-label">
|
||||||
<input type="text" class="gf-form-input width-7" placeholder="1s" />
|
Min auto interval
|
||||||
|
</label>
|
||||||
|
<input type="text"
|
||||||
|
class="gf-form-input width-6"
|
||||||
|
placeholder="1s"
|
||||||
|
ng-model="ctrl.panel.interval"
|
||||||
|
spellcheck="false"
|
||||||
|
ng-model-onblur ng-change="ctrl.panelCtrl.refresh()"
|
||||||
|
/>
|
||||||
<info-popover mode="right-absolute">
|
<info-popover mode="right-absolute">
|
||||||
A lower limit for the auto group by time interval. Recommended to be set to write frequency,
|
A lower limit for the auto group by time interval. Recommended to be set to write frequency,
|
||||||
for example <code>1m</code> if your data is written every minute. Access auto interval via variable <code>$__interval</code> for time range
|
for example <code>1m</code> if your data is written every minute. Access auto interval via variable <code>$__interval</code> for time range
|
||||||
string and <code>$__interval_ms</code> for numeric variable that can be used in math expressions.
|
string and <code>$__interval_ms</code> for numeric variable that can be used in math expressions.
|
||||||
</info-popover>
|
</info-popover>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="gf-form" ng-if="ctrl.hasCacheTimeout">
|
||||||
|
<label class="gf-form-label">
|
||||||
|
Cache timeout
|
||||||
|
</label>
|
||||||
|
<input type="text"
|
||||||
|
class="gf-form-input width-6"
|
||||||
|
placeholder="60"
|
||||||
|
ng-model="ctrl.panel.cacheTimeout"
|
||||||
|
ng-model-onblur ng-change="ctrl.panelCtrl.refresh()"
|
||||||
|
spellcheck="false"
|
||||||
|
/>
|
||||||
|
<info-popover mode="right-absolute">
|
||||||
|
If your time series store has a query cache this option can override the default
|
||||||
|
cache timeout. Specify a numeric value in seconds.
|
||||||
|
</info-popover>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form" ng-if="ctrl.hasMaxDataPoints">
|
||||||
|
<label class="gf-form-label">
|
||||||
|
Max data points
|
||||||
|
</label>
|
||||||
|
<input type="text"
|
||||||
|
class="gf-form-input width-6"
|
||||||
|
placeholder="auto"
|
||||||
|
ng-model-onblur ng-change="ctrl.panelCtrl.refresh()"
|
||||||
|
ng-model="ctrl.panel.maxDataPoints"
|
||||||
|
spellcheck="false" />
|
||||||
|
<info-popover mode="right-absolute">
|
||||||
|
The maximum data points the query should return. For graphs this
|
||||||
|
is automatically set to one data point per pixel.
|
||||||
|
</info-popover>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="gf-form gf-form--grow">
|
<div class="gf-form gf-form--grow">
|
||||||
<label class="gf-form-label gf-form-label--grow"></label>
|
<label class="gf-form-label gf-form-label--grow"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form" ng-if="ctrl.hasHelp">
|
||||||
<label class="gf-form-label">
|
<button class="btn btn-secondary gf-form-btn" ng-click="ctrl.toggleHelp()">
|
||||||
<i class="fa fa-question-circle"></i>
|
<i class="fa fa-chevron-right" ng-hide="ctrl.helpOpen"></i>
|
||||||
<a href="http://google.com">Help & Docs</a>
|
<i class="fa fa-chevron-down" ng-show="ctrl.helpOpen"></i>
|
||||||
</label>
|
Help
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<button class="btn btn-secondary gf-form-btn" ng-click="ctrl.toggleQueryTroubleshooter()">
|
<button class="btn btn-secondary gf-form-btn" ng-click="ctrl.toggleQueryTroubleshooter()" bs-tooltip="'Display data query request & response'">
|
||||||
<i class="fa fa-chevron-right" ng-hide="ctrl.queryTroubleshooterOpen"></i>
|
<i class="fa fa-chevron-right" ng-hide="ctrl.queryTroubleshooterOpen"></i>
|
||||||
<i class="fa fa-chevron-down" ng-show="ctrl.queryTroubleshooterOpen"></i>
|
<i class="fa fa-chevron-down" ng-show="ctrl.queryTroubleshooterOpen"></i>
|
||||||
Query Inspector
|
Query Inspector
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="grafana-info-box grafana-info-box--animate" ng-if="ctrl.helpOpen" ng-class="{'grafana-info-box--animate-open': ctrl.animateStart}">
|
||||||
|
<div class="markdown-html" ng-bind-html="ctrl.helpHtml"></div>
|
||||||
|
<a class="grafana-info-box__close" ng-click="ctrl.toggleHelp()">
|
||||||
|
<i class="fa fa-chevron-up"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<query-troubleshooter panel-ctrl="ctrl.panelCtrl" is-open="ctrl.queryTroubleshooterOpen"></query-troubleshooter>
|
<query-troubleshooter panel-ctrl="ctrl.panelCtrl" is-open="ctrl.queryTroubleshooterOpen"></query-troubleshooter>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="query-editor-rows gf-form-group">
|
<div class="query-editor-rows gf-form-group">
|
||||||
<div ng-repeat="target in ctrl.panel.targets" ng-class="{'gf-form-disabled': target.hide}">
|
<div ng-repeat="target in ctrl.panel.targets" ng-class="{'gf-form-disabled': target.hide}">
|
||||||
<rebuild-on-change property="ctrl.panel.datasource || target.datasource" show-null="true">
|
<rebuild-on-change property="ctrl.panel.datasource || target.datasource" show-null="true">
|
||||||
<plugin-component type="query-ctrl">
|
<plugin-component type="query-ctrl">
|
||||||
</plugin-component>
|
</plugin-component>
|
||||||
</rebuild-on-change>
|
</rebuild-on-change>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form-query">
|
<div class="gf-form-query">
|
||||||
@ -56,16 +105,16 @@
|
|||||||
</span>
|
</span>
|
||||||
<span class="gf-form-query-letter-cell-letter">{{ctrl.panelCtrl.nextRefId}}</span>
|
<span class="gf-form-query-letter-cell-letter">{{ctrl.panelCtrl.nextRefId}}</span>
|
||||||
</label>
|
</label>
|
||||||
<button class="btn btn-secondary gf-form-btn" ng-click="ctrl.addQuery()" ng-hide="ctrl.current.meta.mixed">
|
<button class="btn btn-secondary gf-form-btn" ng-click="ctrl.addQuery()" ng-hide="ctrl.current.meta.mixed">
|
||||||
Add Query
|
Add Query
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="dropdown" ng-if="ctrl.current.meta.mixed">
|
<div class="dropdown" ng-if="ctrl.current.meta.mixed">
|
||||||
<gf-form-dropdown model="ctrl.addQueryDropdown"
|
<gf-form-dropdown model="ctrl.addQueryDropdown"
|
||||||
get-options="ctrl.getOptions(false)"
|
get-options="ctrl.getOptions(false)"
|
||||||
on-change="ctrl.addMixedQuery($option)">
|
on-change="ctrl.addMixedQuery($option)">
|
||||||
</gf-form-dropdown>
|
</gf-form-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
|
import Remarkable from 'remarkable';
|
||||||
|
|
||||||
export class PluginEditCtrl {
|
export class PluginEditCtrl {
|
||||||
model: any;
|
model: any;
|
||||||
@ -67,11 +68,9 @@ export class PluginEditCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initReadme() {
|
initReadme() {
|
||||||
return this.backendSrv.get(`/api/plugins/${this.pluginId}/readme`).then(res => {
|
return this.backendSrv.get(`/api/plugins/${this.pluginId}/markdown/readme`).then(res => {
|
||||||
return System.import('remarkable').then(Remarkable => {
|
var md = new Remarkable();
|
||||||
var md = new Remarkable();
|
this.readmeHtml = this.$sce.trustAsHtml(md.render(res));
|
||||||
this.readmeHtml = this.$sce.trustAsHtml(md.render(res));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,19 @@ export function GraphiteDatasource(instanceSettings, $q, backendSrv, templateSrv
|
|||||||
this.withCredentials = instanceSettings.withCredentials;
|
this.withCredentials = instanceSettings.withCredentials;
|
||||||
this.render_method = instanceSettings.render_method || 'POST';
|
this.render_method = instanceSettings.render_method || 'POST';
|
||||||
|
|
||||||
|
this.getQueryOptionsInfo = function() {
|
||||||
|
return {
|
||||||
|
"maxDataPoints": true,
|
||||||
|
"cacheTimeout": true,
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
text: "Help",
|
||||||
|
url: "http://docs.grafana.org/features/datasources/graphite/#using-graphite-in-grafana"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
this.query = function(options) {
|
this.query = function(options) {
|
||||||
var graphOptions = {
|
var graphOptions = {
|
||||||
from: this.translateTime(options.rangeRaw.from, false),
|
from: this.translateTime(options.rangeRaw.from, false),
|
||||||
|
32
public/app/plugins/datasource/graphite/help.md
Normal file
32
public/app/plugins/datasource/graphite/help.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#### Get Shorter legend names
|
||||||
|
|
||||||
|
- alias() function to specify a custom series name<
|
||||||
|
- aliasByNode(2) to alias by a specific part of your metric path
|
||||||
|
- aliasByNode(2, -1) you can add multiple segment paths, and use negative index
|
||||||
|
- groupByNode(2, 'sum') is useful if you have 2 wildcards in your metric path and want to sumSeries and group by
|
||||||
|
|
||||||
|
#### Series as parameter
|
||||||
|
|
||||||
|
- Some graphite functions allow you to have many series arguments
|
||||||
|
- Use #[A-Z] to use a graphite query as parameter to a function
|
||||||
|
- Examples:
|
||||||
|
- asPercent(#A, #B)
|
||||||
|
- prod.srv-01.counters.count - asPercent(#A) : percentage of count in comparison with A query
|
||||||
|
- prod.srv-01.counters.count - sumSeries(#A) : sum count and series A
|
||||||
|
- divideSeries(#A, #B)
|
||||||
|
|
||||||
|
If a query is added only to be used as a parameter, hide it from the graph with the eye icon
|
||||||
|
|
||||||
|
#### Max data points
|
||||||
|
- Every graphite request is issued with a maxDataPoints parameter
|
||||||
|
- Graphite uses this parameter to consolidate the real number of values down to this number
|
||||||
|
- If there are more real values, then by default they will be consolidated using averages
|
||||||
|
- This could hide real peaks and max values in your series
|
||||||
|
- You can change how point consolidation is made using the consolidateBy graphite function
|
||||||
|
- Point consolidation will effect series legend values (min,max,total,current)
|
||||||
|
- if you override maxDataPoint and set a high value performance can be severely effected
|
||||||
|
|
||||||
|
#### Documentation links:
|
||||||
|
|
||||||
|
- [Grafana's Graphite Documentation](http://docs.grafana.org/features/datasources/graphite)
|
||||||
|
- [Official Graphite Documentation](https://graphite.readthedocs.io)
|
@ -10,6 +10,8 @@
|
|||||||
"metrics": true,
|
"metrics": true,
|
||||||
"alerting": true,
|
"alerting": true,
|
||||||
"annotations": true,
|
"annotations": true,
|
||||||
|
"maxDataPoints": true,
|
||||||
|
"cacheTimeout": true,
|
||||||
|
|
||||||
"info": {
|
"info": {
|
||||||
"author": {
|
"author": {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"metrics": true,
|
"metrics": true,
|
||||||
"annotations": true,
|
"annotations": true,
|
||||||
"alerting": true,
|
"alerting": true,
|
||||||
|
"minInterval": true,
|
||||||
|
|
||||||
"info": {
|
"info": {
|
||||||
"author": {
|
"author": {
|
||||||
|
@ -276,7 +276,7 @@ $card-background-hover: linear-gradient(135deg, #343434, #262626);
|
|||||||
$card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .3);
|
$card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, .1), 1px 1px 0 0 rgba(0, 0, 0, .3);
|
||||||
|
|
||||||
// info box
|
// info box
|
||||||
$info-box-background: linear-gradient(120deg, #142749, #0e203e);
|
$info-box-background: linear-gradient(177deg, #006e95, #412078);
|
||||||
|
|
||||||
// footer
|
// footer
|
||||||
$footer-link-color: $gray-1;
|
$footer-link-color: $gray-1;
|
||||||
|
@ -277,7 +277,7 @@ $gf-form-margin: 0.25rem;
|
|||||||
&--right-absolute {
|
&--right-absolute {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: $spacer;
|
right: $spacer;
|
||||||
top: 8px;
|
top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--right-normal {
|
&--right-normal {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
.grafana-info-box::before {
|
// .grafana-info-box::before {
|
||||||
content: "\f05a";
|
// content: "\f05a";
|
||||||
font-family:'FontAwesome';
|
// font-family:'FontAwesome';
|
||||||
position: absolute;
|
// position: absolute;
|
||||||
top: -13px;
|
// top: -13px;
|
||||||
left: -8px;
|
// left: -8px;
|
||||||
font-size: 20px;
|
// font-size: 20px;
|
||||||
color: $text-color;
|
// color: $text-color;
|
||||||
}
|
// }
|
||||||
|
|
||||||
.grafana-info-box {
|
.grafana-info-box {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -15,6 +15,7 @@
|
|||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin-bottom: $spacer;
|
margin-bottom: $spacer;
|
||||||
|
margin-right: $gf-form-margin;
|
||||||
|
|
||||||
h5 {
|
h5 {
|
||||||
margin-bottom: $spacer;
|
margin-bottom: $spacer;
|
||||||
@ -26,5 +27,23 @@
|
|||||||
a {
|
a {
|
||||||
@extend .external-link;
|
@extend .external-link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--animate {
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--animate-open {
|
||||||
|
max-height: 1000px;
|
||||||
|
transition: max-height 250ms ease-in-out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grafana-info-box__close {
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
color: $link-color !important;
|
||||||
|
height: 0;
|
||||||
|
position: relative;
|
||||||
|
top: -9px;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user