...

Source file src/golang.conradwood.net/go-easyops/prometheus/usage_tracker.go

Documentation: golang.conradwood.net/go-easyops/prometheus

     1  package prometheus
     2  
     3  import (
     4  	"fmt"
     5  	dto "github.com/prometheus/client_model/go"
     6  	"sync"
     7  	"time"
     8  )
     9  
    10  var (
    11  	tlock          sync.Mutex
    12  	tracker_arrays = make(map[string][]*metrictracker)
    13  )
    14  
    15  type metrictracker struct {
    16  	name        string
    17  	labels      map[string]string
    18  	lastUpdated time.Time
    19  }
    20  
    21  func label_map_string(m map[string]string) string {
    22  	s := ""
    23  	for k, v := range m {
    24  		s = s + k + "=" + v + ","
    25  	}
    26  	return s
    27  }
    28  func (p *promRegistry) find_or_create_metric(metricname string, labels map[string]string) *metrictracker {
    29  	tlock.Lock()
    30  	defer tlock.Unlock()
    31  	lms := label_map_string(labels)
    32  	trackers := tracker_arrays[lms]
    33  	for _, t := range trackers {
    34  		if t.name != metricname {
    35  			continue
    36  		}
    37  		if isEqualMap(labels, t.labels) {
    38  			return t
    39  		}
    40  	}
    41  	t := &metrictracker{name: metricname, labels: labels, lastUpdated: time.Now()}
    42  	//	trackers = append(trackers, t)
    43  	tracker_arrays[lms] = append(tracker_arrays[lms], t)
    44  	return t
    45  }
    46  func (p *promRegistry) find_metric(metricname string, labels map[string]string) *metrictracker {
    47  	tlock.Lock()
    48  	defer tlock.Unlock()
    49  	lms := label_map_string(labels)
    50  	trackers := tracker_arrays[lms]
    51  	for _, t := range trackers {
    52  		if t.name != metricname {
    53  			continue
    54  		}
    55  		if isEqualMap(labels, t.labels) {
    56  			return t
    57  		}
    58  	}
    59  	return nil
    60  }
    61  func (m *metrictracker) String() string {
    62  	ls := ""
    63  	deli := ""
    64  	for k, v := range m.labels {
    65  		ls = ls + deli + k + "=\"" + v + "\""
    66  		deli = ","
    67  	}
    68  	return fmt.Sprintf("%s{%s}", m.name, ls)
    69  }
    70  func (m *metrictracker) update() {
    71  	m.lastUpdated = time.Now()
    72  }
    73  
    74  // a metric calls this if it is modified
    75  func (p *promRegistry) used(metricname string, labels map[string]string) {
    76  	p.find_or_create_metric(metricname, labels).update()
    77  }
    78  func (p *promRegistry) recently_used_family(mf *dto.MetricFamily, maxage time.Duration) *dto.MetricFamily {
    79  	var rm []*dto.Metric
    80  	for _, m := range mf.Metric {
    81  		l := make(map[string]string)
    82  		for _, lp := range m.Label {
    83  			l[*lp.Name] = l[*lp.Value]
    84  		}
    85  		mt := p.find_metric(*mf.Name, l)
    86  		if mt == nil {
    87  			// not one that has been added
    88  			rm = append(rm, m)
    89  			continue
    90  		}
    91  		if time.Since(mt.lastUpdated) > maxage {
    92  			//		fmt.Printf("Filtered: %s\n", mt.String())
    93  			continue
    94  		}
    95  		rm = append(rm, m)
    96  	}
    97  	mf.Metric = rm
    98  	return mf
    99  }
   100  
   101  func isEqualMap(a1, a2 map[string]string) bool {
   102  	if a1 == nil && a2 == nil {
   103  		return true
   104  	}
   105  	if a1 == nil || a2 == nil {
   106  		return false
   107  	}
   108  	if len(a1) != len(a2) {
   109  		return false
   110  	}
   111  	for k, v := range a1 {
   112  		if a2[k] != v {
   113  			return false
   114  		}
   115  	}
   116  	return true
   117  }
   118  

View as plain text