From ca6dd7392312fb05c15a18d71aba4df09133ab1c Mon Sep 17 00:00:00 2001 From: Athurg Feng Date: Thu, 25 Oct 2018 18:17:05 +0800 Subject: [PATCH 01/59] 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 02/59] 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 03/59] 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 04/59] 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 05/59] 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 06/59] 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 07/59] 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 08/59] 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 e5ce7591677976768fa3877eac240a4a3f94d9be Mon Sep 17 00:00:00 2001 From: ryan Date: Sat, 23 Feb 2019 21:53:20 -0800 Subject: [PATCH 09/59] update --- public/app/plugins/panel/text2/TextPanel.tsx | 100 ++++++++++++++++++ .../plugins/panel/text2/TextPanelEditor.tsx | 32 ++++++ public/app/plugins/panel/text2/module.tsx | 18 ++-- public/app/plugins/panel/text2/types.ts | 14 +++ 4 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 public/app/plugins/panel/text2/TextPanel.tsx create mode 100644 public/app/plugins/panel/text2/TextPanelEditor.tsx create mode 100644 public/app/plugins/panel/text2/types.ts diff --git a/public/app/plugins/panel/text2/TextPanel.tsx b/public/app/plugins/panel/text2/TextPanel.tsx new file mode 100644 index 00000000000..9e9210df119 --- /dev/null +++ b/public/app/plugins/panel/text2/TextPanel.tsx @@ -0,0 +1,100 @@ +import React, { Component } from 'react'; + +import Remarkable from 'remarkable'; +import { sanitize } from 'app/core/utils/text'; +import config from 'app/core/config'; +import templateSrv from 'app/features/templating/template_srv'; +import { debounce } from 'lodash'; + +// Types +import { TextOptions } from './types'; +import { PanelProps } from '@grafana/ui/src/types'; + +interface Props extends PanelProps {} +interface State { + html: string; +} + +export class TextPanel extends Component { + remarkable: Remarkable; + + constructor(props) { + super(props); + + // TODO thre must be some better way to start with defualt options! + let opts = props.options; + if (opts && opts['options']) { + opts = opts['options']; + console.log('WEIRD!', opts); + } + + this.state = { + html: this.processContent(opts), + }; + } + + updateHTML = debounce(() => { + const html = this.processContent(this.props.options); + if (html !== this.state.html) { + this.setState({ html }); + } + }, 100); + + componentDidUpdate(prevProps: Props) { + // Since any change could be referenced in a template variable, + // This needs to process everything + this.updateHTML(); + } + + prepareHTML(html: string): string { + const scopedVars = {}; // TODO?? = this.props.; + html = config.disableSanitizeHtml ? html : sanitize(html); + try { + return templateSrv.replace(html, scopedVars); + } catch (e) { + // TODO -- put the error in the header window + console.log('Text panel error: ', e); + return html; + } + } + + prepareText(content: string): string { + return this.prepareHTML( + content + .replace(/&/g, '&') + .replace(/>/g, '>') + .replace(/') + ); + } + + prepareMarkdown(content: string): string { + if (!this.remarkable) { + this.remarkable = new Remarkable(); + } + return this.prepareHTML(this.remarkable.render(content)); + } + + processContent(options: TextOptions): string { + const { mode, content } = options; + + if (!content) { + return ''; + } + + if (mode === 'markdown') { + return this.prepareMarkdown(content); + } + if (mode === 'html') { + return this.prepareHTML(content); + } + + return this.prepareText(content); + } + + render() { + const { html } = this.state; + + return
; + } +} diff --git a/public/app/plugins/panel/text2/TextPanelEditor.tsx b/public/app/plugins/panel/text2/TextPanelEditor.tsx new file mode 100644 index 00000000000..2581384af9a --- /dev/null +++ b/public/app/plugins/panel/text2/TextPanelEditor.tsx @@ -0,0 +1,32 @@ +import React, { PureComponent } from 'react'; +import { PanelEditorProps, PanelOptionsGroup, Select, SelectOptionItem } from '@grafana/ui'; + +import { TextOptions } from './types'; + +export class TextPanelEditor extends PureComponent> { + modes: SelectOptionItem[] = [ + { value: 'markdown', label: 'Markdown' }, + { value: 'text', label: 'Text' }, + { value: 'html', label: 'HTML' }, + ]; + + onModeChange = (item: SelectOptionItem) => this.props.onChange({ ...this.props.options, mode: item.value }); + + onContentChange = evt => this.props.onChange({ ...this.props.options, content: (event.target as any).value }); + + render() { + const { mode, content } = this.props.options; + + return ( + +
+ Mode + + placeholder="{{passwordHint}}">
- - {/* TODO:
); From e3b3062107841517a832a420325f7ed5dd6a3004 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 8 Mar 2019 13:31:46 +0100 Subject: [PATCH 24/59] add nil/length check when delete old login attempts --- pkg/services/sqlstore/login_attempt.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/services/sqlstore/login_attempt.go b/pkg/services/sqlstore/login_attempt.go index ceff2394dce..fe77dd7e914 100644 --- a/pkg/services/sqlstore/login_attempt.go +++ b/pkg/services/sqlstore/login_attempt.go @@ -44,6 +44,10 @@ func DeleteOldLoginAttempts(cmd *m.DeleteOldLoginAttemptsCommand) error { return err } + if result == nil || len(result) == 0 || result[0] == nil { + return nil + } + maxId = toInt64(result[0]["id"]) if maxId == 0 { From d7d968412ba087dabd3b86c0d9886266379e1b19 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 8 Mar 2019 13:46:05 +0100 Subject: [PATCH 25/59] fix typo in pr template --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5ecbc8397df..22642808fa4 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -20,7 +20,7 @@ Fixes # **Release note**: ```release-note From 878da68c90688094eac50fbabab7db7ad5afbe91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 8 Mar 2019 13:49:48 +0100 Subject: [PATCH 26/59] Refactoring of PR #14772 --- public/app/core/specs/kbn.test.ts | 4 ++-- public/app/plugins/panel/graph/module.ts | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/public/app/core/specs/kbn.test.ts b/public/app/core/specs/kbn.test.ts index 25f82a5f850..c97e2e1101a 100644 --- a/public/app/core/specs/kbn.test.ts +++ b/public/app/core/specs/kbn.test.ts @@ -2,12 +2,12 @@ import kbn from '../utils/kbn'; describe('stringToJsRegex', () => { it('should parse the valid regex value', () => { - const output = kbn.stringToJsRegex("/validRegexp/"); + const output = kbn.stringToJsRegex('/validRegexp/'); expect(output).toBeInstanceOf(RegExp); }); it('should throw error on invalid regex value', () => { - const input = "/etc/hostname"; + const input = '/etc/hostname'; expect(() => { kbn.stringToJsRegex(input); }).toThrow(); diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index e3e3c4eb588..3919c4f69a9 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -235,11 +235,7 @@ class GraphCtrl extends MetricsPanelCtrl { } for (const series of this.seriesList) { - try { - series.applySeriesOverrides(this.panel.seriesOverrides); - } catch (e) { - this.publishAppEvent('alert-error', [e.message]); - } + series.applySeriesOverrides(this.panel.seriesOverrides); if (series.unit) { this.panel.yaxes[series.yaxis - 1].format = series.unit; From 74421ceb139e16c6b120d128816e33cda7665cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 8 Mar 2019 13:56:21 +0100 Subject: [PATCH 27/59] Updated prettierignore --- .prettierignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.prettierignore b/.prettierignore index b7a33870ddd..336d03e2551 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,4 +5,5 @@ pkg/ node_modules public/vendor/ vendor/ +data/ From 60272d8a77a92c408ce8a6dfc12dd882c019e4ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 14 Feb 2019 18:15:51 +0100 Subject: [PATCH 28/59] Simple implementation for preserve tags, closes #11627 --- .../SaveModals/SaveDashboardAsModalCtrl.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/public/app/features/dashboard/components/SaveModals/SaveDashboardAsModalCtrl.ts b/public/app/features/dashboard/components/SaveModals/SaveDashboardAsModalCtrl.ts index 60fa031f71c..59cfa22e468 100644 --- a/public/app/features/dashboard/components/SaveModals/SaveDashboardAsModalCtrl.ts +++ b/public/app/features/dashboard/components/SaveModals/SaveDashboardAsModalCtrl.ts @@ -16,19 +16,19 @@ const template = `