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  }