github.com/hashicorp/go-metrics@v0.5.3/sink.go (about) 1 package metrics 2 3 import ( 4 "fmt" 5 "net/url" 6 ) 7 8 // The MetricSink interface is used to transmit metrics information 9 // to an external system 10 type MetricSink interface { 11 // A Gauge should retain the last value it is set to 12 SetGauge(key []string, val float32) 13 SetGaugeWithLabels(key []string, val float32, labels []Label) 14 15 // Should emit a Key/Value pair for each call 16 EmitKey(key []string, val float32) 17 18 // Counters should accumulate values 19 IncrCounter(key []string, val float32) 20 IncrCounterWithLabels(key []string, val float32, labels []Label) 21 22 // Samples are for timing information, where quantiles are used 23 AddSample(key []string, val float32) 24 AddSampleWithLabels(key []string, val float32, labels []Label) 25 } 26 27 // PrecisionGaugeMetricSink interfae is used to support 64 bit precisions for Sinks, if needed. 28 type PrecisionGaugeMetricSink interface { 29 SetPrecisionGauge(key []string, val float64) 30 SetPrecisionGaugeWithLabels(key []string, val float64, labels []Label) 31 } 32 33 type ShutdownSink interface { 34 MetricSink 35 36 // Shutdown the metric sink, flush metrics to storage, and cleanup resources. 37 // Called immediately prior to application exit. Implementations must block 38 // until metrics are flushed to storage. 39 Shutdown() 40 } 41 42 // BlackholeSink is used to just blackhole messages 43 type BlackholeSink struct{} 44 45 func (*BlackholeSink) SetGauge(key []string, val float32) {} 46 func (*BlackholeSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {} 47 func (*BlackholeSink) SetPrecisionGauge(key []string, val float64) {} 48 func (*BlackholeSink) SetPrecisionGaugeWithLabels(key []string, val float64, labels []Label) {} 49 func (*BlackholeSink) EmitKey(key []string, val float32) {} 50 func (*BlackholeSink) IncrCounter(key []string, val float32) {} 51 func (*BlackholeSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {} 52 func (*BlackholeSink) AddSample(key []string, val float32) {} 53 func (*BlackholeSink) AddSampleWithLabels(key []string, val float32, labels []Label) {} 54 55 // FanoutSink is used to sink to fanout values to multiple sinks 56 type FanoutSink []MetricSink 57 58 func (fh FanoutSink) SetGauge(key []string, val float32) { 59 fh.SetGaugeWithLabels(key, val, nil) 60 } 61 62 func (fh FanoutSink) SetGaugeWithLabels(key []string, val float32, labels []Label) { 63 for _, s := range fh { 64 s.SetGaugeWithLabels(key, val, labels) 65 } 66 } 67 68 func (fh FanoutSink) SetPrecisionGauge(key []string, val float64) { 69 fh.SetPrecisionGaugeWithLabels(key, val, nil) 70 } 71 72 func (fh FanoutSink) SetPrecisionGaugeWithLabels(key []string, val float64, labels []Label) { 73 for _, s := range fh { 74 // The Sink needs to implement PrecisionGaugeMetricSink, in case it doesn't, the metric value won't be set and ingored instead 75 if s64, ok := s.(PrecisionGaugeMetricSink); ok { 76 s64.SetPrecisionGaugeWithLabels(key, val, labels) 77 } 78 } 79 } 80 81 func (fh FanoutSink) EmitKey(key []string, val float32) { 82 for _, s := range fh { 83 s.EmitKey(key, val) 84 } 85 } 86 87 func (fh FanoutSink) IncrCounter(key []string, val float32) { 88 fh.IncrCounterWithLabels(key, val, nil) 89 } 90 91 func (fh FanoutSink) IncrCounterWithLabels(key []string, val float32, labels []Label) { 92 for _, s := range fh { 93 s.IncrCounterWithLabels(key, val, labels) 94 } 95 } 96 97 func (fh FanoutSink) AddSample(key []string, val float32) { 98 fh.AddSampleWithLabels(key, val, nil) 99 } 100 101 func (fh FanoutSink) AddSampleWithLabels(key []string, val float32, labels []Label) { 102 for _, s := range fh { 103 s.AddSampleWithLabels(key, val, labels) 104 } 105 } 106 107 func (fh FanoutSink) Shutdown() { 108 for _, s := range fh { 109 if ss, ok := s.(ShutdownSink); ok { 110 ss.Shutdown() 111 } 112 } 113 } 114 115 // sinkURLFactoryFunc is an generic interface around the *SinkFromURL() function provided 116 // by each sink type 117 type sinkURLFactoryFunc func(*url.URL) (MetricSink, error) 118 119 // sinkRegistry supports the generic NewMetricSink function by mapping URL 120 // schemes to metric sink factory functions 121 var sinkRegistry = map[string]sinkURLFactoryFunc{ 122 "statsd": NewStatsdSinkFromURL, 123 "statsite": NewStatsiteSinkFromURL, 124 "inmem": NewInmemSinkFromURL, 125 } 126 127 // NewMetricSinkFromURL allows a generic URL input to configure any of the 128 // supported sinks. The scheme of the URL identifies the type of the sink, the 129 // and query parameters are used to set options. 130 // 131 // "statsd://" - Initializes a StatsdSink. The host and port are passed through 132 // as the "addr" of the sink 133 // 134 // "statsite://" - Initializes a StatsiteSink. The host and port become the 135 // "addr" of the sink 136 // 137 // "inmem://" - Initializes an InmemSink. The host and port are ignored. The 138 // "interval" and "duration" query parameters must be specified with valid 139 // durations, see NewInmemSink for details. 140 func NewMetricSinkFromURL(urlStr string) (MetricSink, error) { 141 u, err := url.Parse(urlStr) 142 if err != nil { 143 return nil, err 144 } 145 146 sinkURLFactoryFunc := sinkRegistry[u.Scheme] 147 if sinkURLFactoryFunc == nil { 148 return nil, fmt.Errorf( 149 "cannot create metric sink, unrecognized sink name: %q", u.Scheme) 150 } 151 152 return sinkURLFactoryFunc(u) 153 }