github.com/mhutchinson/trillian@v1.2.1/monitoring/inert.go (about)

     1  // Copyright 2017 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package monitoring
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  	"sync"
    21  
    22  	"github.com/golang/glog"
    23  )
    24  
    25  // InertMetricFactory creates inert metrics for testing.
    26  type InertMetricFactory struct{}
    27  
    28  // NewCounter creates a new inert Counter.
    29  func (imf InertMetricFactory) NewCounter(name, help string, labelNames ...string) Counter {
    30  	return &InertFloat{
    31  		labelCount: len(labelNames),
    32  		vals:       make(map[string]float64),
    33  	}
    34  }
    35  
    36  // NewGauge creates a new inert Gauge.
    37  func (imf InertMetricFactory) NewGauge(name, help string, labelNames ...string) Gauge {
    38  	return &InertFloat{
    39  		labelCount: len(labelNames),
    40  		vals:       make(map[string]float64),
    41  	}
    42  }
    43  
    44  // NewHistogram creates a new inert Histogram.
    45  func (imf InertMetricFactory) NewHistogram(name, help string, labelNames ...string) Histogram {
    46  	return &InertDistribution{
    47  		labelCount: len(labelNames),
    48  		counts:     make(map[string]uint64),
    49  		sums:       make(map[string]float64),
    50  	}
    51  }
    52  
    53  // InertFloat is an internal-only implementation of both the Counter and Gauge interfaces.
    54  type InertFloat struct {
    55  	labelCount int
    56  	mu         sync.Mutex
    57  	vals       map[string]float64
    58  }
    59  
    60  // Inc adds 1 to the value.
    61  func (m *InertFloat) Inc(labelVals ...string) {
    62  	m.Add(1.0, labelVals...)
    63  }
    64  
    65  // Dec subtracts 1 from the value.
    66  func (m *InertFloat) Dec(labelVals ...string) {
    67  	m.Add(-1.0, labelVals...)
    68  }
    69  
    70  // Add adds the given amount to the value.
    71  func (m *InertFloat) Add(val float64, labelVals ...string) {
    72  	m.mu.Lock()
    73  	defer m.mu.Unlock()
    74  	key, err := keyForLabels(labelVals, m.labelCount)
    75  	if err != nil {
    76  		glog.Error(err.Error())
    77  		return
    78  	}
    79  	m.vals[key] += val
    80  }
    81  
    82  // Set sets the value.
    83  func (m *InertFloat) Set(val float64, labelVals ...string) {
    84  	m.mu.Lock()
    85  	defer m.mu.Unlock()
    86  	key, err := keyForLabels(labelVals, m.labelCount)
    87  	if err != nil {
    88  		glog.Error(err.Error())
    89  		return
    90  	}
    91  	m.vals[key] = val
    92  }
    93  
    94  // Value returns the current value.
    95  func (m *InertFloat) Value(labelVals ...string) float64 {
    96  	m.mu.Lock()
    97  	defer m.mu.Unlock()
    98  	key, err := keyForLabels(labelVals, m.labelCount)
    99  	if err != nil {
   100  		glog.Error(err.Error())
   101  		return 0.0
   102  	}
   103  	return m.vals[key]
   104  }
   105  
   106  // InertDistribution is an internal-only implementation of the Distribution interface.
   107  type InertDistribution struct {
   108  	labelCount int
   109  	mu         sync.Mutex
   110  	counts     map[string]uint64
   111  	sums       map[string]float64
   112  }
   113  
   114  // Observe adds a single observation to the distribution.
   115  func (m *InertDistribution) Observe(val float64, labelVals ...string) {
   116  	m.mu.Lock()
   117  	defer m.mu.Unlock()
   118  	key, err := keyForLabels(labelVals, m.labelCount)
   119  	if err != nil {
   120  		glog.Error(err.Error())
   121  		return
   122  	}
   123  	m.counts[key]++
   124  	m.sums[key] += val
   125  }
   126  
   127  // Info returns count, sum for the distribution.
   128  func (m *InertDistribution) Info(labelVals ...string) (uint64, float64) {
   129  	m.mu.Lock()
   130  	defer m.mu.Unlock()
   131  	key, err := keyForLabels(labelVals, m.labelCount)
   132  	if err != nil {
   133  		glog.Error(err.Error())
   134  		return 0, 0.0
   135  	}
   136  	return m.counts[key], m.sums[key]
   137  }
   138  
   139  func keyForLabels(labelVals []string, count int) (string, error) {
   140  	if len(labelVals) != count {
   141  		return "", fmt.Errorf("invalid label count %d; want %d", len(labelVals), count)
   142  	}
   143  	return strings.Join(labelVals, "|"), nil
   144  }