Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
14eba30f
Commit
14eba30f
authored
Jul 23, 2016
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(alerting): more work on notifications
parent
a6c60947
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
195 additions
and
271 deletions
+195
-271
pkg/services/alerting/notifier.go
+195
-193
pkg/services/alerting/transformers/aggregation.go
+0
-71
pkg/services/alerting/transformers/transformer.go
+0
-7
No files found.
pkg/services/alerting/notifier.go
View file @
14eba30f
package
alerting
// type NotifierImpl struct {
// log log.Logger
// getNotifications func(orgId int64, notificationGroups []int64) []*Notification
// }
//
// func NewNotifier() *NotifierImpl {
// log := log.New("alerting.notifier")
// return &NotifierImpl{
// log: log,
// getNotifications: buildGetNotifiers(log),
// }
// }
// func (n NotifierImpl) ShouldDispath(alertResult *AlertResultContext, notifier *Notification) bool {
// warn := alertResult.State == alertstates.Warn && notifier.SendWarning
// crit := alertResult.State == alertstates.Critical && notifier.SendCritical
// return (warn || crit) || alertResult.State == alertstates.Ok
// }
//
// func (n *NotifierImpl) Notify(alertResult *AlertResultContext) {
// notifiers := n.getNotifications(alertResult.Rule.OrgId, alertResult.Rule.Notifications)
//
// for _, notifier := range notifiers {
// if n.ShouldDispath(alertResult, notifier) {
// n.log.Info("Sending notification", "state", alertResult.State, "type", notifier.Type)
// go notifier.Notifierr.Dispatch(alertResult)
// }
// }
// }
//
// type Notification struct {
// Name string
// Type string
// SendWarning bool
// SendCritical bool
//
// Notifierr NotificationDispatcher
// }
//
// type EmailNotifier struct {
// To string
// log log.Logger
// }
//
// func (this *EmailNotifier) Dispatch(alertResult *AlertResult) {
// this.log.Info("Sending email")
// grafanaUrl := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort)
// if setting.AppSubUrl != "" {
// grafanaUrl += "/" + setting.AppSubUrl
// }
//
// query := &m.GetDashboardsQuery{
// DashboardIds: []int64{alertResult.AlertJob.Rule.DashboardId},
// }
//
// if err := bus.Dispatch(query); err != nil {
// this.log.Error("Failed to load dashboard", "error", err)
// return
// }
//
// if len(query.Result) != 1 {
// this.log.Error("Can only support one dashboard", "result", len(query.Result))
// return
// }
//
// dashboard := query.Result[0]
//
// panelId := strconv.Itoa(int(alertResult.AlertJob.Rule.PanelId))
//
// //TODO: get from alertrule and transforms to seconds
// from := "1466169458375"
// to := "1466171258375"
//
// renderUrl := fmt.Sprintf("%s/render/dashboard-solo/db/%s?from=%s&to=%s&panelId=%s&width=1000&height=500", grafanaUrl, dashboard.Slug, from, to, panelId)
// cmd := &m.SendEmailCommand{
// Data: map[string]interface{}{
// "Name": "Name",
// "State": alertResult.State,
// "Description": alertResult.Description,
// "TriggeredAlerts": alertResult.TriggeredAlerts,
// "DashboardLink": grafanaUrl + "/dashboard/db/" + dashboard.Slug,
// "AlertPageUrl": grafanaUrl + "/alerting",
// "DashboardImage": renderUrl,
// },
// To: []string{this.To},
// Template: "alert_notification.html",
// }
//
// err := bus.Dispatch(cmd)
// if err != nil {
// this.log.Error("Could not send alert notification as email", "error", err)
// }
// }
//
// type WebhookNotifier struct {
// Url string
// User string
// Password string
// log log.Logger
// }
//
// func (this *WebhookNotifier) Dispatch(alertResult *AlertResultContext) {
// this.log.Info("Sending webhook")
//
// bodyJSON := simplejson.New()
// bodyJSON.Set("name", alertResult.AlertJob.Rule.Name)
// bodyJSON.Set("state", alertResult.State)
// bodyJSON.Set("trigged", alertResult.TriggeredAlerts)
//
// body, _ := bodyJSON.MarshalJSON()
//
// cmd := &m.SendWebhook{
// Url: this.Url,
// User: this.User,
// Password: this.Password,
// Body: string(body),
// }
//
// bus.Dispatch(cmd)
// }
//
// type NotificationDispatcher interface {
// Dispatch(alertResult *AlertResult)
// }
//
// func buildGetNotifiers(log log.Logger) func(orgId int64, notificationGroups []int64) []*Notification {
// return func(orgId int64, notificationGroups []int64) []*Notification {
// query := &m.GetAlertNotificationQuery{
// OrgID: orgId,
// Ids: notificationGroups,
// IncludeAlwaysExecute: true,
// }
// err := bus.Dispatch(query)
// if err != nil {
// log.Error("Failed to read notifications", "error", err)
// }
//
// var result []*Notification
// for _, notification := range query.Result {
// not, err := NewNotificationFromDBModel(notification)
// if err == nil {
// result = append(result, not)
// } else {
// log.Error("Failed to read notification model", "error", err)
// }
// }
//
// return result
// }
// }
//
// func NewNotificationFromDBModel(model *m.AlertNotification) (*Notification, error) {
// notifier, err := createNotifier(model.Type, model.Settings)
//
// if err != nil {
// return nil, err
// }
//
// return &Notification{
// Name: model.Name,
// Type: model.Type,
// Notifierr: notifier,
// SendCritical: model.Settings.Get("sendCrit").MustBool(),
// SendWarning: model.Settings.Get("sendWarn").MustBool(),
// }, nil
// }
//
// var createNotifier = func(notificationType string, settings *simplejson.Json) (NotificationDispatcher, error) {
// if notificationType == "email" {
// to := settings.Get("to").MustString()
//
// if to == "" {
// return nil, fmt.Errorf("Could not find to propertie in settings")
// }
//
// return &EmailNotifier{
// To: to,
// log: log.New("alerting.notification.email"),
// }, nil
// }
//
// url := settings.Get("url").MustString()
// if url == "" {
// return nil, fmt.Errorf("Could not find url propertie in settings")
// }
//
// return &WebhookNotifier{
// Url: url,
// User: settings.Get("user").MustString(),
// Password: settings.Get("password").MustString(),
// log: log.New("alerting.notification.webhook"),
// }, nil
// }
import
(
"fmt"
"log"
"strconv"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/setting"
)
type
NotifierImpl
struct
{
log
log
.
Logger
getNotifications
func
(
orgId
int64
,
notificationGroups
[]
int64
)
[]
*
Notification
}
func
NewNotifier
()
*
NotifierImpl
{
log
:=
log
.
New
(
"alerting.notifier"
)
return
&
NotifierImpl
{
log
:
log
,
getNotifications
:
buildGetNotifiers
(
log
),
}
}
func
(
n
*
NotifierImpl
)
Notify
(
alertResult
*
AlertResultContext
)
{
notifiers
:=
n
.
getNotifications
(
alertResult
.
Rule
.
OrgId
,
alertResult
.
Rule
.
Notifications
)
for
_
,
notifier
:=
range
notifiers
{
n
.
log
.
Info
(
"Sending notification"
,
"state"
,
alertResult
.
State
,
"type"
,
notifier
.
Type
)
go
notifier
.
Notifierr
.
Dispatch
(
alertResult
)
}
}
type
Notification
struct
{
Name
string
Type
string
SendWarning
bool
SendCritical
bool
Notifierr
NotificationDispatcher
}
type
EmailNotifier
struct
{
To
string
log
log
.
Logger
}
func
(
this
*
EmailNotifier
)
Dispatch
(
alertResult
*
AlertResult
)
{
this
.
log
.
Info
(
"Sending email"
)
grafanaUrl
:=
fmt
.
Sprintf
(
"%s:%s"
,
setting
.
HttpAddr
,
setting
.
HttpPort
)
if
setting
.
AppSubUrl
!=
""
{
grafanaUrl
+=
"/"
+
setting
.
AppSubUrl
}
query
:=
&
m
.
GetDashboardsQuery
{
DashboardIds
:
[]
int64
{
alertResult
.
AlertJob
.
Rule
.
DashboardId
},
}
if
err
:=
bus
.
Dispatch
(
query
);
err
!=
nil
{
this
.
log
.
Error
(
"Failed to load dashboard"
,
"error"
,
err
)
return
}
if
len
(
query
.
Result
)
!=
1
{
this
.
log
.
Error
(
"Can only support one dashboard"
,
"result"
,
len
(
query
.
Result
))
return
}
dashboard
:=
query
.
Result
[
0
]
panelId
:=
strconv
.
Itoa
(
int
(
alertResult
.
AlertJob
.
Rule
.
PanelId
))
//TODO: get from alertrule and transforms to seconds
from
:=
"1466169458375"
to
:=
"1466171258375"
renderUrl
:=
fmt
.
Sprintf
(
"%s/render/dashboard-solo/db/%s?from=%s&to=%s&panelId=%s&width=1000&height=500"
,
grafanaUrl
,
dashboard
.
Slug
,
from
,
to
,
panelId
)
cmd
:=
&
m
.
SendEmailCommand
{
Data
:
map
[
string
]
interface
{}{
"Name"
:
"Name"
,
"State"
:
alertResult
.
State
,
"Description"
:
alertResult
.
Description
,
"TriggeredAlerts"
:
alertResult
.
TriggeredAlerts
,
"DashboardLink"
:
grafanaUrl
+
"/dashboard/db/"
+
dashboard
.
Slug
,
"AlertPageUrl"
:
grafanaUrl
+
"/alerting"
,
"DashboardImage"
:
renderUrl
,
},
To
:
[]
string
{
this
.
To
},
Template
:
"alert_notification.html"
,
}
err
:=
bus
.
Dispatch
(
cmd
)
if
err
!=
nil
{
this
.
log
.
Error
(
"Could not send alert notification as email"
,
"error"
,
err
)
}
}
type
WebhookNotifier
struct
{
Url
string
User
string
Password
string
log
log
.
Logger
}
func
(
this
*
WebhookNotifier
)
Dispatch
(
alertResult
*
AlertResultContext
)
{
this
.
log
.
Info
(
"Sending webhook"
)
bodyJSON
:=
simplejson
.
New
()
bodyJSON
.
Set
(
"name"
,
alertResult
.
AlertJob
.
Rule
.
Name
)
bodyJSON
.
Set
(
"state"
,
alertResult
.
State
)
bodyJSON
.
Set
(
"trigged"
,
alertResult
.
TriggeredAlerts
)
body
,
_
:=
bodyJSON
.
MarshalJSON
()
cmd
:=
&
m
.
SendWebhook
{
Url
:
this
.
Url
,
User
:
this
.
User
,
Password
:
this
.
Password
,
Body
:
string
(
body
),
}
bus
.
Dispatch
(
cmd
)
}
type
NotificationDispatcher
interface
{
Dispatch
(
alertResult
*
AlertResult
)
}
func
buildGetNotifiers
(
log
log
.
Logger
)
func
(
orgId
int64
,
notificationGroups
[]
int64
)
[]
*
Notification
{
return
func
(
orgId
int64
,
notificationGroups
[]
int64
)
[]
*
Notification
{
query
:=
&
m
.
GetAlertNotificationQuery
{
OrgID
:
orgId
,
Ids
:
notificationGroups
,
IncludeAlwaysExecute
:
true
,
}
err
:=
bus
.
Dispatch
(
query
)
if
err
!=
nil
{
log
.
Error
(
"Failed to read notifications"
,
"error"
,
err
)
}
var
result
[]
*
Notification
for
_
,
notification
:=
range
query
.
Result
{
not
,
err
:=
NewNotificationFromDBModel
(
notification
)
if
err
==
nil
{
result
=
append
(
result
,
not
)
}
else
{
log
.
Error
(
"Failed to read notification model"
,
"error"
,
err
)
}
}
return
result
}
}
func
NewNotificationFromDBModel
(
model
*
m
.
AlertNotification
)
(
*
Notification
,
error
)
{
notifier
,
err
:=
createNotifier
(
model
.
Type
,
model
.
Settings
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
Notification
{
Name
:
model
.
Name
,
Type
:
model
.
Type
,
Notifierr
:
notifier
,
SendCritical
:
model
.
Settings
.
Get
(
"sendCrit"
)
.
MustBool
(),
SendWarning
:
model
.
Settings
.
Get
(
"sendWarn"
)
.
MustBool
(),
},
nil
}
var
createNotifier
=
func
(
notificationType
string
,
settings
*
simplejson
.
Json
)
(
NotificationDispatcher
,
error
)
{
if
notificationType
==
"email"
{
to
:=
settings
.
Get
(
"to"
)
.
MustString
()
if
to
==
""
{
return
nil
,
fmt
.
Errorf
(
"Could not find to propertie in settings"
)
}
return
&
EmailNotifier
{
To
:
to
,
log
:
log
.
New
(
"alerting.notification.email"
),
},
nil
}
url
:=
settings
.
Get
(
"url"
)
.
MustString
()
if
url
==
""
{
return
nil
,
fmt
.
Errorf
(
"Could not find url propertie in settings"
)
}
return
&
WebhookNotifier
{
Url
:
url
,
User
:
settings
.
Get
(
"user"
)
.
MustString
(),
Password
:
settings
.
Get
(
"password"
)
.
MustString
(),
log
:
log
.
New
(
"alerting.notification.webhook"
),
},
nil
}
pkg/services/alerting/transformers/aggregation.go
deleted
100644 → 0
View file @
a6c60947
package
transformers
import
(
"fmt"
"math"
"github.com/grafana/grafana/pkg/tsdb"
)
func
NewAggregationTransformer
(
method
string
)
*
AggregationTransformer
{
return
&
AggregationTransformer
{
Method
:
method
,
}
}
type
AggregationTransformer
struct
{
Method
string
}
func
(
at
*
AggregationTransformer
)
Transform
(
timeserie
*
tsdb
.
TimeSeries
)
(
float64
,
error
)
{
if
at
.
Method
==
"avg"
{
sum
:=
float64
(
0
)
for
_
,
point
:=
range
timeserie
.
Points
{
sum
+=
point
[
0
]
}
return
sum
/
float64
(
len
(
timeserie
.
Points
)),
nil
}
if
at
.
Method
==
"sum"
{
sum
:=
float64
(
0
)
for
_
,
v
:=
range
timeserie
.
Points
{
sum
+=
v
[
0
]
}
return
sum
,
nil
}
if
at
.
Method
==
"min"
{
min
:=
timeserie
.
Points
[
0
][
0
]
for
_
,
v
:=
range
timeserie
.
Points
{
if
v
[
0
]
<
min
{
min
=
v
[
0
]
}
}
return
min
,
nil
}
if
at
.
Method
==
"max"
{
max
:=
timeserie
.
Points
[
0
][
0
]
for
_
,
v
:=
range
timeserie
.
Points
{
if
v
[
0
]
>
max
{
max
=
v
[
0
]
}
}
return
max
,
nil
}
if
at
.
Method
==
"mean"
{
midPosition
:=
int64
(
math
.
Floor
(
float64
(
len
(
timeserie
.
Points
))
/
float64
(
2
)))
return
timeserie
.
Points
[
midPosition
][
0
],
nil
}
return
float64
(
0
),
fmt
.
Errorf
(
"Missing method"
)
}
pkg/services/alerting/transformers/transformer.go
deleted
100644 → 0
View file @
a6c60947
package
transformers
import
"github.com/grafana/grafana/pkg/tsdb"
type
Transformer
interface
{
Transform
(
timeserie
*
tsdb
.
TimeSeries
)
(
float64
,
error
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment