...

Source file src/github.com/prometheus/common/model/alert.go

Documentation: github.com/prometheus/common/model

     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  	return a.StatusAt(time.Now())
    79  }
    80  
    81  // StatusAt returns the status of the alert at the given timestamp.
    82  func (a *Alert) StatusAt(ts time.Time) AlertStatus {
    83  	if a.ResolvedAt(ts) {
    84  		return AlertResolved
    85  	}
    86  	return AlertFiring
    87  }
    88  
    89  // Validate checks whether the alert data is inconsistent.
    90  func (a *Alert) Validate() error {
    91  	if a.StartsAt.IsZero() {
    92  		return fmt.Errorf("start time missing")
    93  	}
    94  	if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) {
    95  		return fmt.Errorf("start time must be before end time")
    96  	}
    97  	if err := a.Labels.Validate(); err != nil {
    98  		return fmt.Errorf("invalid label set: %w", err)
    99  	}
   100  	if len(a.Labels) == 0 {
   101  		return fmt.Errorf("at least one label pair required")
   102  	}
   103  	if err := a.Annotations.Validate(); err != nil {
   104  		return fmt.Errorf("invalid annotations: %w", err)
   105  	}
   106  	return nil
   107  }
   108  
   109  // Alert is a list of alerts that can be sorted in chronological order.
   110  type Alerts []*Alert
   111  
   112  func (as Alerts) Len() int      { return len(as) }
   113  func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] }
   114  
   115  func (as Alerts) Less(i, j int) bool {
   116  	if as[i].StartsAt.Before(as[j].StartsAt) {
   117  		return true
   118  	}
   119  	if as[i].EndsAt.Before(as[j].EndsAt) {
   120  		return true
   121  	}
   122  	return as[i].Fingerprint() < as[j].Fingerprint()
   123  }
   124  
   125  // HasFiring returns true iff one of the alerts is not resolved.
   126  func (as Alerts) HasFiring() bool {
   127  	for _, a := range as {
   128  		if !a.Resolved() {
   129  			return true
   130  		}
   131  	}
   132  	return false
   133  }
   134  
   135  // HasFiringAt returns true iff one of the alerts is not resolved
   136  // at the time ts.
   137  func (as Alerts) HasFiringAt(ts time.Time) bool {
   138  	for _, a := range as {
   139  		if !a.ResolvedAt(ts) {
   140  			return true
   141  		}
   142  	}
   143  	return false
   144  }
   145  
   146  // Status returns StatusFiring iff at least one of the alerts is firing.
   147  func (as Alerts) Status() AlertStatus {
   148  	if as.HasFiring() {
   149  		return AlertFiring
   150  	}
   151  	return AlertResolved
   152  }
   153  
   154  // StatusAt returns StatusFiring iff at least one of the alerts is firing
   155  // at the time ts.
   156  func (as Alerts) StatusAt(ts time.Time) AlertStatus {
   157  	if as.HasFiringAt(ts) {
   158  		return AlertFiring
   159  	}
   160  	return AlertResolved
   161  }
   162  

View as plain text