github.com/hashicorp/go-metrics@v0.5.3/circonus/circonus.go (about) 1 // Circonus Metrics Sink 2 3 package circonus 4 5 import ( 6 "strings" 7 8 cgm "github.com/circonus-labs/circonus-gometrics" 9 "github.com/hashicorp/go-metrics" 10 ) 11 12 // CirconusSink provides an interface to forward metrics to Circonus with 13 // automatic check creation and metric management 14 type CirconusSink struct { 15 metrics *cgm.CirconusMetrics 16 } 17 18 // Config options for CirconusSink 19 // See https://github.com/circonus-labs/circonus-gometrics for configuration options 20 type Config cgm.Config 21 22 // NewCirconusSink - create new metric sink for circonus 23 // 24 // one of the following must be supplied: 25 // - API Token - search for an existing check or create a new check 26 // - API Token + Check Id - the check identified by check id will be used 27 // - API Token + Check Submission URL - the check identified by the submission url will be used 28 // - Check Submission URL - the check identified by the submission url will be used 29 // metric management will be *disabled* 30 // 31 // Note: If submission url is supplied w/o an api token, the public circonus ca cert will be used 32 // to verify the broker for metrics submission. 33 func NewCirconusSink(cc *Config) (*CirconusSink, error) { 34 cfg := cgm.Config{} 35 if cc != nil { 36 cfg = cgm.Config(*cc) 37 } 38 39 metrics, err := cgm.NewCirconusMetrics(&cfg) 40 if err != nil { 41 return nil, err 42 } 43 44 return &CirconusSink{ 45 metrics: metrics, 46 }, nil 47 } 48 49 // Start submitting metrics to Circonus (flush every SubmitInterval) 50 func (s *CirconusSink) Start() { 51 s.metrics.Start() 52 } 53 54 // Flush manually triggers metric submission to Circonus 55 func (s *CirconusSink) Flush() { 56 s.metrics.Flush() 57 } 58 59 // SetGauge sets value for a gauge metric 60 func (s *CirconusSink) SetGauge(key []string, val float32) { 61 flatKey := s.flattenKey(key) 62 s.metrics.SetGauge(flatKey, int64(val)) 63 } 64 65 // SetGaugeWithLabels sets value for a gauge metric with the given labels 66 func (s *CirconusSink) SetGaugeWithLabels(key []string, val float32, labels []metrics.Label) { 67 flatKey := s.flattenKeyLabels(key, labels) 68 s.metrics.SetGauge(flatKey, int64(val)) 69 } 70 71 // SetPrecisionGauge sets value for a gauge metric with float64 precision 72 func (s *CirconusSink) SetPrecisionGauge(key []string, val float64) { 73 flatKey := s.flattenKey(key) 74 s.metrics.SetGauge(flatKey, val) 75 } 76 77 // SetPrecisionGaugeWithLabels sets value for a gauge metric with the given labels with float64 precision 78 func (s *CirconusSink) SetPrecisionGaugeWithLabels(key []string, val float64, labels []metrics.Label) { 79 flatKey := s.flattenKeyLabels(key, labels) 80 s.metrics.SetGauge(flatKey, val) 81 } 82 83 // EmitKey is not implemented in circonus 84 func (s *CirconusSink) EmitKey(key []string, val float32) { 85 // NOP 86 } 87 88 // IncrCounter increments a counter metric 89 func (s *CirconusSink) IncrCounter(key []string, val float32) { 90 flatKey := s.flattenKey(key) 91 s.metrics.IncrementByValue(flatKey, uint64(val)) 92 } 93 94 // IncrCounterWithLabels increments a counter metric with the given labels 95 func (s *CirconusSink) IncrCounterWithLabels(key []string, val float32, labels []metrics.Label) { 96 flatKey := s.flattenKeyLabels(key, labels) 97 s.metrics.IncrementByValue(flatKey, uint64(val)) 98 } 99 100 // AddSample adds a sample to a histogram metric 101 func (s *CirconusSink) AddSample(key []string, val float32) { 102 flatKey := s.flattenKey(key) 103 s.metrics.RecordValue(flatKey, float64(val)) 104 } 105 106 // AddSampleWithLabels adds a sample to a histogram metric with the given labels 107 func (s *CirconusSink) AddSampleWithLabels(key []string, val float32, labels []metrics.Label) { 108 flatKey := s.flattenKeyLabels(key, labels) 109 s.metrics.RecordValue(flatKey, float64(val)) 110 } 111 112 // Shutdown blocks while flushing metrics to the backend. 113 func (s *CirconusSink) Shutdown() { 114 // The version of circonus metrics in go.mod (v2.3.1), and the current 115 // version (v3.4.6) do not support a shutdown operation. Instead we call 116 // Flush which blocks until metrics are submitted to storage, and then exit 117 // as the README examples do. 118 s.metrics.Flush() 119 } 120 121 // Flattens key to Circonus metric name 122 func (s *CirconusSink) flattenKey(parts []string) string { 123 joined := strings.Join(parts, "`") 124 return strings.Map(func(r rune) rune { 125 switch r { 126 case ' ': 127 return '_' 128 default: 129 return r 130 } 131 }, joined) 132 } 133 134 // Flattens the key along with labels for formatting, removes spaces 135 func (s *CirconusSink) flattenKeyLabels(parts []string, labels []metrics.Label) string { 136 for _, label := range labels { 137 parts = append(parts, label.Value) 138 } 139 return s.flattenKey(parts) 140 }