start.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package metrics
  2. import (
  3. "os"
  4. "sync"
  5. "sync/atomic"
  6. "time"
  7. "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. // DefaultConfig provides a sane default configuration
  44. func DefaultConfig(serviceName string) *Config {
  45. c := &Config{
  46. ServiceName: serviceName, // Use client provided service
  47. HostName: "",
  48. EnableHostname: true, // Enable hostname prefix
  49. EnableRuntimeMetrics: true, // Enable runtime profiling
  50. EnableTypePrefix: false, // Disable type prefix
  51. TimerGranularity: time.Millisecond, // Timers are in milliseconds
  52. ProfileInterval: time.Second, // Poll runtime every second
  53. FilterDefault: true, // Don't filter metrics by default
  54. }
  55. // Try to get the hostname
  56. name, _ := os.Hostname()
  57. c.HostName = name
  58. return c
  59. }
  60. // New is used to create a new instance of Metrics
  61. func New(conf *Config, sink MetricSink) (*Metrics, error) {
  62. met := &Metrics{}
  63. met.Config = *conf
  64. met.sink = sink
  65. met.UpdateFilterAndLabels(conf.AllowedPrefixes, conf.BlockedPrefixes, conf.AllowedLabels, conf.BlockedLabels)
  66. // Start the runtime collector
  67. if conf.EnableRuntimeMetrics {
  68. go met.collectStats()
  69. }
  70. return met, nil
  71. }
  72. // NewGlobal is the same as New, but it assigns the metrics object to be
  73. // used globally as well as returning it.
  74. func NewGlobal(conf *Config, sink MetricSink) (*Metrics, error) {
  75. metrics, err := New(conf, sink)
  76. if err == nil {
  77. globalMetrics.Store(metrics)
  78. }
  79. return metrics, err
  80. }
  81. // Proxy all the methods to the globalMetrics instance
  82. func SetGauge(key []string, val float32) {
  83. globalMetrics.Load().(*Metrics).SetGauge(key, val)
  84. }
  85. func SetGaugeWithLabels(key []string, val float32, labels []Label) {
  86. globalMetrics.Load().(*Metrics).SetGaugeWithLabels(key, val, labels)
  87. }
  88. func EmitKey(key []string, val float32) {
  89. globalMetrics.Load().(*Metrics).EmitKey(key, val)
  90. }
  91. func IncrCounter(key []string, val float32) {
  92. globalMetrics.Load().(*Metrics).IncrCounter(key, val)
  93. }
  94. func IncrCounterWithLabels(key []string, val float32, labels []Label) {
  95. globalMetrics.Load().(*Metrics).IncrCounterWithLabels(key, val, labels)
  96. }
  97. func AddSample(key []string, val float32) {
  98. globalMetrics.Load().(*Metrics).AddSample(key, val)
  99. }
  100. func AddSampleWithLabels(key []string, val float32, labels []Label) {
  101. globalMetrics.Load().(*Metrics).AddSampleWithLabels(key, val, labels)
  102. }
  103. func MeasureSince(key []string, start time.Time) {
  104. globalMetrics.Load().(*Metrics).MeasureSince(key, start)
  105. }
  106. func MeasureSinceWithLabels(key []string, start time.Time, labels []Label) {
  107. globalMetrics.Load().(*Metrics).MeasureSinceWithLabels(key, start, labels)
  108. }
  109. func UpdateFilter(allow, block []string) {
  110. globalMetrics.Load().(*Metrics).UpdateFilter(allow, block)
  111. }
  112. // UpdateFilterAndLabels set allow/block prefixes of metrics while allowedLabels
  113. // and blockedLabels - when not nil - allow filtering of labels in order to
  114. // block/allow globally labels (especially useful when having large number of
  115. // values for a given label). See README.md for more information about usage.
  116. func UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels []string) {
  117. globalMetrics.Load().(*Metrics).UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels)
  118. }