diff --git a/main.go b/main.go index 10d847897b..abd0e6a18e 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ package main import ( + "flag" "log" "github.com/prometheus/alert_manager/manager" @@ -22,6 +23,8 @@ import ( ) func main() { + flag.Parse() + log.Print("Starting event suppressor...") suppressor := manager.NewSuppressor() defer suppressor.Close() diff --git a/manager/aggregator.go b/manager/aggregator.go index f158cb0152..22dab706ad 100644 --- a/manager/aggregator.go +++ b/manager/aggregator.go @@ -20,6 +20,7 @@ import ( ) const ( + minimumRepeatRate = 5 * time.Minute minimumRefreshPeriod = 5 * time.Minute notificationRetryPeriod = 1 * time.Minute ) @@ -172,11 +173,10 @@ func (a *Aggregator) aggregate(req *aggregateEventsRequest, s SummaryReceiver) { return } log.Println("aggregating", *req) - for _, element := range req.Events { + for _, event := range req.Events { for _, r := range a.Rules { - log.Println("Checking rule", r, r.Handles(element)) - if r.Handles(element) { - fp := element.Fingerprint() + if r.Handles(event) { + fp := event.Fingerprint() aggregation, ok := a.Aggregates[fp] if !ok { expTimer := time.AfterFunc(minimumRefreshPeriod, func() { @@ -192,7 +192,7 @@ func (a *Aggregator) aggregate(req *aggregateEventsRequest, s SummaryReceiver) { a.Aggregates[fp] = aggregation } - aggregation.Ingest(element) + aggregation.Ingest(event) aggregation.SendNotification(s) break } @@ -213,6 +213,13 @@ type aggregatorResetRulesRequest struct { func (a *Aggregator) replaceRules(r *aggregatorResetRulesRequest) { log.Println("Replacing", len(r.Rules), "aggregator rules...") + + for _, rule := range r.Rules { + if rule.RepeatRate < minimumRepeatRate { + log.Println("Rule repeat rate too low, setting to minimum value") + rule.RepeatRate = minimumRepeatRate + } + } a.Rules = r.Rules r.Response <- new(aggregatorResetRulesResponse) diff --git a/web/helpers.go b/web/helpers.go new file mode 100644 index 0000000000..ac5b6659ab --- /dev/null +++ b/web/helpers.go @@ -0,0 +1,27 @@ +// Copyright 2013 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package web + +import ( + "html/template" + "time" +) + +func timeSince(t time.Time) string { + return time.Now().Round(time.Second / 10).Sub(t.Round(time.Second / 10)).String() +} + +var webHelpers = template.FuncMap{ + "timeSince": timeSince, +} diff --git a/web/static/css/default.css b/web/static/css/default.css index 3af5ad33d2..2eb08a8a72 100644 --- a/web/static/css/default.css +++ b/web/static/css/default.css @@ -1,3 +1,15 @@ body { padding-top: 60px; } + +#create_silence_modal th { + text-align: left; +} + +.add_silence_form { + display: inline; +} + +.del_label_button { + margin-bottom: 10px; +} diff --git a/web/static/js/alerts.js b/web/static/js/alerts.js new file mode 100644 index 0000000000..a821362d4f --- /dev/null +++ b/web/static/js/alerts.js @@ -0,0 +1,49 @@ +function clearSilenceLabels() { + $("#silence_label_table").empty(); +} + +function addSilenceLabel(label, value) { + if (!label) { + label = ""; + } + if (!value) { + value = ""; + } + $("#silence_label_table").append( + '