github.com/puellanivis/breton@v0.2.16/lib/metrics/option.go (about)

     1  package metrics
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/prometheus/client_golang/prometheus"
     7  )
     8  
     9  // An Option defines specific optional feature for a Metric. When applied,
    10  // it returns a new Option that will revert the feature to the previous state.
    11  type Option func(m *metric) Option
    12  
    13  // withLabelScope allows for toggling labelScopes directly, and not just
    14  // a list of Labelers to keep enscoping into.
    15  func withLabelScope(labels *labelScope) Option {
    16  	return func(m *metric) Option {
    17  		save := m.labels
    18  
    19  		m.labels = labels
    20  
    21  		return withLabelScope(save)
    22  	}
    23  }
    24  
    25  // WithLabels defines a set of Labels to use for a Metric.
    26  // * Label: a Label with the given name, no default.
    27  // * Label.WithValue: a Label with the given name, and default value.
    28  // * Label.Const; a Label with the given name, and a constant value.
    29  func WithLabels(labels ...Labeler) Option {
    30  	return func(m *metric) Option {
    31  		save := m.labels
    32  
    33  		if save == nil {
    34  			m.labels = defineLabels(labels...)
    35  
    36  		} else {
    37  			m.labels = m.labels.With(labels...)
    38  		}
    39  
    40  		return withLabelScope(save)
    41  	}
    42  }
    43  
    44  // WithRegistry defines the Registry to which a Metric will be registered.
    45  // By default, every Metric will be registered with the default prometheus.Registery.
    46  func WithRegistry(registry *prometheus.Registry) Option {
    47  	return func(m *metric) Option {
    48  		save := m.registry
    49  
    50  		m.registry = registry
    51  
    52  		return WithRegistry(save)
    53  	}
    54  }
    55  
    56  // LinearBuckets defines a series of linear buckets defined by:
    57  //
    58  //	for i from 0 to count: a_i = start + width × i
    59  //
    60  // (Caller MUST NOT pass a count <= 0)
    61  func LinearBuckets(start, width float64, count uint) Option {
    62  	return WithBuckets(prometheus.LinearBuckets(start, width, int(count))...)
    63  }
    64  
    65  // ExponentialBuckets defines a series of exponential buckets defined by:
    66  //
    67  //	for i from 0 to count: a_i = start × factor^i
    68  //
    69  // (Caller MUST NOT pass a count <= 0, start <= 0, or factor <= 1)
    70  func ExponentialBuckets(start, factor float64, count uint) Option {
    71  	return WithBuckets(prometheus.ExponentialBuckets(start, factor, int(count))...)
    72  }
    73  
    74  // WithBuckets defines the buckets into which observations are counted. Each
    75  // element in the slice is the upper inclusive bound of a bucket.
    76  //
    77  // (Caller MUST ensure that the buckets are defined in increasing order.)
    78  //
    79  // (Caller MUST not include the highest +Inf bucket boundary, it is added
    80  // implicity.)
    81  func WithBuckets(buckets ...float64) Option {
    82  	return func(m *metric) Option {
    83  		if m.histogramSettings == nil {
    84  			panic("metric is not a histogram")
    85  		}
    86  
    87  		save := m.histogramSettings.buckets
    88  
    89  		m.histogramSettings.buckets = buckets
    90  
    91  		return WithBuckets(save...)
    92  	}
    93  
    94  }
    95  
    96  // WithObjectives defines the quantile rank estimates with their respective
    97  // absolute error. If Objectives[q] = e, then the value reported for q will be
    98  // the φ-quantile value for some φ in the range q±e.
    99  // The default is to have no Objectives.
   100  // For a common case of 50-90-99th percentiles, use CommonObjectives
   101  func WithObjectives(objectives map[float64]float64) Option {
   102  	return func(m *metric) Option {
   103  		if m.summarySettings == nil {
   104  			panic("metric is not a summary")
   105  		}
   106  
   107  		save := m.objectives
   108  
   109  		m.objectives = objectives
   110  
   111  		return WithObjectives(save)
   112  	}
   113  }
   114  
   115  var (
   116  	commonObjectives = map[float64]float64{
   117  		0.5:  0.05,
   118  		0.9:  0.01,
   119  		0.99: 0.001,
   120  	}
   121  )
   122  
   123  // CommonObjectives defines a common set of Objectives, which track the
   124  // percentiles: 50±5 (the median), 90±1, and 99±0.1
   125  // By default, a Summary will not have any Objectives.
   126  func CommonObjectives() Option {
   127  	return WithObjectives(commonObjectives)
   128  }
   129  
   130  // WithMaxAge defines the duration for which an observation stays relevant
   131  // for the summary. Must be positive.
   132  func WithMaxAge(value time.Duration) Option {
   133  	if value <= 0 {
   134  		panic("value for maximum age must be positive")
   135  	}
   136  
   137  	return func(m *metric) Option {
   138  		if m.summarySettings == nil {
   139  			panic("metric is not a summary")
   140  		}
   141  
   142  		save := m.summarySettings.maxAge
   143  
   144  		m.summarySettings.maxAge = value
   145  
   146  		return WithMaxAge(save)
   147  	}
   148  }
   149  
   150  // WithAgeBuckets is the number of buckets used to exclude observations that
   151  // are older than MaxAge from the summary. A higher number has a resource
   152  // penalty, so only increase it if the higher resolution is really required.
   153  // For very high observation rates, you might want to reduce the number of
   154  // age buckets. With only one age bucket, you will effectively see a complete
   155  // reset of the summary each time MaxAge has passed.
   156  func WithAgeBuckets(value uint32) Option {
   157  	return func(m *metric) Option {
   158  		if m.summarySettings == nil {
   159  			panic("metric is not a summary")
   160  		}
   161  
   162  		save := m.summarySettings.ageBuckets
   163  
   164  		m.summarySettings.ageBuckets = value
   165  
   166  		return WithAgeBuckets(save)
   167  	}
   168  }
   169  
   170  // WithBufCap deifnes the default sample stream buffer size. The default value
   171  // should suffice for most users. If there is a need to increase the value,
   172  // a multiple of 500 is recommended (because that is the internal buffer size
   173  // of the underlying package "github.com/bmizerany/perks/quantile")
   174  //
   175  // This Option exposes implementation details, which is undesirable.
   176  func WithBufCap(value uint32) Option {
   177  	return func(m *metric) Option {
   178  		if m.summarySettings == nil {
   179  			panic("metric is not a summary")
   180  		}
   181  
   182  		save := m.summarySettings.bufCap
   183  
   184  		m.summarySettings.bufCap = value
   185  
   186  		return WithBufCap(save)
   187  	}
   188  }