README

✔️ tally GoDoc Build Status Coverage Status

Fast, buffered, hierarchical stats collection in Go.

Installation

go get -u github.com/uber-go/tally

Abstract

Tally provides a common interface for emitting metrics, while letting you not worry about the velocity of metrics emission.

By default it buffers counters and gauges at a specified interval but does not buffer timer values. This is primarily so timer values can have all their values sampled if desired and if not they can be sampled as histograms.

Structure

  • Scope: Keeps track of metrics, and their common metadata.
  • Metrics: Counters, Gauges, Timers.
  • Reporter: Implemented by you. Accepts aggregated values from the scope. Forwards the aggregated values to your metrics ingestion pipeline.
Acquire a Scope
reporter = NewMyStatsReporter()  // Implement as you will
tags := map[string]string{
	"dc": "east-1",
	"type": "master",
}
reportEvery := 1 * time.Second
scope := tally.NewRootScope("some_prefix", tags, reporter, reportEvery, tally.DefaultSeparator)
Get/Create a metric, use it
// Get a counter, increment a counter
reqCounter := scope.Counter("requests")  // cache me
reqCounter.Inc(1)

queueGauge := scope.Gauge("queue_length")  // cache me
queueGauge.Update(42)
Report your metrics

Use the inbuilt statsd reporter:

import (
	"github.com/cactus/go-statsd-client/statsd"
	"github.com/uber-go/tally"
	tallystatsd "github.com/uber-go/tally/statsd"
	// ...
)

client, err := statsd.NewClient("statsd.aggregator.local:1234", "")
// ...

opts := tallystatsd.NewOptions().SetSampleRate(1.0)
reporter = tallystatsd.NewStatsdReporter(client, opts)
tags := map[string]string{
	"dc": "east-1",
	"type": "master",
}
reportEvery := 1 * time.Second
scope := tally.NewRootScope("some_prefix", tags, reporter, reportEvery, tally.DefaultSeparator)

Implement your own reporter using the StatsReporter interface:

type StatsReporter interface {
	// ReportCounter reports a counter value
	ReportCounter(name string, tags map[string]string, value int64)

	// ReportGauge reports a gauge value
	ReportGauge(name string, tags map[string]string, value float64)

	// ReportTimer reports a timer value
	ReportTimer(name string, tags map[string]string, interval time.Duration)

	// Capabilities returns a description of metrics reporting capabilities
	Capabilities() Capabilities

	// Flush is expected to be called by a Scope when it completes a round or reporting
	Flush()
}

Or implement your own metrics implementation that matches the tally Scope interface to use different buffering semantics:

type Scope interface {
	// Counter returns the Counter object corresponding to the name
	Counter(name string) Counter

	// Gauge returns the Gauge object corresponding to the name
	Gauge(name string) Gauge

	// Timer returns the Timer object corresponding to the name
	Timer(name string) Timer

	// Tagged returns a new child scope with the given tags and current tags
	Tagged(tags map[string]string) Scope

	// SubScope returns a new child scope appending a further name prefix
	SubScope(name string) Scope

	// Capabilities returns a description of metrics reporting capabilities
	Capabilities() Capabilities
}

Performance

This stuff needs to be fast. With that in mind, we avoid locks and unnecessary memory allocations.

BenchmarkCounterInc-8               	200000000	         7.68 ns/op
BenchmarkReportCounterNoData-8      	300000000	         4.88 ns/op
BenchmarkReportCounterWithData-8    	100000000	        21.6 ns/op
BenchmarkGaugeSet-8                 	100000000	        16.0 ns/op
BenchmarkReportGaugeNoData-8        	100000000	        10.4 ns/op
BenchmarkReportGaugeWithData-8      	50000000	        27.6 ns/op
BenchmarkTimerInterval-8            	50000000	        37.7 ns/op
BenchmarkTimerReport-8              	300000000	         5.69 ns/op

Released under the [MIT License](LICENSE).
Expand ▾ Collapse ▴

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// NoopScope is a scope that does nothing
	NoopScope, _ = NewRootScope("", nil, NullStatsReporter, 0, "")
	// DefaultSeparator is the default separator used to join nested scopes
	DefaultSeparator = "."
)

