start.go 5.7 KB

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