...

Source file src/github.com/prometheus/alertmanager/store/store.go

Documentation: github.com/prometheus/alertmanager/store

     1  // Copyright 2018 Prometheus Team
     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 store
    15  
    16  import (
    17  	"context"
    18  	"errors"
    19  	"sync"
    20  	"time"
    21  
    22  	"github.com/prometheus/common/model"
    23  
    24  	"github.com/prometheus/alertmanager/types"
    25  )
    26  
    27  // ErrNotFound is returned if a Store cannot find the Alert.
    28  var ErrNotFound = errors.New("alert not found")
    29  
    30  // Alerts provides lock-coordinated to an in-memory map of alerts, keyed by
    31  // their fingerprint. Resolved alerts are removed from the map based on
    32  // gcInterval. An optional callback can be set which receives a slice of all
    33  // resolved alerts that have been removed.
    34  type Alerts struct {
    35  	sync.Mutex
    36  	c  map[model.Fingerprint]*types.Alert
    37  	cb func([]*types.Alert)
    38  }
    39  
    40  // NewAlerts returns a new Alerts struct.
    41  func NewAlerts() *Alerts {
    42  	a := &Alerts{
    43  		c:  make(map[model.Fingerprint]*types.Alert),
    44  		cb: func(_ []*types.Alert) {},
    45  	}
    46  
    47  	return a
    48  }
    49  
    50  // SetGCCallback sets a GC callback to be executed after each GC.
    51  func (a *Alerts) SetGCCallback(cb func([]*types.Alert)) {
    52  	a.Lock()
    53  	defer a.Unlock()
    54  
    55  	a.cb = cb
    56  }
    57  
    58  // Run starts the GC loop. The interval must be greater than zero; if not, the function will panic.
    59  func (a *Alerts) Run(ctx context.Context, interval time.Duration) {
    60  	t := time.NewTicker(interval)
    61  	defer t.Stop()
    62  	for {
    63  		select {
    64  		case <-ctx.Done():
    65  			return
    66  		case <-t.C:
    67  			a.gc()
    68  		}
    69  	}
    70  }
    71  
    72  func (a *Alerts) gc() {
    73  	a.Lock()
    74  	defer a.Unlock()
    75  
    76  	var resolved []*types.Alert
    77  	for fp, alert := range a.c {
    78  		if alert.Resolved() {
    79  			delete(a.c, fp)
    80  			resolved = append(resolved, alert)
    81  		}
    82  	}
    83  	a.cb(resolved)
    84  }
    85  
    86  // Get returns the Alert with the matching fingerprint, or an error if it is
    87  // not found.
    88  func (a *Alerts) Get(fp model.Fingerprint) (*types.Alert, error) {
    89  	a.Lock()
    90  	defer a.Unlock()
    91  
    92  	alert, prs := a.c[fp]
    93  	if !prs {
    94  		return nil, ErrNotFound
    95  	}
    96  	return alert, nil
    97  }
    98  
    99  // Set unconditionally sets the alert in memory.
   100  func (a *Alerts) Set(alert *types.Alert) error {
   101  	a.Lock()
   102  	defer a.Unlock()
   103  
   104  	a.c[alert.Fingerprint()] = alert
   105  	return nil
   106  }
   107  
   108  // Delete removes the Alert with the matching fingerprint from the store.
   109  func (a *Alerts) Delete(fp model.Fingerprint) error {
   110  	a.Lock()
   111  	defer a.Unlock()
   112  
   113  	delete(a.c, fp)
   114  	return nil
   115  }
   116  
   117  // List returns a slice of Alerts currently held in memory.
   118  func (a *Alerts) List() []*types.Alert {
   119  	a.Lock()
   120  	defer a.Unlock()
   121  
   122  	alerts := make([]*types.Alert, 0, len(a.c))
   123  	for _, alert := range a.c {
   124  		alerts = append(alerts, alert)
   125  	}
   126  
   127  	return alerts
   128  }
   129  
   130  // Empty returns true if the store is empty.
   131  func (a *Alerts) Empty() bool {
   132  	a.Lock()
   133  	defer a.Unlock()
   134  
   135  	return len(a.c) == 0
   136  }
   137  

View as plain text