mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: update email template (#34205)
This commit is contained in:
parent
5dca9fd4d8
commit
54c33c6cdd
@ -1,150 +1,218 @@
|
||||
[[Subject .Subject "[[.Title]]"]]
|
||||
|
||||
[[ define "alert" ]]
|
||||
[[ if gt (len .Annotations.SortedPairs) 0 ]]
|
||||
<tr>
|
||||
<td colspan="2" class="annotations">
|
||||
[[ range .Annotations.SortedPairs ]]
|
||||
<p>[[ .Name ]]: [[ .Value ]]</p>
|
||||
[[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ end ]]
|
||||
<tr>
|
||||
<td valign="top" class="labels-heading">Labels:</td>
|
||||
<td>
|
||||
<ul class="labels-list">
|
||||
[[ range .Labels.SortedPairs ]]<li>[[ .Name ]]: [[ .Value ]]</li>[[ end ]]
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
[[ if .SilenceURL ]]
|
||||
<a
|
||||
href="[[ .SilenceURL ]]"
|
||||
class="button"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
height="14"
|
||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAF1SURBVHgBrZLNTsJAEMf/2wYTPfEI9Q1qvBgjsEl5gB498gj1SDHpEKUckaMn4eiNFyAp4cJN30CPHrn5BV1noTWlFD3oJNuZ3Z39zUcH+A9pUffJpzAoOO/xuvvprZHooYCgLISoa7FyFSCbdOXuApj6M43GUVXWhYZUpKP3k1NZ14+kAOYChleVjnssK/ezKHrLAkQuZWIVKCgKyW+n55cUciZClzLoUPOiqISVlPB+s6ZulnNN/ihG3GfT84jKOwGvMO0krVEewoBoHeTA2glIhRuno7WzkH0Yc633sCz/CoiVshdYRGxGKYSo9ahgHnEPoqzvdxP1b/sEHtgsF2e12ditDD6gPE59XgIO8ytfTlbM1DiTzjk7WQvEYgllZ5fSXeE7vnfTOdkC1GqOBSFO2Mk22JG1TB4l+1VzX/IQgQJpBaHHsB6bA47+rNOHUI1O4A/zw2YWAaaT8UyPNkdcZ6JUs0P+7eouGXuO3WC7j7/KF29iokiLUdaFAAAAAElFTkSuQmCC"
|
||||
class="button-img"
|
||||
width="14"
|
||||
/>
|
||||
Silence
|
||||
</a>
|
||||
[[ end ]]
|
||||
[[ if .Annotations.runbook_url ]]
|
||||
<a
|
||||
href="[[ .Annotations.runbook_url ]]"
|
||||
class="button"
|
||||
>
|
||||
<img
|
||||
class="button-img"
|
||||
alt=""
|
||||
height="14"
|
||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADaSURBVHgBrVNLDoIwFJwq0bjTG+ARvIGeQI/ADdSVARY8oki8jZxEbyDewLUfahttAoEWDM7m9bVvJtN0CrQEyzdENLyjt2RgtoFzjcgl1XTyJw/0T4K8ghmBH8Zz1VhqsaHtVBT7CYwP5KY6tk+xw3k2Kgl0YdmyKrIYvEjB73EqbI+rBC1owMDXGdjws0aqm9MK7Mg7ogE6aInWAqUreLQPanJgdtAgB2YHIgeTuhxUOlBPNcBvKPwFT4RHbnDgLOpNw3EEaxEFblJwIPECZhw8MZAlQkX+C95zCzqWDYrK2AAAAABJRU5ErkJggg=="
|
||||
width="14"
|
||||
/>
|
||||
View Runbook
|
||||
</a>
|
||||
[[ end ]]
|
||||
[[ if .DashboardURL]]
|
||||
<a
|
||||
href="[[ .DashboardURL ]]"
|
||||
class="button"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
height="14"
|
||||
class="button-img"
|
||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAE9SURBVHgBrVLNWcMwDH220/bjhEdIR2AC6ASMQEeAU6G9+FLycQojdAUmgE7ACGSEcEybRkj5cUKbnFp9X2JZ8nuypQecaUp+Kxf98BIeJ3cwNxqZDRB89mCTtXuZBvVGwBsCtiUrkYVS8RgHmzeVFB4Lwm9d9Y6XB/EbAhCK7atbbcRfuCjkRNwtt6fs4825RPyli4SkJNA40/wNFCm7cC6sdnnYSdVmQs6Xnla4JjoikDcHmMQYrCSNrI434C7BrA/EXf6Slad0kieY1BPsUKQahcWA5cj7otYTjKG/+/oplQU8oAMx1aKInkbAVL6BJ818ns82wVYHilLnlon4rIOTGeTIWHleB6mq4xfUAfTts1tXPh1YyubfwZGa3HO+K+WWgMeacHBuoOc1m7cr6HSPcvbvpnNhweAS9gdSqGSnoVA2cQAAAABJRU5ErkJggg=="
|
||||
width="14"
|
||||
/>
|
||||
Go to Dashboard
|
||||
</a>
|
||||
[[ end ]]
|
||||
[[ if .PanelURL]]
|
||||
<a
|
||||
href="[[ .PanelURL ]]"
|
||||
class="button"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
class="button-img"
|
||||
height="14"
|
||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAE9SURBVHgBrVLNWcMwDH220/bjhEdIR2AC6ASMQEeAU6G9+FLycQojdAUmgE7ACGSEcEybRkj5cUKbnFp9X2JZ8nuypQecaUp+Kxf98BIeJ3cwNxqZDRB89mCTtXuZBvVGwBsCtiUrkYVS8RgHmzeVFB4Lwm9d9Y6XB/EbAhCK7atbbcRfuCjkRNwtt6fs4825RPyli4SkJNA40/wNFCm7cC6sdnnYSdVmQs6Xnla4JjoikDcHmMQYrCSNrI434C7BrA/EXf6Slad0kieY1BPsUKQahcWA5cj7otYTjKG/+/oplQU8oAMx1aKInkbAVL6BJ818ns82wVYHilLnlon4rIOTGeTIWHleB6mq4xfUAfTts1tXPh1YyubfwZGa3HO+K+WWgMeacHBuoOc1m7cr6HSPcvbvpnNhweAS9gdSqGSnoVA2cQAAAABJRU5ErkJggg=="
|
||||
width="14"
|
||||
/>
|
||||
Go to Panel
|
||||
</a>
|
||||
[[ end ]]
|
||||
[[ if gt (len .GeneratorURL) 0 ]]<a href="[[ .GeneratorURL ]]" class="button">Source</a>[[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div style="height: 24px"></div>
|
||||
<div style="background: #c7d0d9; height: 1px"></div>
|
||||
<div style="height: 24px"></div>
|
||||
</td>
|
||||
</tr>
|
||||
[[ end ]]
|
||||
|
||||
[[ if gt (len .Message) 0 ]]
|
||||
[[ .Message ]]
|
||||
[[ else ]]
|
||||
|
||||
<style>
|
||||
.alert-warning {
|
||||
background-color: #E6522C;
|
||||
.button {
|
||||
background: #f1f5f9;
|
||||
border: 1px solid #c7d0d9;
|
||||
border-radius: 2px;
|
||||
color: #464c54;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin: 0 10px 0 0;
|
||||
padding: 5px 9px;
|
||||
}
|
||||
.alert-good {
|
||||
background-color: #68B90F;
|
||||
.annotations {
|
||||
font-size: 14px;
|
||||
padding: 24px 0 12px 0;
|
||||
}
|
||||
.labels-heading {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
vertical-align: top;
|
||||
}
|
||||
.labels-list {
|
||||
font-size: 14px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.section-heading {
|
||||
color: #2c3235;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
padding: 0 0 32px 0;
|
||||
}
|
||||
.alert-label {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 0 0 0 12px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.status-tag {
|
||||
color: #ffffff;
|
||||
padding: 4px 8px;
|
||||
text-align: center;
|
||||
width: 68px
|
||||
}
|
||||
.status-firing {
|
||||
background: #e02f44;
|
||||
}
|
||||
.status-resolved {
|
||||
background: #464c54;
|
||||
}
|
||||
.button-img {
|
||||
height: 14px;
|
||||
margin: 0 5px 0 0;
|
||||
vertical-align: sub;
|
||||
width: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<table class="row">
|
||||
<tr>
|
||||
<td class="wrapper last">
|
||||
<table class="twelve columns">
|
||||
<td class="twelve">
|
||||
<table>
|
||||
[[ if gt (len .Alerts.Firing) 0 ]]
|
||||
<tr>
|
||||
<td class="center">
|
||||
[[ if gt (len .Alerts.Firing) 0 ]]
|
||||
<h3 style="color: #E6522C; font-weight: bold; font-style: italic;">[[.Title]]</h3>
|
||||
[[ else ]]
|
||||
<h3 style="font-weight: bold; font-style: italic;">[[.Title]]</h3>
|
||||
[[ end ]]
|
||||
<td colspan="2" class="section-heading">
|
||||
Firing: [[ .Alerts.Firing | len ]] alert[[ if gt (len .Alerts.Firing) 1 ]]s[[ end ]][[ if gt (len .GroupLabels.SortedPairs) 1 ]] for
|
||||
[[ range .GroupLabels.SortedPairs ]]
|
||||
[[ .Name ]]=[[ .Value ]]
|
||||
[[ end ]][[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="row">
|
||||
<tr>
|
||||
[[ if gt (len .Alerts.Firing) 0 ]]
|
||||
<td class="alert-warning twelve column last">
|
||||
[[ .Alerts | len ]] alert[[ if gt (len .Alerts) 1 ]]s[[ end ]] for
|
||||
[[ range .GroupLabels.SortedPairs ]]
|
||||
[[ .Name ]]=[[ .Value ]]
|
||||
[[ end ]]
|
||||
</td>
|
||||
[[ else ]]
|
||||
<td class="alert-good twelve column last">
|
||||
[[ .Alerts | len ]] alert[[ if gt (len .Alerts) 1 ]]s[[ end ]] for
|
||||
[[ range .GroupLabels.SortedPairs ]]
|
||||
[[ .Name ]]=[[ .Value ]]
|
||||
[[ end ]]
|
||||
</td>
|
||||
[[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="last">
|
||||
<table class="twelve columns">
|
||||
[[ if gt (len .Alerts.Firing) 0 ]]
|
||||
<tr>
|
||||
<td class="twelve last">
|
||||
<h5 style="font-weight: bold;">([[ .Alerts.Firing | len ]]) Firing</h5>
|
||||
</td>
|
||||
</tr>
|
||||
[[ end ]]
|
||||
[[ range .Alerts.Firing ]]
|
||||
<tr>
|
||||
<td class="four">
|
||||
<h5 style="font-weight: bold">Labels</h5>
|
||||
</td>
|
||||
<td class="eight last">
|
||||
[[ if gt (len .Annotations) 0 ]]<h5 style="font-weight: bold">Annotations</h5>[[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="four">
|
||||
[[ range .Labels.SortedPairs ]][[ .Name ]] = [[ .Value ]]<br />[[ end ]]
|
||||
<a href="[[ .GeneratorURL ]]">Source</a><br />
|
||||
</td>
|
||||
<td class="eight last">
|
||||
[[ range .Annotations.SortedPairs ]][[ .Name ]] = [[ .Value ]]<br />[[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
class="status-tag status-firing"
|
||||
width="68"
|
||||
>
|
||||
Firing
|
||||
</td>
|
||||
<td class="alert-label">
|
||||
[[ .Labels.alertname ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ template "alert" . ]]
|
||||
[[ end ]]
|
||||
|
||||
[[ if gt (len .Alerts.Resolved) 0 ]]
|
||||
[[ if gt (len .Alerts.Firing) 0 ]]
|
||||
[[ end ]]
|
||||
[[ if gt (len .Alerts.Resolved) 0 ]]
|
||||
<tr>
|
||||
<td class="twelve">
|
||||
<br />
|
||||
<hr />
|
||||
<br />
|
||||
<td colspan="2" class="section-heading">
|
||||
Resolved: [[ .Alerts.Resolved | len ]] alert[[ if gt (len .Alerts.Resolved) 1 ]]s[[ end ]][[ if gt (len .GroupLabels.SortedPairs) 1 ]] for
|
||||
[[ range .GroupLabels.SortedPairs ]]
|
||||
[[ .Name ]]=[[ .Value ]]
|
||||
[[ end ]][[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ end ]]
|
||||
<tr>
|
||||
<td class="twelve last">
|
||||
<h5 style="font-weight: bold;">([[ .Alerts.Resolved | len ]]) Resolved</h5>
|
||||
</td>
|
||||
</tr>
|
||||
[[ end ]]
|
||||
[[ range .Alerts.Resolved ]]
|
||||
<tr>
|
||||
<td class="six">
|
||||
<h5 style="font-weight: bold">Labels</h5>
|
||||
</td>
|
||||
<td class="six last">
|
||||
[[ if gt (len .Annotations) 0 ]]<h5 style="font-weight: bold">Annotations</h5>[[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="six">
|
||||
[[ range .Labels.SortedPairs ]][[ .Name ]] = [[ .Value ]]<br />[[ end ]]
|
||||
<a href="[[ .GeneratorURL ]]">Source</a><br />
|
||||
</td>
|
||||
<td class="six last">
|
||||
[[ range .Annotations.SortedPairs ]][[ .Name ]] = [[ .Value ]]<br />[[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
class="status-tag status-resolved"
|
||||
width="68"
|
||||
>
|
||||
Resolved
|
||||
</td>
|
||||
<td class="alert-label">
|
||||
[[ .Labels.alertname ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ template "alert" . ]]
|
||||
[[ end ]]
|
||||
[[ end ]]
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<a href="[[ .AlertPageUrl ]]" class="button">Go to alerts page</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
<table class="row">
|
||||
<tr>
|
||||
<td class="wrapper last">
|
||||
<table class="twelve columns">
|
||||
<tr>
|
||||
<td class="center six">
|
||||
<table class="better-button" align="center" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" class="better-button" bgcolor="#ff8f2b">
|
||||
<a href="[[.RuleUrl]]" target="_blank">View your Alert rule</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="center six">
|
||||
<table class="better-button" align="center" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" class="better-button-alt" bgcolor="#efefef">
|
||||
<a href="[[.AlertPageUrl]]" target="_blank"> Go to the Alerts page</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
[[ end ]]
|
@ -3,6 +3,7 @@ package channels
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
gokit_log "github.com/go-kit/kit/log"
|
||||
@ -66,12 +67,25 @@ func NewEmailNotifier(model *NotificationChannelConfig, t *template.Template) (*
|
||||
// Notify sends the alert notification.
|
||||
func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
|
||||
// We only need ExternalURL from this template object. This hack should go away with https://github.com/prometheus/alertmanager/pull/2508.
|
||||
data := notify.GetTemplateData(ctx, &template.Template{ExternalURL: en.tmpl.ExternalURL}, as, gokit_log.NewLogfmtLogger(logging.NewWrapper(en.log)))
|
||||
data, err := ExtendData(notify.GetTemplateData(ctx, &template.Template{ExternalURL: en.tmpl.ExternalURL}, as, gokit_log.NewLogfmtLogger(logging.NewWrapper(en.log))))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
var tmplErr error
|
||||
tmpl := notify.TmplText(en.tmpl, data, &tmplErr)
|
||||
tmpl := TmplText(en.tmpl, data, &tmplErr)
|
||||
|
||||
title := tmpl(`{{ template "default.title" . }}`)
|
||||
|
||||
u, err := url.Parse(en.tmpl.ExternalURL.String())
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to parse external URL: %w", err)
|
||||
}
|
||||
basePath := u.Path
|
||||
u.Path = path.Join(basePath, "/alerting/list")
|
||||
ruleURL := u.String()
|
||||
u.RawQuery = "alertState=firing&view=state"
|
||||
alertPageURL := u.String()
|
||||
|
||||
cmd := &models.SendEmailCommandSync{
|
||||
SendEmailCommand: models.SendEmailCommand{
|
||||
Subject: title,
|
||||
@ -84,8 +98,8 @@ func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
||||
"CommonLabels": data.CommonLabels,
|
||||
"CommonAnnotations": data.CommonAnnotations,
|
||||
"ExternalURL": data.ExternalURL,
|
||||
"RuleUrl": path.Join(en.tmpl.ExternalURL.String(), "/alerting/list"),
|
||||
"AlertPageUrl": path.Join(en.tmpl.ExternalURL.String(), "/alerting/list?alertState=firing&view=state"),
|
||||
"RuleUrl": ruleURL,
|
||||
"AlertPageUrl": alertPageURL,
|
||||
},
|
||||
To: en.Addresses,
|
||||
SingleEmail: en.SingleEmail,
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
func TestEmailNotifier(t *testing.T) {
|
||||
tmpl := templateForTests(t)
|
||||
|
||||
externalURL, err := url.Parse("http://localhost")
|
||||
externalURL, err := url.Parse("http://localhost/base")
|
||||
require.NoError(t, err)
|
||||
tmpl.ExternalURL = externalURL
|
||||
|
||||
@ -67,7 +67,7 @@ func TestEmailNotifier(t *testing.T) {
|
||||
{
|
||||
Alert: model.Alert{
|
||||
Labels: model.LabelSet{"alertname": "AlwaysFiring", "severity": "warning"},
|
||||
Annotations: model.LabelSet{"runbook_url": "http://fix.me"},
|
||||
Annotations: model.LabelSet{"runbook_url": "http://fix.me", "__dashboardUid__": "abc", "__panelId__": "5"},
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -85,20 +85,23 @@ func TestEmailNotifier(t *testing.T) {
|
||||
"Title": "[FIRING:1] (AlwaysFiring warning)",
|
||||
"Message": "[FIRING:1] (AlwaysFiring warning)",
|
||||
"Status": "firing",
|
||||
"Alerts": template.Alerts{
|
||||
template.Alert{
|
||||
Status: "firing",
|
||||
Labels: template.KV{"alertname": "AlwaysFiring", "severity": "warning"},
|
||||
Annotations: template.KV{"runbook_url": "http://fix.me"},
|
||||
Fingerprint: "15a37193dce72bab",
|
||||
"Alerts": ExtendedAlerts{
|
||||
ExtendedAlert{
|
||||
Status: "firing",
|
||||
Labels: template.KV{"alertname": "AlwaysFiring", "severity": "warning"},
|
||||
Annotations: template.KV{"runbook_url": "http://fix.me"},
|
||||
Fingerprint: "15a37193dce72bab",
|
||||
SilenceURL: "http://localhost/base/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DAlwaysFiring%2Cseverity%3Dwarning",
|
||||
DashboardURL: "http://localhost/base/d/abc",
|
||||
PanelURL: "http://localhost/base/d/abc?viewPanel=5",
|
||||
},
|
||||
},
|
||||
"GroupLabels": template.KV{},
|
||||
"CommonLabels": template.KV{"alertname": "AlwaysFiring", "severity": "warning"},
|
||||
"CommonAnnotations": template.KV{"runbook_url": "http://fix.me"},
|
||||
"ExternalURL": "http://localhost",
|
||||
"RuleUrl": "http:/localhost/alerting/list",
|
||||
"AlertPageUrl": "http:/localhost/alerting/list?alertState=firing&view=state",
|
||||
"ExternalURL": "http://localhost/base",
|
||||
"RuleUrl": "http://localhost/base/alerting/list",
|
||||
"AlertPageUrl": "http://localhost/base/alerting/list?alertState=firing&view=state",
|
||||
},
|
||||
}, expected)
|
||||
})
|
||||
|
153
pkg/services/ngalert/notifier/channels/template_data.go
Normal file
153
pkg/services/ngalert/notifier/channels/template_data.go
Normal file
@ -0,0 +1,153 @@
|
||||
package channels
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
type ExtendedAlert struct {
|
||||
Status string `json:"status"`
|
||||
Labels template.KV `json:"labels"`
|
||||
Annotations template.KV `json:"annotations"`
|
||||
StartsAt time.Time `json:"startsAt"`
|
||||
EndsAt time.Time `json:"endsAt"`
|
||||
GeneratorURL string `json:"generatorURL"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
SilenceURL string `json:"silenceURL"`
|
||||
DashboardURL string `json:"dashboardURL"`
|
||||
PanelURL string `json:"panelURL"`
|
||||
}
|
||||
|
||||
type ExtendedAlerts []ExtendedAlert
|
||||
|
||||
type ExtendedData struct {
|
||||
Receiver string `json:"receiver"`
|
||||
Status string `json:"status"`
|
||||
Alerts ExtendedAlerts `json:"alerts"`
|
||||
|
||||
GroupLabels template.KV `json:"groupLabels"`
|
||||
CommonLabels template.KV `json:"commonLabels"`
|
||||
CommonAnnotations template.KV `json:"commonAnnotations"`
|
||||
|
||||
ExternalURL string `json:"externalURL"`
|
||||
}
|
||||
|
||||
func removePrivateItems(kv template.KV) template.KV {
|
||||
for key := range kv {
|
||||
if strings.HasPrefix(key, "__") && strings.HasSuffix(key, "__") {
|
||||
kv = kv.Remove([]string{key})
|
||||
}
|
||||
}
|
||||
return kv
|
||||
}
|
||||
|
||||
func extendAlert(alert template.Alert, externalURL string) (*ExtendedAlert, error) {
|
||||
extended := ExtendedAlert{
|
||||
Status: alert.Status,
|
||||
Labels: alert.Labels,
|
||||
Annotations: alert.Annotations,
|
||||
StartsAt: alert.StartsAt,
|
||||
EndsAt: alert.EndsAt,
|
||||
GeneratorURL: alert.GeneratorURL,
|
||||
Fingerprint: alert.Fingerprint,
|
||||
}
|
||||
|
||||
// fill in some grafana-specific urls
|
||||
if len(externalURL) > 0 {
|
||||
u, err := url.Parse(externalURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse external URL: %w", err)
|
||||
}
|
||||
externalPath := u.Path
|
||||
dashboardUid := alert.Annotations["__dashboardUid__"]
|
||||
if len(dashboardUid) > 0 {
|
||||
u.Path = path.Join(externalPath, "/d/", dashboardUid)
|
||||
extended.DashboardURL = u.String()
|
||||
panelId := alert.Annotations["__panelId__"]
|
||||
if len(panelId) > 0 {
|
||||
u.RawQuery = "viewPanel=" + panelId
|
||||
extended.PanelURL = u.String()
|
||||
}
|
||||
}
|
||||
|
||||
matchers := make([]string, 0)
|
||||
for key, value := range alert.Labels {
|
||||
if !(strings.HasPrefix(key, "__") && strings.HasSuffix(key, "__")) {
|
||||
matchers = append(matchers, key+"="+value)
|
||||
}
|
||||
}
|
||||
sort.Strings(matchers)
|
||||
u.Path = path.Join(externalPath, "/alerting/silence/new")
|
||||
u.RawQuery = "alertmanager=grafana&matchers=" + url.QueryEscape(strings.Join(matchers, ","))
|
||||
extended.SilenceURL = u.String()
|
||||
}
|
||||
|
||||
// remove "private" annotations & labels so they don't show up in the template
|
||||
extended.Annotations = removePrivateItems(extended.Annotations)
|
||||
extended.Labels = removePrivateItems(extended.Labels)
|
||||
|
||||
return &extended, nil
|
||||
}
|
||||
|
||||
func ExtendData(data *template.Data) (*ExtendedData, error) {
|
||||
alerts := []ExtendedAlert{}
|
||||
|
||||
for _, alert := range data.Alerts {
|
||||
extendedAlert, err := extendAlert(alert, data.ExternalURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
alerts = append(alerts, *extendedAlert)
|
||||
}
|
||||
|
||||
extended := &ExtendedData{
|
||||
Receiver: data.Receiver,
|
||||
Status: data.Status,
|
||||
Alerts: alerts,
|
||||
GroupLabels: data.GroupLabels,
|
||||
CommonLabels: removePrivateItems(data.CommonLabels),
|
||||
CommonAnnotations: removePrivateItems(data.CommonAnnotations),
|
||||
|
||||
ExternalURL: data.ExternalURL,
|
||||
}
|
||||
return extended, nil
|
||||
}
|
||||
|
||||
func TmplText(tmpl *template.Template, data *ExtendedData, err *error) func(string) string {
|
||||
return func(name string) (s string) {
|
||||
if *err != nil {
|
||||
return
|
||||
}
|
||||
s, *err = tmpl.ExecuteTextString(name, data)
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// Firing returns the subset of alerts that are firing.
|
||||
func (as ExtendedAlerts) Firing() []ExtendedAlert {
|
||||
res := []ExtendedAlert{}
|
||||
for _, a := range as {
|
||||
if a.Status == string(model.AlertFiring) {
|
||||
res = append(res, a)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Resolved returns the subset of alerts that are resolved.
|
||||
func (as ExtendedAlerts) Resolved() []ExtendedAlert {
|
||||
res := []ExtendedAlert{}
|
||||
for _, a := range as {
|
||||
if a.Status == string(model.AlertResolved) {
|
||||
res = append(res, a)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { Silence, SilenceCreatePayload } from 'app/plugins/datasource/alertmanager/types';
|
||||
import React, { FC, useState } from 'react';
|
||||
import React, { FC, useMemo, useState } from 'react';
|
||||
import { Button, Field, FieldSet, Input, LinkButton, TextArea, useStyles } from '@grafana/ui';
|
||||
import {
|
||||
DefaultTimeZone,
|
||||
@ -9,6 +9,7 @@ import {
|
||||
addDurationToDate,
|
||||
dateTime,
|
||||
isValidDate,
|
||||
UrlQueryMap,
|
||||
} from '@grafana/data';
|
||||
import { useDebounce } from 'react-use';
|
||||
import { config } from '@grafana/runtime';
|
||||
@ -23,13 +24,34 @@ import { css, cx } from '@emotion/css';
|
||||
import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector';
|
||||
import { makeAMLink } from '../../utils/misc';
|
||||
import { useCleanup } from 'app/core/hooks/useCleanup';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { parseQueryParamMatchers } from '../../utils/matchers';
|
||||
|
||||
interface Props {
|
||||
silence?: Silence;
|
||||
alertManagerSourceName: string;
|
||||
}
|
||||
|
||||
const getDefaultFormValues = (silence?: Silence): SilenceFormFields => {
|
||||
const defaultsFromQuery = (queryParams: UrlQueryMap): Partial<SilenceFormFields> => {
|
||||
const defaults: Partial<SilenceFormFields> = {};
|
||||
|
||||
const { matchers, comment } = queryParams;
|
||||
|
||||
if (typeof matchers === 'string') {
|
||||
const formMatchers = parseQueryParamMatchers(matchers);
|
||||
if (formMatchers.length) {
|
||||
defaults.matchers = formMatchers;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof comment === 'string') {
|
||||
defaults.comment = comment;
|
||||
}
|
||||
|
||||
return defaults;
|
||||
};
|
||||
|
||||
const getDefaultFormValues = (queryParams: UrlQueryMap, silence?: Silence): SilenceFormFields => {
|
||||
const now = new Date();
|
||||
if (silence) {
|
||||
const isExpired = Date.parse(silence.endsAt) < Date.now();
|
||||
@ -66,12 +88,15 @@ const getDefaultFormValues = (silence?: Silence): SilenceFormFields => {
|
||||
matcherName: '',
|
||||
matcherValue: '',
|
||||
timeZone: DefaultTimeZone,
|
||||
...defaultsFromQuery(queryParams),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const SilencesEditor: FC<Props> = ({ silence, alertManagerSourceName }) => {
|
||||
const formAPI = useForm({ defaultValues: getDefaultFormValues(silence) });
|
||||
const [queryParams] = useQueryParams();
|
||||
const defaultValues = useMemo(() => getDefaultFormValues(queryParams, silence), [silence, queryParams]);
|
||||
const formAPI = useForm({ defaultValues });
|
||||
const dispatch = useDispatch();
|
||||
const styles = useStyles(getStyles);
|
||||
|
||||
|
10
public/app/features/alerting/unified/utils/matchers.ts
Normal file
10
public/app/features/alerting/unified/utils/matchers.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Matcher } from 'app/plugins/datasource/alertmanager/types';
|
||||
import { parseMatcher } from './alertmanager';
|
||||
|
||||
// parses comma separated matchers like "foo=bar,baz=~bad*" into SilenceMatcher[]
|
||||
export function parseQueryParamMatchers(paramValue: string): Matcher[] {
|
||||
return paramValue
|
||||
.split(',')
|
||||
.filter((x) => !!x.trim())
|
||||
.map((x) => parseMatcher(x.trim()));
|
||||
}
|
@ -92,21 +92,12 @@ text-decoration: underline;
|
||||
table[class="body"] .columns {
|
||||
table-layout: fixed !important; float: none !important; width: 100% !important; padding-right: 0px !important; padding-left: 0px !important; display: block !important;
|
||||
}
|
||||
table[class="body"] .column {
|
||||
table-layout: fixed !important; float: none !important; width: 100% !important; padding-right: 0px !important; padding-left: 0px !important; display: block !important;
|
||||
}
|
||||
table[class="body"] table.columns td {
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class="body"] .columns td.four {
|
||||
width: 33.333333% !important;
|
||||
}
|
||||
table[class="body"] .columns td.six {
|
||||
width: 50% !important;
|
||||
}
|
||||
table[class="body"] .columns td.eight {
|
||||
width: 66.666666% !important;
|
||||
}
|
||||
table[class="body"] .columns td.twelve {
|
||||
width: 100% !important;
|
||||
}
|
||||
@ -215,150 +206,127 @@ text-decoration: underline;
|
||||
<td class="mini-centered-text" style="color: #343b41; mso-table-lspace: 0pt; mso-table-rspace: 0pt; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 25px 35px; font: 400 16px/27px 'Helvetica Neue', Helvetica, Arial, sans-serif;" align="center" valign="top">
|
||||
{{Subject .Subject "{{.Title}}"}}
|
||||
|
||||
{{ define "alert" }}
|
||||
{{ if gt (len .Annotations.SortedPairs) 0 }}
|
||||
</td></tr><tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td colspan="2" class="annotations" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 24px 0 12px;" align="left" valign="top">
|
||||
{{ range .Annotations.SortedPairs }}
|
||||
<p style="color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0 0 10px; padding: 0;" align="left">{{ .Name }}: {{ .Value }}</p>
|
||||
{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td valign="top" class="labels-heading" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: bold; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left">Labels:</td>
|
||||
<td style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left" valign="top">
|
||||
<ul class="labels-list" style="font-size: 14px; vertical-align: top;">
|
||||
{{ range .Labels.SortedPairs }}<li>{{ .Name }}: {{ .Value }}</li>{{ end }}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td colspan="2" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left" valign="top">
|
||||
{{ if .SilenceURL }}
|
||||
<a href="{{ .SilenceURL }}" class="button" style="color: #464c54; text-decoration: none; background-color: #f1f5f9; border-radius: 2px; display: inline-block; font-size: 12px; font-weight: bold; margin: 0 10px 0 0; padding: 5px 9px; border: 1px solid #c7d0d9;">
|
||||
<img alt="" height="14" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAF1SURBVHgBrZLNTsJAEMf/2wYTPfEI9Q1qvBgjsEl5gB498gj1SDHpEKUckaMn4eiNFyAp4cJN30CPHrn5BV1noTWlFD3oJNuZ3Z39zUcH+A9pUffJpzAoOO/xuvvprZHooYCgLISoa7FyFSCbdOXuApj6M43GUVXWhYZUpKP3k1NZ14+kAOYChleVjnssK/ezKHrLAkQuZWIVKCgKyW+n55cUciZClzLoUPOiqISVlPB+s6ZulnNN/ihG3GfT84jKOwGvMO0krVEewoBoHeTA2glIhRuno7WzkH0Yc633sCz/CoiVshdYRGxGKYSo9ahgHnEPoqzvdxP1b/sEHtgsF2e12ditDD6gPE59XgIO8ytfTlbM1DiTzjk7WQvEYgllZ5fSXeE7vnfTOdkC1GqOBSFO2Mk22JG1TB4l+1VzX/IQgQJpBaHHsB6bA47+rNOHUI1O4A/zw2YWAaaT8UyPNkdcZ6JUs0P+7eouGXuO3WC7j7/KF29iokiLUdaFAAAAAElFTkSuQmCC" class="button-img" width="14" style="outline: none !important; text-decoration: none !important; -ms-interpolation-mode: bicubic; width: 14px; clear: both; display: block; height: 14px; vertical-align: sub; margin: 0 5px 0 0; border: 0 none;" align="left" />
|
||||
Silence
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ if .Annotations.runbook_url }}
|
||||
<a href="{{ .Annotations.runbook_url }}" class="button" style="color: #464c54; text-decoration: none; background-color: #f1f5f9; border-radius: 2px; display: inline-block; font-size: 12px; font-weight: bold; margin: 0 10px 0 0; padding: 5px 9px; border: 1px solid #c7d0d9;">
|
||||
<img class="button-img" alt="" height="14" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADaSURBVHgBrVNLDoIwFJwq0bjTG+ARvIGeQI/ADdSVARY8oki8jZxEbyDewLUfahttAoEWDM7m9bVvJtN0CrQEyzdENLyjt2RgtoFzjcgl1XTyJw/0T4K8ghmBH8Zz1VhqsaHtVBT7CYwP5KY6tk+xw3k2Kgl0YdmyKrIYvEjB73EqbI+rBC1owMDXGdjws0aqm9MK7Mg7ogE6aInWAqUreLQPanJgdtAgB2YHIgeTuhxUOlBPNcBvKPwFT4RHbnDgLOpNw3EEaxEFblJwIPECZhw8MZAlQkX+C95zCzqWDYrK2AAAAABJRU5ErkJggg==" width="14" style="outline: none !important; text-decoration: none !important; -ms-interpolation-mode: bicubic; width: 14px; clear: both; display: block; height: 14px; vertical-align: sub; margin: 0 5px 0 0; border: 0 none;" align="left" />
|
||||
View Runbook
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ if .DashboardURL}}
|
||||
<a href="{{ .DashboardURL }}" class="button" style="color: #464c54; text-decoration: none; background-color: #f1f5f9; border-radius: 2px; display: inline-block; font-size: 12px; font-weight: bold; margin: 0 10px 0 0; padding: 5px 9px; border: 1px solid #c7d0d9;">
|
||||
<img alt="" height="14" class="button-img" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAE9SURBVHgBrVLNWcMwDH220/bjhEdIR2AC6ASMQEeAU6G9+FLycQojdAUmgE7ACGSEcEybRkj5cUKbnFp9X2JZ8nuypQecaUp+Kxf98BIeJ3cwNxqZDRB89mCTtXuZBvVGwBsCtiUrkYVS8RgHmzeVFB4Lwm9d9Y6XB/EbAhCK7atbbcRfuCjkRNwtt6fs4825RPyli4SkJNA40/wNFCm7cC6sdnnYSdVmQs6Xnla4JjoikDcHmMQYrCSNrI434C7BrA/EXf6Slad0kieY1BPsUKQahcWA5cj7otYTjKG/+/oplQU8oAMx1aKInkbAVL6BJ818ns82wVYHilLnlon4rIOTGeTIWHleB6mq4xfUAfTts1tXPh1YyubfwZGa3HO+K+WWgMeacHBuoOc1m7cr6HSPcvbvpnNhweAS9gdSqGSnoVA2cQAAAABJRU5ErkJggg==" width="14" style="outline: none !important; text-decoration: none !important; -ms-interpolation-mode: bicubic; width: 14px; clear: both; display: block; height: 14px; vertical-align: sub; margin: 0 5px 0 0; border: 0 none;" align="left" />
|
||||
Go to Dashboard
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ if .PanelURL}}
|
||||
<a href="{{ .PanelURL }}" class="button" style="color: #464c54; text-decoration: none; background-color: #f1f5f9; border-radius: 2px; display: inline-block; font-size: 12px; font-weight: bold; margin: 0 10px 0 0; padding: 5px 9px; border: 1px solid #c7d0d9;">
|
||||
<img alt="" class="button-img" height="14" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAE9SURBVHgBrVLNWcMwDH220/bjhEdIR2AC6ASMQEeAU6G9+FLycQojdAUmgE7ACGSEcEybRkj5cUKbnFp9X2JZ8nuypQecaUp+Kxf98BIeJ3cwNxqZDRB89mCTtXuZBvVGwBsCtiUrkYVS8RgHmzeVFB4Lwm9d9Y6XB/EbAhCK7atbbcRfuCjkRNwtt6fs4825RPyli4SkJNA40/wNFCm7cC6sdnnYSdVmQs6Xnla4JjoikDcHmMQYrCSNrI434C7BrA/EXf6Slad0kieY1BPsUKQahcWA5cj7otYTjKG/+/oplQU8oAMx1aKInkbAVL6BJ818ns82wVYHilLnlon4rIOTGeTIWHleB6mq4xfUAfTts1tXPh1YyubfwZGa3HO+K+WWgMeacHBuoOc1m7cr6HSPcvbvpnNhweAS9gdSqGSnoVA2cQAAAABJRU5ErkJggg==" width="14" style="outline: none !important; text-decoration: none !important; -ms-interpolation-mode: bicubic; width: 14px; clear: both; display: block; height: 14px; vertical-align: sub; margin: 0 5px 0 0; border: 0 none;" align="left" />
|
||||
Go to Panel
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ if gt (len .GeneratorURL) 0 }}<a href="{{ .GeneratorURL }}" class="button" style="color: #464c54; text-decoration: none; background-color: #f1f5f9; border-radius: 2px; display: inline-block; font-size: 12px; font-weight: bold; margin: 0 10px 0 0; padding: 5px 9px; border: 1px solid #c7d0d9;">Source</a>{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td colspan="2" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left" valign="top">
|
||||
<div style="height: 24px;"></div>
|
||||
<div style="background-color: #c7d0d9; height: 1px;"></div>
|
||||
<div style="height: 24px;"></div>
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
|
||||
{{ if gt (len .Message) 0 }}
|
||||
{{ .Message }}
|
||||
{{ else }}
|
||||
|
||||
|
||||
|
||||
<table class="row" style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: left; width: 100%; position: relative; display: block; padding: 0px;">
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="wrapper last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; position: relative; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 10px 0px 0px;" align="left" valign="top">
|
||||
<table class="twelve columns" style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: left; width: 580px; margin: 0 auto; padding: 0;">
|
||||
<td class="twelve" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left" valign="top">
|
||||
<table style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: left; padding: 0;">
|
||||
{{ if gt (len .Alerts.Firing) 0 }}
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="center" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="center" valign="top">
|
||||
{{ if gt (len .Alerts.Firing) 0 }}
|
||||
<h3 style="color: #E6522C; font-weight: bold; font-style: italic; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; line-height: 1.3; word-break: normal; font-size: 22px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 10px 0; padding: 0;" align="left">{{.Title}}</h3>
|
||||
{{ else }}
|
||||
<h3 style="font-weight: bold; font-style: italic; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; line-height: 1.3; word-break: normal; font-size: 22px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 10px 0; padding: 0;" align="left">{{.Title}}</h3>
|
||||
{{ end }}
|
||||
<td colspan="2" class="section-heading" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #2c3235; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: bold; line-height: 19px; font-size: 22px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0 0 32px;" align="left" valign="top">
|
||||
Firing: {{ .Alerts.Firing | len }} alert{{ if gt (len .Alerts.Firing) 1 }}s{{ end }}{{ if gt (len .GroupLabels.SortedPairs) 1 }} for
|
||||
{{ range .GroupLabels.SortedPairs }}
|
||||
{{ .Name }}={{ .Value }}
|
||||
{{ end }}{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="row" style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: left; width: 100%; position: relative; display: block; padding: 0px;">
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
{{ if gt (len .Alerts.Firing) 0 }}
|
||||
<td class="alert-warning twelve column last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0 0px 0 0;" align="left" bgcolor="#E6522C" valign="top">
|
||||
{{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for
|
||||
{{ range .GroupLabels.SortedPairs }}
|
||||
{{ .Name }}={{ .Value }}
|
||||
{{ end }}
|
||||
</td>
|
||||
{{ else }}
|
||||
<td class="alert-good twelve column last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0 0px 0 0;" align="left" bgcolor="#68B90F" valign="top">
|
||||
{{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for
|
||||
{{ range .GroupLabels.SortedPairs }}
|
||||
{{ .Name }}={{ .Value }}
|
||||
{{ end }}
|
||||
</td>
|
||||
{{ end }}
|
||||
|
||||
</tr>
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0 0px 0 0;" align="left" valign="top">
|
||||
<table class="twelve columns" style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: left; width: 580px; margin: 0 auto; padding: 0;">
|
||||
{{ if gt (len .Alerts.Firing) 0 }}
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="twelve last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 100%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
<h5 style="font-weight: bold; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; line-height: 1.3; word-break: normal; font-size: 18px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left">({{ .Alerts.Firing | len }}) Firing</h5>
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
{{ range .Alerts.Firing }}
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="four" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 33.333333%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
<h5 style="font-weight: bold; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; line-height: 1.3; word-break: normal; font-size: 18px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left">Labels</h5>
|
||||
</td>
|
||||
<td class="eight last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 66.666666%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
{{ if gt (len .Annotations) 0 }}<h5 style="font-weight: bold; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; line-height: 1.3; word-break: normal; font-size: 18px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left">Annotations</h5>{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="four" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 33.333333%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
{{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}<br />{{ end }}
|
||||
<a href="{{ .GeneratorURL }}" style="color: #E67612; text-decoration: none;">Source</a><br />
|
||||
</td>
|
||||
<td class="eight last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 66.666666%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
{{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}<br />{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="status-tag status-firing" width="68" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #ffffff; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 68px; margin: 0; padding: 4px 8px;" align="center" bgcolor="#e02f44" valign="top">
|
||||
Firing
|
||||
</td>
|
||||
<td class="alert-label" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: bold; line-height: 19px; font-size: 16px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; text-decoration: underline; margin: 0; padding: 0 0 0 12px;" align="left" valign="top">
|
||||
{{ .Labels.alertname }}
|
||||
</td>
|
||||
</tr>
|
||||
{{ template "alert" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ if gt (len .Alerts.Resolved) 0 }}
|
||||
{{ if gt (len .Alerts.Firing) 0 }}
|
||||
{{ end }}
|
||||
{{ if gt (len .Alerts.Resolved) 0 }}
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="twelve" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 100%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
<br />
|
||||
<hr style="color: #d9d9d9; background-color: #d9d9d9; height: 1px; border: none;" />
|
||||
<br />
|
||||
<td colspan="2" class="section-heading" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #2c3235; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: bold; line-height: 19px; font-size: 22px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0 0 32px;" align="left" valign="top">
|
||||
Resolved: {{ .Alerts.Resolved | len }} alert{{ if gt (len .Alerts.Resolved) 1 }}s{{ end }}{{ if gt (len .GroupLabels.SortedPairs) 1 }} for
|
||||
{{ range .GroupLabels.SortedPairs }}
|
||||
{{ .Name }}={{ .Value }}
|
||||
{{ end }}{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="twelve last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 100%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
<h5 style="font-weight: bold; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; line-height: 1.3; word-break: normal; font-size: 18px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left">({{ .Alerts.Resolved | len }}) Resolved</h5>
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
{{ range .Alerts.Resolved }}
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="six" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 50%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
<h5 style="font-weight: bold; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; line-height: 1.3; word-break: normal; font-size: 18px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left">Labels</h5>
|
||||
</td>
|
||||
<td class="six last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 50%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
{{ if gt (len .Annotations) 0 }}<h5 style="font-weight: bold; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; line-height: 1.3; word-break: normal; font-size: 18px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left">Annotations</h5>{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="six" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 50%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
{{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}<br />{{ end }}
|
||||
<a href="{{ .GeneratorURL }}" style="color: #E67612; text-decoration: none;">Source</a><br />
|
||||
</td>
|
||||
<td class="six last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 50%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="left" valign="top">
|
||||
{{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}<br />{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="status-tag status-resolved" width="68" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #ffffff; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 68px; margin: 0; padding: 4px 8px;" align="center" bgcolor="#464c54" valign="top">
|
||||
Resolved
|
||||
</td>
|
||||
<td class="alert-label" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: bold; line-height: 19px; font-size: 16px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; text-decoration: underline; margin: 0; padding: 0 0 0 12px;" align="left" valign="top">
|
||||
{{ .Labels.alertname }}
|
||||
</td>
|
||||
</tr>
|
||||
{{ template "alert" . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td colspan="2" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0;" align="left" valign="top">
|
||||
<a href="{{ .AlertPageUrl }}" class="button" style="color: #464c54; text-decoration: none; background-color: #f1f5f9; border-radius: 2px; display: inline-block; font-size: 12px; font-weight: bold; margin: 0 10px 0 0; padding: 5px 9px; border: 1px solid #c7d0d9;">Go to alerts page</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</td></tr></table>
|
||||
|
||||
|
||||
</table>
|
||||
{{ end }}
|
||||
|
||||
|
||||
|
||||
<table class="row" style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: left; width: 100%; position: relative; display: block; padding: 0px;">
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="wrapper last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; position: relative; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 10px 0px 0px;" align="left" valign="top">
|
||||
<table class="twelve columns" style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: left; width: 580px; margin: 0 auto; padding: 0;">
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="center six" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 50%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="center" valign="top">
|
||||
<table class="better-button" align="center" border="0" cellspacing="0" cellpadding="0" style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: left; margin-top: 10px; margin-bottom: 20px; padding: 0;">
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td align="center" class="better-button" bgcolor="#ff8f2b" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; margin: 0; padding: 0px;" valign="top">
|
||||
<a href="{{.RuleUrl}}" target="_blank" style="color: #FFF; text-decoration: none; -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; display: inline-block; padding: 12px 25px; border: 1px solid #ff8f2b;">View your Alert rule</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="center six" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 50%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" align="center" valign="top">
|
||||
<table class="better-button" align="center" border="0" cellspacing="0" cellpadding="0" style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: left; margin-top: 10px; margin-bottom: 20px; padding: 0;">
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td align="center" class="better-button-alt" bgcolor="#efefef" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; margin: 0; padding: 0px;" valign="top">
|
||||
<a href="{{.AlertPageUrl}}" target="_blank" style="color: #ff8f2b; text-decoration: none; -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; display: inline-block; background-color: #EFEFEF; padding: 12px 25px; border: 1px solid #ff8f2b;"> Go to the Alerts page</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</center></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@ -367,7 +335,7 @@ text-decoration: underline;
|
||||
<td class="wrapper last" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; position: relative; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 10px 20px 0px 0px;" align="left" valign="top">
|
||||
<table class="twelve columns center" style="border-spacing: 0; border-collapse: collapse; vertical-align: top; text-align: center; width: 580px; margin: 0 auto; padding: 0;">
|
||||
<tr style="vertical-align: top; padding: 0;" align="left">
|
||||
<td class="twelve" align="center" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; width: 100%; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" valign="top">
|
||||
<td class="twelve" align="center" style="word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; border-collapse: collapse !important; color: #222222; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0; padding: 0px 0px 10px;" valign="top">
|
||||
<center style="width: 100%; min-width: 580px;">
|
||||
<p style="font-size: 12px; color: #999999; font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; font-weight: normal; line-height: 19px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; margin: 0 0 10px; padding: 0;" align="center">
|
||||
Sent by <a href="{{.AppUrl}}" style="color: #E67612; text-decoration: none;">Grafana v{{.BuildVersion}}</a>
|
||||
@ -381,9 +349,9 @@ text-decoration: underline;
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user