github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/prometheus/common/model/alert.go (about)

     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  
    14  package model
    15  
    16  import (
    17  	"fmt"
    18  	"time"
    19  )
    20  
    21  type AlertStatus string
    22  
    23  const (
    24  	AlertFiring   AlertStatus = "firing"
    25  	AlertResolved AlertStatus = "resolved"
    26  )
    27  
    28  // Alert is a generic representation of an alert in the Prometheus eco-system.
    29  type 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.
    44  func (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.
    50  func (a *Alert) Fingerprint() Fingerprint {
    51  	return a.Labels.Fingerprint()
    52  }
    53  
    54  func (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.
    63  func (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.
    69  func (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.
    77  func (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.
    85  func (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.
   105  type Alerts []*Alert
   106  
   107  func (as Alerts) Len() int      { return len(as) }
   108  func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] }
   109  
   110  func (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.
   121  func (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.
   131  func (as Alerts) Status() AlertStatus {
   132  	if as.HasFiring() {
   133  		return AlertFiring
   134  	}
   135  	return AlertResolved
   136  }