github.com/hashicorp/go-metrics@v0.5.3/start.go (about) 1 package metrics 2 3 import ( 4 "os" 5 "sync" 6 "sync/atomic" 7 "time" 8 9 iradix "github.com/hashicorp/go-immutable-radix" 10 ) 11 12 // Config is used to configure metrics settings 13 type Config struct { 14 ServiceName string // Prefixed with keys to separate services 15 HostName string // Hostname to use. If not provided and EnableHostname, it will be os.Hostname 16 EnableHostname bool // Enable prefixing gauge values with hostname 17 EnableHostnameLabel bool // Enable adding hostname to labels 18 EnableServiceLabel bool // Enable adding service to labels 19 EnableRuntimeMetrics bool // Enables profiling of runtime metrics (GC, Goroutines, Memory) 20 EnableTypePrefix bool // Prefixes key with a type ("counter", "gauge", "timer") 21 TimerGranularity time.Duration // Granularity of timers. 22 ProfileInterval time.Duration // Interval to profile runtime metrics 23 24 AllowedPrefixes []string // A list of metric prefixes to allow, with '.' as the separator 25 BlockedPrefixes []string // A list of metric prefixes to block, with '.' as the separator 26 AllowedLabels []string // A list of metric labels to allow, with '.' as the separator 27 BlockedLabels []string // A list of metric labels to block, with '.' as the separator 28 FilterDefault bool // Whether to allow metrics by default 29 } 30 31 // Metrics represents an instance of a metrics sink that can 32 // be used to emit 33 type Metrics struct { 34 Config 35 lastNumGC uint32 36 sink MetricSink 37 filter *iradix.Tree 38 allowedLabels map[string]bool 39 blockedLabels map[string]bool 40 filterLock sync.RWMutex // Lock filters and allowedLabels/blockedLabels access 41 } 42 43 // Shared global metrics instance 44 var globalMetrics atomic.Value // *Metrics 45 46 func init() { 47 // Initialize to a blackhole sink to avoid errors 48 globalMetrics.Store(&Metrics{sink: &BlackholeSink{}}) 49 } 50 51 // Default returns the shared global metrics instance. 52 func Default() *Metrics { 53 return globalMetrics.Load().(*Metrics) 54 } 55 56 // DefaultConfig provides a sane default configuration 57 func DefaultConfig(serviceName string) *Config { 58 c := &Config{ 59 ServiceName: serviceName, // Use client provided service 60 HostName: "", 61 EnableHostname: true, // Enable hostname prefix 62 EnableRuntimeMetrics: true, // Enable runtime profiling 63 EnableTypePrefix: false, // Disable type prefix 64 TimerGranularity: time.Millisecond, // Timers are in milliseconds 65 ProfileInterval: time.Second, // Poll runtime every second 66 FilterDefault: true, // Don't filter metrics by default 67 } 68 69 // Try to get the hostname 70 name, _ := os.Hostname() 71 c.HostName = name 72 return c 73 } 74 75 // New is used to create a new instance of Metrics 76 func New(conf *Config, sink MetricSink) (*Metrics, error) { 77 met := &Metrics{} 78 met.Config = *conf 79 met.sink = sink 80 met.UpdateFilterAndLabels(conf.AllowedPrefixes, conf.BlockedPrefixes, conf.AllowedLabels, conf.BlockedLabels) 81 82 // Start the runtime collector 83 if conf.EnableRuntimeMetrics { 84 go met.collectStats() 85 } 86 return met, nil 87 } 88 89 // NewGlobal is the same as New, but it assigns the metrics object to be 90 // used globally as well as returning it. 91 func NewGlobal(conf *Config, sink MetricSink) (*Metrics, error) { 92 metrics, err := New(conf, sink) 93 if err == nil { 94 globalMetrics.Store(metrics) 95 } 96 return metrics, err 97 } 98 99 // Proxy all the methods to the globalMetrics instance 100 101 // Set gauge key and value with 32 bit precision 102 func SetGauge(key []string, val float32) { 103 globalMetrics.Load().(*Metrics).SetGauge(key, val) 104 } 105 106 // Set gauge key and value with 32 bit precision 107 func SetGaugeWithLabels(key []string, val float32, labels []Label) { 108 globalMetrics.Load().(*Metrics).SetGaugeWithLabels(key, val, labels) 109 } 110 111 // Set gauge key and value with 64 bit precision 112 // The Sink needs to implement PrecisionGaugeMetricSink, in case it doesn't, the metric value won't be set and ingored instead 113 func SetPrecisionGauge(key []string, val float64) { 114 globalMetrics.Load().(*Metrics).SetPrecisionGauge(key, val) 115 } 116 117 // Set gauge key, value with 64 bit precision, and labels 118 // The Sink needs to implement PrecisionGaugeMetricSink, in case it doesn't, the metric value won't be set and ingored instead 119 func SetPrecisionGaugeWithLabels(key []string, val float64, labels []Label) { 120 globalMetrics.Load().(*Metrics).SetPrecisionGaugeWithLabels(key, val, labels) 121 } 122 123 func EmitKey(key []string, val float32) { 124 globalMetrics.Load().(*Metrics).EmitKey(key, val) 125 } 126 127 func IncrCounter(key []string, val float32) { 128 globalMetrics.Load().(*Metrics).IncrCounter(key, val) 129 } 130 131 func IncrCounterWithLabels(key []string, val float32, labels []Label) { 132 globalMetrics.Load().(*Metrics).IncrCounterWithLabels(key, val, labels) 133 } 134 135 func AddSample(key []string, val float32) { 136 globalMetrics.Load().(*Metrics).AddSample(key, val) 137 } 138 139 func AddSampleWithLabels(key []string, val float32, labels []Label) { 140 globalMetrics.Load().(*Metrics).AddSampleWithLabels(key, val, labels) 141 } 142 143 func MeasureSince(key []string, start time.Time) { 144 globalMetrics.Load().(*Metrics).MeasureSince(key, start) 145 } 146 147 func MeasureSinceWithLabels(key []string, start time.Time, labels []Label) { 148 globalMetrics.Load().(*Metrics).MeasureSinceWithLabels(key, start, labels) 149 } 150 151 func UpdateFilter(allow, block []string) { 152 globalMetrics.Load().(*Metrics).UpdateFilter(allow, block) 153 } 154 155 // UpdateFilterAndLabels set allow/block prefixes of metrics while allowedLabels 156 // and blockedLabels - when not nil - allow filtering of labels in order to 157 // block/allow globally labels (especially useful when having large number of 158 // values for a given label). See README.md for more information about usage. 159 func UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels []string) { 160 globalMetrics.Load().(*Metrics).UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels) 161 } 162 163 // Shutdown disables metric collection, then blocks while attempting to flush metrics to storage. 164 // WARNING: Not all MetricSink backends support this functionality, and calling this will cause them to leak resources. 165 // This is intended for use immediately prior to application exit. 166 func Shutdown() { 167 m := globalMetrics.Load().(*Metrics) 168 // Swap whatever MetricSink is currently active with a BlackholeSink. Callers must not have a 169 // reason to expect that calls to the library will successfully collect metrics after Shutdown 170 // has been called. 171 globalMetrics.Store(&Metrics{sink: &BlackholeSink{}}) 172 m.Shutdown() 173 }