Functions

func KeyForPrefixedStringMap

func KeyForPrefixedStringMap(
	prefix string,
	stringMap map[string]string,
) string

    KeyForPrefixedStringMap generates a unique key for a a prefix and a map string set combination.

    func KeyForStringMap

    func KeyForStringMap(
    	stringMap map[string]string,
    ) string

      KeyForStringMap generates a unique key for a map string set combination.

      Types

      type BaseStatsReporter

      type BaseStatsReporter interface {
      	Capabilities() Capabilities
      	Flush()
      }

        BaseStatsReporter implements the shared reporter methods

        type CachedCount

        type CachedCount interface {
        	ReportCount(value int64)
        }

          CachedCount interface for reporting an individual counter

          type CachedGauge

          type CachedGauge interface {
          	ReportGauge(value float64)
          }

            CachedGauge interface for reporting an individual gauge

            type CachedStatsReporter

            type CachedStatsReporter interface {
            	BaseStatsReporter
            
            	// AllocateCounter pre allocates a counter data structure with name & tags.
            	AllocateCounter(name string, tags map[string]string) CachedCount
            
            	// AllocateGauge pre allocates a gauge data structure with name & tags.
            	AllocateGauge(name string, tags map[string]string) CachedGauge
            
            	// AllocateTimer pre allocates a timer data structure with name & tags.
            	AllocateTimer(name string, tags map[string]string) CachedTimer
            }

              CachedStatsReporter is a backend for Scopes that pre allocates all counter, gauges & timers. This is harder to implement but more performant

              type CachedTimer

              type CachedTimer interface {
              	ReportTimer(interval time.Duration)
              }

                CachedTimer interface for reporting an individual timer

                type Capabilities

                type Capabilities interface {
                	// Reporting returns whether the reporter has the ability to actively report
                	Reporting() bool
                
                	// Tagging returns whether the reporter has the capability for tagged metrics
                	Tagging() bool
                }

                  Capabilities is a description of metrics reporting capabilities

                  type Counter

                  type Counter interface {
                  	// Inc increments the counter by a delta
                  	Inc(delta int64)
                  }

                    Counter is the interface for emitting counter type metrics

                    type CounterSnapshot

                    type CounterSnapshot interface {
                    	// Name returns the name
                    	Name() string
                    
                    	// Tags returns the tags
                    	Tags() map[string]string
                    
                    	// Value returns the value
                    	Value() int64
                    }

                      CounterSnapshot is a snapshot of a counter

                      type Gauge

                      type Gauge interface {
                      	// Update sets the gauges absolute value
                      	Update(value float64)
                      }

                        Gauge is the interface for emitting gauge metrics

                        type GaugeSnapshot

                        type GaugeSnapshot interface {
                        	// Name returns the name
                        	Name() string
                        
                        	// Tags returns the tags
                        	Tags() map[string]string
                        
                        	// Value returns the value
                        	Value() float64
                        }

                          GaugeSnapshot is a snapshot of a gauge

                          type ObjectPool

                          type ObjectPool struct {
                          	// contains filtered or unexported fields
                          }

                            ObjectPool is an minimalistic object pool to avoid any circular dependencies on any other object pool.

                            func NewObjectPool

                            func NewObjectPool(size int) *ObjectPool

                              NewObjectPool creates a new pool.

                              func (*ObjectPool) Get

                              func (p *ObjectPool) Get() interface{}

                                Get gets an object from the pool.

                                func (*ObjectPool) Init

                                func (p *ObjectPool) Init(alloc func() interface{})

                                  Init initializes the object pool.

                                  func (*ObjectPool) Put

                                  func (p *ObjectPool) Put(obj interface{})

                                    Put puts an object back to the pool.

                                    type Scope

                                    type Scope interface {
                                    	// Counter returns the Counter object corresponding to the name
                                    	Counter(name string) Counter
                                    
                                    	// Gauge returns the Gauge object corresponding to the name
                                    	Gauge(name string) Gauge
                                    
                                    	// Timer returns the Timer object corresponding to the name
                                    	Timer(name string) Timer
                                    
                                    	// Tagged returns a new child scope with the given tags and current tags
                                    	Tagged(tags map[string]string) Scope
                                    
                                    	// SubScope returns a new child scope appending a further name prefix
                                    	SubScope(name string) Scope
                                    
                                    	// Capabilities returns a description of metrics reporting capabilities
                                    	Capabilities() Capabilities
                                    }

                                      Scope is a namespace wrapper around a stats reporter, ensuring that all emitted values have a given prefix or set of tags

                                      func NewCachedRootScope

                                      func NewCachedRootScope(
                                      	prefix string,
                                      	tags map[string]string,
                                      	reporter CachedStatsReporter,
                                      	interval time.Duration,
                                      	separator string,
                                      ) (Scope, io.Closer)

                                        NewCachedRootScope creates a new Scope using a more performant cached stats reporter with the given prefix

                                        func NewRootScope

                                        func NewRootScope(
                                        	prefix string,
                                        	tags map[string]string,
                                        	reporter StatsReporter,
                                        	interval time.Duration,
                                        	separator string,
                                        ) (Scope, io.Closer)

                                          NewRootScope creates a new Scope around a given stats reporter with the given prefix

                                          type Snapshot

                                          type Snapshot interface {
                                          	// Counters returns a snapshot of all counter summations since last report execution
                                          	Counters() map[string]CounterSnapshot
                                          
                                          	// Gauges returns a snapshot of gauge last values since last report execution
                                          	Gauges() map[string]GaugeSnapshot
                                          
                                          	// Timers returns a snapshot of timer values since last report execution
                                          	Timers() map[string]TimerSnapshot
                                          }

                                            Snapshot is a snapshot of values since last report execution

                                            type StatsReporter

                                            type StatsReporter interface {
                                            	BaseStatsReporter
                                            
                                            	// ReportCounter reports a counter value
                                            	ReportCounter(name string, tags map[string]string, value int64)
                                            
                                            	// ReportGauge reports a gauge value
                                            	ReportGauge(name string, tags map[string]string, value float64)
                                            
                                            	// ReportTimer reports a timer value
                                            	ReportTimer(name string, tags map[string]string, interval time.Duration)
                                            }

                                              StatsReporter is a backend for Scopes to report metrics to

                                              var NullStatsReporter StatsReporter = nullStatsReporter{}

                                                NullStatsReporter is an implementatin of StatsReporter than simply does nothing.

                                                type Stopwatch

                                                type Stopwatch struct {
                                                	// contains filtered or unexported fields
                                                }

                                                  Stopwatch is a helper convenience struct for nicer tracking of elapsed time

                                                  func (Stopwatch) Stop

                                                  func (s Stopwatch) Stop() time.Duration

                                                    Stop records the difference between the current clock and startTime

                                                    type TestScope

                                                    type TestScope interface {
                                                    	Scope
                                                    
                                                    	// Snapshot returns a copy of all values since the last report execution,
                                                    	// this is an expensive operation and should only be use for testing purposes
                                                    	Snapshot() Snapshot
                                                    }

                                                      TestScope is a metrics collector that has no reporting, ensuring that all emitted values have a given prefix or set of tags

                                                      func NewTestScope

                                                      func NewTestScope(
                                                      	prefix string,
                                                      	tags map[string]string,
                                                      ) TestScope

                                                        NewTestScope creates a new Scope without a stats reporter with the given prefix and adds the ability to take snapshots of metrics emitted to it

                                                        type Timer

                                                        type Timer interface {
                                                        	// Record a specific duration directly
                                                        	Record(time.Duration)
                                                        
                                                        	// Start gives you back a specific point in time to report via Stop()
                                                        	Start() Stopwatch
                                                        }

                                                          Timer is the interface for emitting timer metrics

                                                          type TimerSnapshot

                                                          type TimerSnapshot interface {
                                                          	// Name returns the name
                                                          	Name() string
                                                          
                                                          	// Tags returns the tags
                                                          	Tags() map[string]string
                                                          
                                                          	// Values returns the values
                                                          	Values() []time.Duration
                                                          }

                                                            TimerSnapshot is a snapshot of a timer