From ca6dd7392312fb05c15a18d71aba4df09133ab1c Mon Sep 17 00:00:00 2001 From: Athurg Feng Date: Thu, 25 Oct 2018 18:17:05 +0800 Subject: [PATCH 001/244] Add match values into Dingding notification message --- pkg/services/alerting/notifiers/dingding.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/services/alerting/notifiers/dingding.go b/pkg/services/alerting/notifiers/dingding.go index 1ef085c82f1..9ad85d55004 100644 --- a/pkg/services/alerting/notifiers/dingding.go +++ b/pkg/services/alerting/notifiers/dingding.go @@ -1,6 +1,8 @@ package notifiers import ( + "fmt" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/log" @@ -61,6 +63,10 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { message = title } + for i, match := range evalContext.EvalMatches { + message += fmt.Sprintf("\\n%2d. %s value %s", i+1, match.Metric, match.Value) + } + bodyJSON, err := simplejson.NewJson([]byte(`{ "msgtype": "link", "link": { From 7f45afac63b93bacd73d6ada811b5db0178b1723 Mon Sep 17 00:00:00 2001 From: Athurg Feng Date: Thu, 25 Oct 2018 18:24:04 +0800 Subject: [PATCH 002/244] Split text template into variable --- pkg/services/alerting/notifiers/dingding.go | 23 ++++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/pkg/services/alerting/notifiers/dingding.go b/pkg/services/alerting/notifiers/dingding.go index 9ad85d55004..bf1b721f753 100644 --- a/pkg/services/alerting/notifiers/dingding.go +++ b/pkg/services/alerting/notifiers/dingding.go @@ -10,19 +10,21 @@ import ( "github.com/grafana/grafana/pkg/services/alerting" ) -func init() { - alerting.RegisterNotifier(&alerting.NotifierPlugin{ - Type: "dingding", - Name: "DingDing", - Description: "Sends HTTP POST request to DingDing", - Factory: NewDingDingNotifier, - OptionsTemplate: ` +const DingdingOptionsTemplate = `

DingDing settings

Url
- `, +` + +func init() { + alerting.RegisterNotifier(&alerting.NotifierPlugin{ + Type: "dingding", + Name: "DingDing", + Description: "Sends HTTP POST request to DingDing", + Factory: NewDingDingNotifier, + OptionsTemplate: DingdingOptionsTemplate, }) } @@ -67,7 +69,7 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { message += fmt.Sprintf("\\n%2d. %s value %s", i+1, match.Metric, match.Value) } - bodyJSON, err := simplejson.NewJson([]byte(`{ + bodyStr := `{ "msgtype": "link", "link": { "text": "` + message + `", @@ -75,7 +77,8 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { "picUrl": "` + picUrl + `", "messageUrl": "` + messageUrl + `" } - }`)) + }` + bodyJSON, err := simplejson.NewJson([]byte(bodyStr)) if err != nil { this.log.Error("Failed to create Json data", "error", err, "dingding", this.Name) From cb86e386289a02f1a8638b2e84030b36c697efa9 Mon Sep 17 00:00:00 2001 From: Athurg Feng Date: Thu, 25 Oct 2018 18:29:47 +0800 Subject: [PATCH 003/244] Add Dingding message type to support mass text notification --- pkg/services/alerting/notifiers/dingding.go | 45 ++++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/pkg/services/alerting/notifiers/dingding.go b/pkg/services/alerting/notifiers/dingding.go index bf1b721f753..ce932b7a799 100644 --- a/pkg/services/alerting/notifiers/dingding.go +++ b/pkg/services/alerting/notifiers/dingding.go @@ -10,12 +10,17 @@ import ( "github.com/grafana/grafana/pkg/services/alerting" ) +const DefaultDingdingMsgType = "link" const DingdingOptionsTemplate = `

DingDing settings

Url
+
+ MessageType + +
` func init() { @@ -35,8 +40,11 @@ func NewDingDingNotifier(model *m.AlertNotification) (alerting.Notifier, error) return nil, alerting.ValidationError{Reason: "Could not find url property in settings"} } + msgType := model.Settings.Get("msgType").MustString(DefaultDingdingMsgType) + return &DingDingNotifier{ NotifierBase: NewNotifierBase(model), + MsgType: msgType, Url: url, log: log.New("alerting.notifier.dingding"), }, nil @@ -44,8 +52,9 @@ func NewDingDingNotifier(model *m.AlertNotification) (alerting.Notifier, error) type DingDingNotifier struct { NotifierBase - Url string - log log.Logger + MsgType string + Url string + log log.Logger } func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { @@ -69,15 +78,29 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { message += fmt.Sprintf("\\n%2d. %s value %s", i+1, match.Metric, match.Value) } - bodyStr := `{ - "msgtype": "link", - "link": { - "text": "` + message + `", - "title": "` + title + `", - "picUrl": "` + picUrl + `", - "messageUrl": "` + messageUrl + `" - } - }` + var bodyStr string + if this.MsgType == "actionCard" { + bodyStr = `{ + "msgtype": "actionCard", + "actionCard": { + "text": "` + message + `", + "title": "` + title + `", + "singleTitle": "More", + "singleURL": "` + messageUrl + `" + } + }` + } else { + bodyStr = `{ + "msgtype": "link", + "link": { + "text": "` + message + `", + "title": "` + title + `", + "picUrl": "` + picUrl + `", + "messageUrl": "` + messageUrl + `" + } + }` + } + bodyJSON, err := simplejson.NewJson([]byte(bodyStr)) if err != nil { From 201dd6bf658501782180ce90111390d4970b16c8 Mon Sep 17 00:00:00 2001 From: Athurg Feng Date: Thu, 25 Oct 2018 18:53:45 +0800 Subject: [PATCH 004/244] Optimize the Dingding match values format --- pkg/services/alerting/notifiers/dingding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/alerting/notifiers/dingding.go b/pkg/services/alerting/notifiers/dingding.go index ce932b7a799..94961e82025 100644 --- a/pkg/services/alerting/notifiers/dingding.go +++ b/pkg/services/alerting/notifiers/dingding.go @@ -75,7 +75,7 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { } for i, match := range evalContext.EvalMatches { - message += fmt.Sprintf("\\n%2d. %s value %s", i+1, match.Metric, match.Value) + message += fmt.Sprintf("\\n%2d. %s: %s", i+1, match.Metric, match.Value) } var bodyStr string From b7787db34e2b71cdc59aef829ea1a3d69b0a1e3c Mon Sep 17 00:00:00 2001 From: Athurg Feng Date: Thu, 8 Nov 2018 18:44:00 +0800 Subject: [PATCH 005/244] Add new option to set where to open the message url --- pkg/services/alerting/notifiers/dingding.go | 37 ++++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/pkg/services/alerting/notifiers/dingding.go b/pkg/services/alerting/notifiers/dingding.go index 94961e82025..af1063a4c70 100644 --- a/pkg/services/alerting/notifiers/dingding.go +++ b/pkg/services/alerting/notifiers/dingding.go @@ -2,6 +2,7 @@ package notifiers import ( "fmt" + "net/url" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" @@ -15,12 +16,17 @@ const DingdingOptionsTemplate = `

DingDing settings

Url - +
MessageType
+
+ OpenInBrowser + + Open the message url in browser instead of inside of Dingding +
` func init() { @@ -41,20 +47,23 @@ func NewDingDingNotifier(model *m.AlertNotification) (alerting.Notifier, error) } msgType := model.Settings.Get("msgType").MustString(DefaultDingdingMsgType) + openInBrowser := model.Settings.Get("openInBrowser").MustBool(true) return &DingDingNotifier{ - NotifierBase: NewNotifierBase(model), - MsgType: msgType, - Url: url, - log: log.New("alerting.notifier.dingding"), + NotifierBase: NewNotifierBase(model), + OpenInBrowser: openInBrowser, + MsgType: msgType, + Url: url, + log: log.New("alerting.notifier.dingding"), }, nil } type DingDingNotifier struct { NotifierBase - MsgType string - Url string - log log.Logger + MsgType string + OpenInBrowser bool //Set whether the message url will open outside of Dingding + Url string + log log.Logger } func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { @@ -65,6 +74,18 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { this.log.Error("Failed to get messageUrl", "error", err, "dingding", this.Name) messageUrl = "" } + + if this.OpenInBrowser { + q := url.Values{ + "pc_slide": {"false"}, + "url": {messageUrl}, + } + + // Use special link to auto open the message url outside of Dingding + // Refer: https://open-doc.dingtalk.com/docs/doc.htm?treeId=385&articleId=104972&docType=1#s9 + messageUrl = "dingtalk://dingtalkclient/page/link?" + q.Encode() + } + this.log.Info("messageUrl:" + messageUrl) message := evalContext.Rule.Message From 919d00437e21944d5feea3c6ac175a2d85736784 Mon Sep 17 00:00:00 2001 From: Athurg Feng Date: Mon, 12 Nov 2018 11:18:53 +0800 Subject: [PATCH 006/244] Add pic into actionCard message --- pkg/services/alerting/notifiers/dingding.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/services/alerting/notifiers/dingding.go b/pkg/services/alerting/notifiers/dingding.go index af1063a4c70..3514554a1db 100644 --- a/pkg/services/alerting/notifiers/dingding.go +++ b/pkg/services/alerting/notifiers/dingding.go @@ -101,6 +101,11 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { var bodyStr string if this.MsgType == "actionCard" { + // Embed the pic into the markdown directly because actionCard doesn't have a picUrl field + if picUrl != "" { + message = "![](" + picUrl + ")\\n\\n" + message + } + bodyStr = `{ "msgtype": "actionCard", "actionCard": { From bba92c0746e3bbbb53833dd222cb4f38cca8a2d5 Mon Sep 17 00:00:00 2001 From: Athurg Feng Date: Sat, 2 Feb 2019 13:35:17 +0800 Subject: [PATCH 007/244] Remove option used to control within browser --- pkg/services/alerting/notifiers/dingding.go | 38 ++++++++------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/pkg/services/alerting/notifiers/dingding.go b/pkg/services/alerting/notifiers/dingding.go index 3514554a1db..a3934903bd6 100644 --- a/pkg/services/alerting/notifiers/dingding.go +++ b/pkg/services/alerting/notifiers/dingding.go @@ -22,11 +22,6 @@ const DingdingOptionsTemplate = ` MessageType -
- OpenInBrowser - - Open the message url in browser instead of inside of Dingding -
` func init() { @@ -47,23 +42,20 @@ func NewDingDingNotifier(model *m.AlertNotification) (alerting.Notifier, error) } msgType := model.Settings.Get("msgType").MustString(DefaultDingdingMsgType) - openInBrowser := model.Settings.Get("openInBrowser").MustBool(true) return &DingDingNotifier{ - NotifierBase: NewNotifierBase(model), - OpenInBrowser: openInBrowser, - MsgType: msgType, - Url: url, - log: log.New("alerting.notifier.dingding"), + NotifierBase: NewNotifierBase(model), + MsgType: msgType, + Url: url, + log: log.New("alerting.notifier.dingding"), }, nil } type DingDingNotifier struct { NotifierBase - MsgType string - OpenInBrowser bool //Set whether the message url will open outside of Dingding - Url string - log log.Logger + MsgType string + Url string + log log.Logger } func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { @@ -75,17 +67,15 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { messageUrl = "" } - if this.OpenInBrowser { - q := url.Values{ - "pc_slide": {"false"}, - "url": {messageUrl}, - } - - // Use special link to auto open the message url outside of Dingding - // Refer: https://open-doc.dingtalk.com/docs/doc.htm?treeId=385&articleId=104972&docType=1#s9 - messageUrl = "dingtalk://dingtalkclient/page/link?" + q.Encode() + q := url.Values{ + "pc_slide": {"false"}, + "url": {messageUrl}, } + // Use special link to auto open the message url outside of Dingding + // Refer: https://open-doc.dingtalk.com/docs/doc.htm?treeId=385&articleId=104972&docType=1#s9 + messageUrl = "dingtalk://dingtalkclient/page/link?" + q.Encode() + this.log.Info("messageUrl:" + messageUrl) message := evalContext.Rule.Message From 70b23ab73bfbf364c97da23fe9a829ae9099731c Mon Sep 17 00:00:00 2001 From: Athurg Feng Date: Sat, 2 Feb 2019 13:36:10 +0800 Subject: [PATCH 008/244] Add string quote func --- pkg/services/alerting/notifiers/dingding.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/services/alerting/notifiers/dingding.go b/pkg/services/alerting/notifiers/dingding.go index a3934903bd6..3e3496622b7 100644 --- a/pkg/services/alerting/notifiers/dingding.go +++ b/pkg/services/alerting/notifiers/dingding.go @@ -3,6 +3,7 @@ package notifiers import ( "fmt" "net/url" + "strings" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" @@ -99,8 +100,8 @@ func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error { bodyStr = `{ "msgtype": "actionCard", "actionCard": { - "text": "` + message + `", - "title": "` + title + `", + "text": "` + strings.Replace(message, `"`, "'", -1) + `", + "title": "` + strings.Replace(title, `"`, "'", -1) + `", "singleTitle": "More", "singleURL": "` + messageUrl + `" } From 9fc87e417447a280ea8dd02428124b213069fa4b Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Tue, 5 Feb 2019 15:12:04 +0100 Subject: [PATCH 009/244] first working draft --- .../grafana-ui/src/components/Gauge/Gauge.tsx | 20 ++++---- public/app/plugins/panel/gauge/GaugePanel.tsx | 49 +++++++++++++++---- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/packages/grafana-ui/src/components/Gauge/Gauge.tsx b/packages/grafana-ui/src/components/Gauge/Gauge.tsx index 04d89bf3f57..9842903b394 100644 --- a/packages/grafana-ui/src/components/Gauge/Gauge.tsx +++ b/packages/grafana-ui/src/components/Gauge/Gauge.tsx @@ -184,17 +184,15 @@ export class Gauge extends PureComponent { const { height, width } = this.props; return ( -
-
(this.canvasElement = element)} - /> -
+
(this.canvasElement = element)} + /> ); } } diff --git a/public/app/plugins/panel/gauge/GaugePanel.tsx b/public/app/plugins/panel/gauge/GaugePanel.tsx index b6f37dde94f..928f9a43909 100644 --- a/public/app/plugins/panel/gauge/GaugePanel.tsx +++ b/public/app/plugins/panel/gauge/GaugePanel.tsx @@ -16,6 +16,7 @@ interface Props extends PanelProps {} export class GaugePanel extends PureComponent { render() { + console.log('renduru'); const { panelData, width, height, onInterpolate, options } = this.props; const prefix = onInterpolate(options.prefix); @@ -28,7 +29,33 @@ export class GaugePanel extends PureComponent { nullValueMode: NullValueMode.Null, }); - if (vmSeries[0]) { + const gauges = []; + if (vmSeries.length > 1) { + for (let i = 0; i < vmSeries.length; i++) { + gauges.push( + + {theme => ( +
+ +
Gauge {i}
+
+ )} +
+ ); + } + return [gauges]; + } else if (vmSeries.length > 0) { value = vmSeries[0].stats[options.stat]; } else { value = null; @@ -40,15 +67,17 @@ export class GaugePanel extends PureComponent { return ( {theme => ( - +
+ +
)}
); From 9d3d1bc669043f5a1e7228c35d9408436491dbe2 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Tue, 5 Feb 2019 16:34:01 +0100 Subject: [PATCH 010/244] refactor panel --- public/app/core/utils/ConfigProvider.tsx | 2 +- public/app/plugins/panel/gauge/GaugePanel.tsx | 111 +++++++++--------- 2 files changed, 59 insertions(+), 54 deletions(-) diff --git a/public/app/core/utils/ConfigProvider.tsx b/public/app/core/utils/ConfigProvider.tsx index 6883401ad27..1a7c394434d 100644 --- a/public/app/core/utils/ConfigProvider.tsx +++ b/public/app/core/utils/ConfigProvider.tsx @@ -14,7 +14,7 @@ export const provideConfig = (component: React.ComponentType) => { }; interface ThemeProviderProps { - children: (theme: GrafanaTheme) => JSX.Element; + children: (theme: GrafanaTheme) => JSX.Element | JSX.Element[]; } export const ThemeProvider = ({ children }: ThemeProviderProps) => { diff --git a/public/app/plugins/panel/gauge/GaugePanel.tsx b/public/app/plugins/panel/gauge/GaugePanel.tsx index 928f9a43909..040a06eed5c 100644 --- a/public/app/plugins/panel/gauge/GaugePanel.tsx +++ b/public/app/plugins/panel/gauge/GaugePanel.tsx @@ -9,77 +9,82 @@ import { Gauge } from '@grafana/ui'; // Types import { GaugeOptions } from './types'; -import { PanelProps, NullValueMode, TimeSeriesValue } from '@grafana/ui/src/types'; +import { PanelProps, NullValueMode } from '@grafana/ui/src/types'; import { ThemeProvider } from 'app/core/utils/ConfigProvider'; interface Props extends PanelProps {} export class GaugePanel extends PureComponent { - render() { - console.log('renduru'); - const { panelData, width, height, onInterpolate, options } = this.props; + renderMultipleGauge(vmSeries, theme) { + const { options, width } = this.props; + const gauges = []; + + for (let i = 0; i < vmSeries.length; i++) { + const singleStatWidth = 1 / vmSeries.length * 100; + const gaugeWidth = Math.floor(width / vmSeries.length) - 10; // make Gauge slightly smaller than panel. + + gauges.push( +
+ {this.renderGauge(vmSeries[i].stats[options.stat], gaugeWidth, theme)} + +
Gauge {i}
+
+ ); + } + return gauges; + } + + renderGauge(value, width, theme) { + const { height, onInterpolate, options } = this.props; const prefix = onInterpolate(options.prefix); const suffix = onInterpolate(options.suffix); - let value: TimeSeriesValue; + return ( + + ); + } + + renderSingleGauge(timeSeries, theme) { + const { options, width } = this.props; + const timeSeriesValue = timeSeries[0].stats[options.stat]; + return
{this.renderGauge(timeSeriesValue, width, theme)}
; + } + + renderGaugeWithTableData(panelData, theme) { + const { width } = this.props; + + const firstTableDataValue = panelData.tableData.rows[0].find(prop => prop > 0); + return
{this.renderGauge(firstTableDataValue, width, theme)}
; + } + + renderPanel(theme) { + const { panelData } = this.props; if (panelData.timeSeries) { - const vmSeries = processTimeSeries({ + const timeSeries = processTimeSeries({ timeSeries: panelData.timeSeries, nullValueMode: NullValueMode.Null, }); - const gauges = []; - if (vmSeries.length > 1) { - for (let i = 0; i < vmSeries.length; i++) { - gauges.push( - - {theme => ( -
- -
Gauge {i}
-
- )} -
- ); - } - return [gauges]; - } else if (vmSeries.length > 0) { - value = vmSeries[0].stats[options.stat]; + if (timeSeries.length > 1) { + return this.renderMultipleGauge(timeSeries, theme); + } else if (timeSeries.length > 0) { + return this.renderSingleGauge(timeSeries, theme); } else { - value = null; + return null; } } else if (panelData.tableData) { - value = panelData.tableData.rows[0].find(prop => prop > 0); + return this.renderGaugeWithTableData(panelData, theme); + } else { + return
No time series data available
; } + } - return ( - - {theme => ( -
- -
- )} -
- ); + render() { + return {theme => this.renderPanel(theme)}; } } From 71cfcd58ba79e55bb483d37894a6e1e3c4a2f2e7 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Wed, 6 Feb 2019 15:38:51 +0100 Subject: [PATCH 011/244] combine mode with avg value --- .../src/components/Switch/Switch.tsx | 2 +- .../panel/gauge/GaugeOptionsEditor.tsx | 39 ++++++++++++++++--- public/app/plugins/panel/gauge/GaugePanel.tsx | 17 ++++++-- .../plugins/panel/gauge/GaugePanelOptions.tsx | 9 ++--- public/app/plugins/panel/gauge/types.ts | 1 + 5 files changed, 52 insertions(+), 16 deletions(-) diff --git a/packages/grafana-ui/src/components/Switch/Switch.tsx b/packages/grafana-ui/src/components/Switch/Switch.tsx index feee58386b8..8cdd7c481f2 100644 --- a/packages/grafana-ui/src/components/Switch/Switch.tsx +++ b/packages/grafana-ui/src/components/Switch/Switch.tsx @@ -34,7 +34,7 @@ export class Switch extends PureComponent { const switchClassName = `gf-form-switch ${switchClass} ${transparent ? 'gf-form-switch--transparent' : ''}`; return ( -