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
2b276d5c
Commit
2b276d5c
authored
Jul 30, 2016
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(alerting): working on alert notification and image rendering
parent
f9ddfb43
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
128 additions
and
50 deletions
+128
-50
pkg/components/imguploader/imguploader.go
+3
-10
pkg/components/renderer/renderer.go
+7
-3
pkg/services/alerting/eval_context.go
+50
-12
pkg/services/alerting/notifier.go
+42
-0
pkg/services/alerting/notifiers/common.go
+0
-19
pkg/services/alerting/notifiers/email.go
+2
-2
pkg/services/alerting/notifiers/slack.go
+4
-4
pkg/setting/setting.go
+9
-0
vendor/phantomjs/render.js
+11
-0
No files found.
pkg/components/imguploader/imguploader.go
View file @
2b276d5c
...
...
@@ -3,7 +3,6 @@ package imguploader
import
(
"io/ioutil"
"net/http"
"time"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/util"
...
...
@@ -11,7 +10,7 @@ import (
)
type
Uploader
interface
{
Upload
(
imgUrl
string
)
(
string
,
error
)
Upload
(
path
string
)
(
string
,
error
)
}
type
S3Uploader
struct
{
...
...
@@ -28,13 +27,7 @@ func NewS3Uploader(bucket, accessKey, secretKey string) *S3Uploader {
}
}
func
(
u
*
S3Uploader
)
Upload
(
imgUrl
string
)
(
string
,
error
)
{
client
:=
http
.
Client
{
Timeout
:
time
.
Duration
(
60
*
time
.
Second
)}
res
,
err
:=
client
.
Get
(
imgUrl
)
if
err
!=
nil
{
return
""
,
err
}
func
(
u
*
S3Uploader
)
Upload
(
path
string
)
(
string
,
error
)
{
s3util
.
DefaultConfig
.
AccessKey
=
u
.
accessKey
s3util
.
DefaultConfig
.
SecretKey
=
u
.
secretKey
...
...
@@ -53,7 +46,7 @@ func (u *S3Uploader) Upload(imgUrl string) (string, error) {
defer
writer
.
Close
()
imgData
,
err
:=
ioutil
.
Read
All
(
res
.
Body
)
imgData
,
err
:=
ioutil
.
Read
File
(
path
)
if
err
!=
nil
{
return
""
,
err
}
...
...
pkg/components/renderer/renderer.go
View file @
2b276d5c
...
...
@@ -9,10 +9,11 @@ import (
"runtime"
"time"
"strconv"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"strconv"
)
type
RenderOpts
struct
{
...
...
@@ -23,8 +24,10 @@ type RenderOpts struct {
Timeout
string
}
var
rendererLog
log
.
Logger
=
log
.
New
(
"png-renderer"
)
func
RenderToPng
(
params
*
RenderOpts
)
(
string
,
error
)
{
log
.
Info
(
"PhantomRenderer::renderToPng url %v
"
,
params
.
Url
)
rendererLog
.
Info
(
"Rendering"
,
"url
"
,
params
.
Url
)
var
executable
=
"phantomjs"
if
runtime
.
GOOS
==
"windows"
{
...
...
@@ -71,11 +74,12 @@ func RenderToPng(params *RenderOpts) (string, error) {
select
{
case
<-
time
.
After
(
time
.
Duration
(
timeout
)
*
time
.
Second
)
:
if
err
:=
cmd
.
Process
.
Kill
();
err
!=
nil
{
log
.
Error
(
4
,
"failed to kill: %v
"
,
err
)
rendererLog
.
Error
(
"failed to kill"
,
"error
"
,
err
)
}
return
""
,
fmt
.
Errorf
(
"PhantomRenderer::renderToPng timeout (>%vs)"
,
timeout
)
case
<-
done
:
}
rendererLog
.
Debug
(
"Image rendered"
,
"path"
,
pngPath
)
return
pngPath
,
nil
}
pkg/services/alerting/eval_context.go
View file @
2b276d5c
package
alerting
import
(
"fmt"
"time"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/log"
m
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
)
type
EvalContext
struct
{
Firing
bool
IsTestRun
bool
Events
[]
*
Event
Logs
[]
*
ResultLogEntry
Error
error
Description
string
StartTime
time
.
Time
EndTime
time
.
Time
Rule
*
Rule
DoneChan
chan
bool
CancelChan
chan
bool
log
log
.
Logger
Firing
bool
IsTestRun
bool
Events
[]
*
Event
Logs
[]
*
ResultLogEntry
Error
error
Description
string
StartTime
time
.
Time
EndTime
time
.
Time
Rule
*
Rule
DoneChan
chan
bool
CancelChan
chan
bool
log
log
.
Logger
dashboardSlug
string
ImagePublicUrl
string
ImageOnDiskPath
string
}
func
(
a
*
EvalContext
)
GetDurationMs
()
float64
{
...
...
@@ -50,6 +56,38 @@ func (c *EvalContext) GetStateText() string {
}
}
func
(
c
*
EvalContext
)
getDashboardSlug
()
(
string
,
error
)
{
if
c
.
dashboardSlug
!=
""
{
return
c
.
dashboardSlug
,
nil
}
slugQuery
:=
&
m
.
GetDashboardSlugByIdQuery
{
Id
:
c
.
Rule
.
DashboardId
}
if
err
:=
bus
.
Dispatch
(
slugQuery
);
err
!=
nil
{
return
""
,
err
}
c
.
dashboardSlug
=
slugQuery
.
Result
return
c
.
dashboardSlug
,
nil
}
func
(
c
*
EvalContext
)
GetRuleUrl
()
(
string
,
error
)
{
if
slug
,
err
:=
c
.
getDashboardSlug
();
err
!=
nil
{
return
""
,
err
}
else
{
ruleUrl
:=
fmt
.
Sprintf
(
"%sdashboard/db/%s?fullscreen&edit&tab=alert&panelId=%d"
,
setting
.
AppUrl
,
slug
,
c
.
Rule
.
PanelId
)
return
ruleUrl
,
nil
}
}
func
(
c
*
EvalContext
)
GetImageUrl
()
(
string
,
error
)
{
if
slug
,
err
:=
c
.
getDashboardSlug
();
err
!=
nil
{
return
""
,
err
}
else
{
ruleUrl
:=
fmt
.
Sprintf
(
"%sdashboard-solo/db/%s?&panelId=%d"
,
setting
.
AppUrl
,
slug
,
c
.
Rule
.
PanelId
)
return
ruleUrl
,
nil
}
}
func
NewEvalContext
(
rule
*
Rule
)
*
EvalContext
{
return
&
EvalContext
{
StartTime
:
time
.
Now
(),
...
...
pkg/services/alerting/notifier.go
View file @
2b276d5c
...
...
@@ -4,8 +4,11 @@ import (
"errors"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/imguploader"
"github.com/grafana/grafana/pkg/components/renderer"
"github.com/grafana/grafana/pkg/log"
m
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
)
type
RootNotifier
struct
{
...
...
@@ -35,12 +38,51 @@ func (n *RootNotifier) Notify(context *EvalContext) {
return
}
err
=
n
.
uploadImage
(
context
)
if
err
!=
nil
{
n
.
log
.
Error
(
"Failed to upload alert panel image"
,
"error"
,
err
)
}
for
_
,
notifier
:=
range
notifiers
{
n
.
log
.
Info
(
"Sending notification"
,
"firing"
,
context
.
Firing
,
"type"
,
notifier
.
GetType
())
go
notifier
.
Notify
(
context
)
}
}
func
(
n
*
RootNotifier
)
uploadImage
(
context
*
EvalContext
)
error
{
uploader
:=
imguploader
.
NewS3Uploader
(
setting
.
S3TempImageStoreBucketUrl
,
setting
.
S3TempImageStoreAccessKey
,
setting
.
S3TempImageStoreSecretKey
)
imageUrl
,
err
:=
context
.
GetImageUrl
()
if
err
!=
nil
{
return
err
}
renderOpts
:=
&
renderer
.
RenderOpts
{
Url
:
imageUrl
,
Width
:
"800"
,
Height
:
"400"
,
SessionId
:
"123"
,
Timeout
:
"10"
,
}
if
imagePath
,
err
:=
renderer
.
RenderToPng
(
renderOpts
);
err
!=
nil
{
return
err
}
else
{
context
.
ImageOnDiskPath
=
imagePath
}
context
.
ImagePublicUrl
,
err
=
uploader
.
Upload
(
context
.
ImageOnDiskPath
)
if
err
!=
nil
{
return
err
}
n
.
log
.
Info
(
"uploaded"
,
"url"
,
context
.
ImagePublicUrl
)
return
nil
}
func
(
n
*
RootNotifier
)
getNotifiers
(
orgId
int64
,
notificationIds
[]
int64
)
([]
Notifier
,
error
)
{
query
:=
&
m
.
GetAlertNotificationsQuery
{
OrgId
:
orgId
,
Ids
:
notificationIds
}
...
...
pkg/services/alerting/notifiers/common.go
View file @
2b276d5c
package
notifiers
import
(
"fmt"
"github.com/grafana/grafana/pkg/bus"
m
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/setting"
)
func
getRuleLink
(
rule
*
alerting
.
Rule
)
(
string
,
error
)
{
slugQuery
:=
&
m
.
GetDashboardSlugByIdQuery
{
Id
:
rule
.
DashboardId
}
if
err
:=
bus
.
Dispatch
(
slugQuery
);
err
!=
nil
{
return
""
,
err
}
ruleLink
:=
fmt
.
Sprintf
(
"%sdashboard/db/%s?fullscreen&edit&tab=alert&panelId=%d"
,
setting
.
AppUrl
,
slugQuery
.
Result
,
rule
.
PanelId
)
return
ruleLink
,
nil
}
pkg/services/alerting/notifiers/email.go
View file @
2b276d5c
...
...
@@ -39,7 +39,7 @@ func NewEmailNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
func
(
this
*
EmailNotifier
)
Notify
(
context
*
alerting
.
EvalContext
)
{
this
.
log
.
Info
(
"Sending alert notification to"
,
"addresses"
,
this
.
Addresses
)
rule
Link
,
err
:=
getRuleLink
(
context
.
Rule
)
rule
Url
,
err
:=
context
.
GetRuleUrl
(
)
if
err
!=
nil
{
this
.
log
.
Error
(
"Failed get rule link"
,
"error"
,
err
)
return
...
...
@@ -50,7 +50,7 @@ func (this *EmailNotifier) Notify(context *alerting.EvalContext) {
"RuleState"
:
context
.
Rule
.
State
,
"RuleName"
:
context
.
Rule
.
Name
,
"Severity"
:
context
.
Rule
.
Severity
,
"Rule
Link"
:
ruleLink
,
"Rule
Url"
:
ruleUrl
,
},
To
:
this
.
Addresses
,
Template
:
"alert_notification.html"
,
...
...
pkg/services/alerting/notifiers/slack.go
View file @
2b276d5c
...
...
@@ -41,7 +41,7 @@ func (this *SlackNotifier) Notify(context *alerting.EvalContext) {
rule
:=
context
.
Rule
rule
Link
,
err
:=
getRuleLink
(
rule
)
rule
Url
,
err
:=
context
.
GetRuleUrl
(
)
if
err
!=
nil
{
this
.
log
.
Error
(
"Failed get rule link"
,
"error"
,
err
)
return
...
...
@@ -69,10 +69,10 @@ func (this *SlackNotifier) Notify(context *alerting.EvalContext) {
// "author_link": "http://flickr.com/bobby/",
// "author_icon": "http://flickr.com/icons/bobby.jpg",
"title"
:
"["
+
context
.
GetStateText
()
+
"] "
+
rule
.
Name
,
"title_link"
:
rule
Link
,
"title_link"
:
rule
Url
,
// "text": "Optional text that appears within the attachment",
"fields"
:
fields
,
// "image_url": "http://my-website.com/path/to/image.jpg"
,
"fields"
:
fields
,
"image_url"
:
context
.
ImagePublicUrl
,
// "thumb_url": "http://example.com/path/to/thumb.png",
"footer"
:
"Grafana v4.0.0"
,
"footer_icon"
:
"http://grafana.org/assets/img/fav32.png"
,
...
...
pkg/setting/setting.go
View file @
2b276d5c
...
...
@@ -148,6 +148,11 @@ var (
// Grafana.NET URL
GrafanaNetUrl
string
// S3 temp image store
S3TempImageStoreBucketUrl
string
S3TempImageStoreAccessKey
string
S3TempImageStoreSecretKey
string
)
type
CommandLineArgs
struct
{
...
...
@@ -534,6 +539,10 @@ func NewConfigContext(args *CommandLineArgs) error {
GrafanaNetUrl
=
Cfg
.
Section
(
"grafana.net"
)
.
Key
(
"url"
)
.
MustString
(
"https://grafana.net"
)
s3temp
:=
Cfg
.
Section
(
"s3-temp-image-store"
)
S3TempImageStoreBucketUrl
=
s3temp
.
Key
(
"bucket_url"
)
.
String
()
S3TempImageStoreAccessKey
=
s3temp
.
Key
(
"access_key"
)
.
String
()
S3TempImageStoreSecretKey
=
s3temp
.
Key
(
"secret_key"
)
.
String
()
return
nil
}
...
...
vendor/phantomjs/render.js
View file @
2b276d5c
...
...
@@ -35,6 +35,17 @@
page
.
open
(
params
.
url
,
function
(
status
)
{
// console.log('Loading a web page: ' + params.url + ' status: ' + status);
page
.
onError
=
function
(
msg
,
trace
)
{
var
msgStack
=
[
'ERROR: '
+
msg
];
if
(
trace
&&
trace
.
length
)
{
msgStack
.
push
(
'TRACE:'
);
trace
.
forEach
(
function
(
t
)
{
msgStack
.
push
(
' -> '
+
t
.
file
+
': '
+
t
.
line
+
(
t
.
function
?
' (in function "'
+
t
.
function
+
'")'
:
''
));
});
}
console
.
error
(
msgStack
.
join
(
'
\
n'
));
};
function
checkIsReady
()
{
var
panelsRendered
=
page
.
evaluate
(
function
()
{
if
(
!
window
.
angular
)
{
return
false
;
}
...
...
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