mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
3.7 KiB
136 lines
3.7 KiB
// Copyright 2013 The Prometheus Authors |
|
// 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 model |
|
|
|
import ( |
|
"fmt" |
|
"time" |
|
) |
|
|
|
type AlertStatus string |
|
|
|
const ( |
|
AlertFiring AlertStatus = "firing" |
|
AlertResolved AlertStatus = "resolved" |
|
) |
|
|
|
// Alert is a generic representation of an alert in the Prometheus eco-system. |
|
type Alert struct { |
|
// Label value pairs for purpose of aggregation, matching, and disposition |
|
// dispatching. This must minimally include an "alertname" label. |
|
Labels LabelSet `json:"labels"` |
|
|
|
// Extra key/value information which does not define alert identity. |
|
Annotations LabelSet `json:"annotations"` |
|
|
|
// The known time range for this alert. Both ends are optional. |
|
StartsAt time.Time `json:"startsAt,omitempty"` |
|
EndsAt time.Time `json:"endsAt,omitempty"` |
|
GeneratorURL string `json:"generatorURL"` |
|
} |
|
|
|
// Name returns the name of the alert. It is equivalent to the "alertname" label. |
|
func (a *Alert) Name() string { |
|
return string(a.Labels[AlertNameLabel]) |
|
} |
|
|
|
// Fingerprint returns a unique hash for the alert. It is equivalent to |
|
// the fingerprint of the alert's label set. |
|
func (a *Alert) Fingerprint() Fingerprint { |
|
return a.Labels.Fingerprint() |
|
} |
|
|
|
func (a *Alert) String() string { |
|
s := fmt.Sprintf("%s[%s]", a.Name(), a.Fingerprint().String()[:7]) |
|
if a.Resolved() { |
|
return s + "[resolved]" |
|
} |
|
return s + "[active]" |
|
} |
|
|
|
// Resolved returns true iff the activity interval ended in the past. |
|
func (a *Alert) Resolved() bool { |
|
return a.ResolvedAt(time.Now()) |
|
} |
|
|
|
// ResolvedAt returns true off the activity interval ended before |
|
// the given timestamp. |
|
func (a *Alert) ResolvedAt(ts time.Time) bool { |
|
if a.EndsAt.IsZero() { |
|
return false |
|
} |
|
return !a.EndsAt.After(ts) |
|
} |
|
|
|
// Status returns the status of the alert. |
|
func (a *Alert) Status() AlertStatus { |
|
if a.Resolved() { |
|
return AlertResolved |
|
} |
|
return AlertFiring |
|
} |
|
|
|
// Validate checks whether the alert data is inconsistent. |
|
func (a *Alert) Validate() error { |
|
if a.StartsAt.IsZero() { |
|
return fmt.Errorf("start time missing") |
|
} |
|
if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) { |
|
return fmt.Errorf("start time must be before end time") |
|
} |
|
if err := a.Labels.Validate(); err != nil { |
|
return fmt.Errorf("invalid label set: %s", err) |
|
} |
|
if len(a.Labels) == 0 { |
|
return fmt.Errorf("at least one label pair required") |
|
} |
|
if err := a.Annotations.Validate(); err != nil { |
|
return fmt.Errorf("invalid annotations: %s", err) |
|
} |
|
return nil |
|
} |
|
|
|
// Alert is a list of alerts that can be sorted in chronological order. |
|
type Alerts []*Alert |
|
|
|
func (as Alerts) Len() int { return len(as) } |
|
func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] } |
|
|
|
func (as Alerts) Less(i, j int) bool { |
|
if as[i].StartsAt.Before(as[j].StartsAt) { |
|
return true |
|
} |
|
if as[i].EndsAt.Before(as[j].EndsAt) { |
|
return true |
|
} |
|
return as[i].Fingerprint() < as[j].Fingerprint() |
|
} |
|
|
|
// HasFiring returns true iff one of the alerts is not resolved. |
|
func (as Alerts) HasFiring() bool { |
|
for _, a := range as { |
|
if !a.Resolved() { |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
// Status returns StatusFiring iff at least one of the alerts is firing. |
|
func (as Alerts) Status() AlertStatus { |
|
if as.HasFiring() { |
|
return AlertFiring |
|
} |
|
return AlertResolved |
|
}
|
|
|