1// Copyright 2013 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package model 15 16import ( 17 "fmt" 18 "time" 19) 20 21type AlertStatus string 22 23const ( 24 AlertFiring AlertStatus = "firing" 25 AlertResolved AlertStatus = "resolved" 26) 27 28// Alert is a generic representation of an alert in the Prometheus eco-system. 29type Alert struct { 30 // Label value pairs for purpose of aggregation, matching, and disposition 31 // dispatching. This must minimally include an "alertname" label. 32 Labels LabelSet `json:"labels"` 33 34 // Extra key/value information which does not define alert identity. 35 Annotations LabelSet `json:"annotations"` 36 37 // The known time range for this alert. Both ends are optional. 38 StartsAt time.Time `json:"startsAt,omitempty"` 39 EndsAt time.Time `json:"endsAt,omitempty"` 40 GeneratorURL string `json:"generatorURL"` 41} 42 43// Name returns the name of the alert. It is equivalent to the "alertname" label. 44func (a *Alert) Name() string { 45 return string(a.Labels[AlertNameLabel]) 46} 47 48// Fingerprint returns a unique hash for the alert. It is equivalent to 49// the fingerprint of the alert's label set. 50func (a *Alert) Fingerprint() Fingerprint { 51 return a.Labels.Fingerprint() 52} 53 54func (a *Alert) String() string { 55 s := fmt.Sprintf("%s[%s]", a.Name(), a.Fingerprint().String()[:7]) 56 if a.Resolved() { 57 return s + "[resolved]" 58 } 59 return s + "[active]" 60} 61 62// Resolved returns true iff the activity interval ended in the past. 63func (a *Alert) Resolved() bool { 64 return a.ResolvedAt(time.Now()) 65} 66 67// ResolvedAt returns true off the activity interval ended before 68// the given timestamp. 69func (a *Alert) ResolvedAt(ts time.Time) bool { 70 if a.EndsAt.IsZero() { 71 return false 72 } 73 return !a.EndsAt.After(ts) 74} 75 76// Status returns the status of the alert. 77func (a *Alert) Status() AlertStatus { 78 if a.Resolved() { 79 return AlertResolved 80 } 81 return AlertFiring 82} 83 84// Validate checks whether the alert data is inconsistent. 85func (a *Alert) Validate() error { 86 if a.StartsAt.IsZero() { 87 return fmt.Errorf("start time missing") 88 } 89 if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) { 90 return fmt.Errorf("start time must be before end time") 91 } 92 if err := a.Labels.Validate(); err != nil { 93 return fmt.Errorf("invalid label set: %s", err) 94 } 95 if len(a.Labels) == 0 { 96 return fmt.Errorf("at least one label pair required") 97 } 98 if err := a.Annotations.Validate(); err != nil { 99 return fmt.Errorf("invalid annotations: %s", err) 100 } 101 return nil 102} 103 104// Alert is a list of alerts that can be sorted in chronological order. 105type Alerts []*Alert 106 107func (as Alerts) Len() int { return len(as) } 108func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] } 109 110func (as Alerts) Less(i, j int) bool { 111 if as[i].StartsAt.Before(as[j].StartsAt) { 112 return true 113 } 114 if as[i].EndsAt.Before(as[j].EndsAt) { 115 return true 116 } 117 return as[i].Fingerprint() < as[j].Fingerprint() 118} 119 120// HasFiring returns true iff one of the alerts is not resolved. 121func (as Alerts) HasFiring() bool { 122 for _, a := range as { 123 if !a.Resolved() { 124 return true 125 } 126 } 127 return false 128} 129 130// Status returns StatusFiring iff at least one of the alerts is firing. 131func (as Alerts) Status() AlertStatus { 132 if as.HasFiring() { 133 return AlertFiring 134 } 135 return AlertResolved 136} 137