stats

package module
v0.4.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 11, 2024 License: Apache-2.0 Imports: 16 Imported by: 50

README

Gostats GoDoc Build Status

gostats is a Go metrics library with support for Counters, Gauges, and Timers.

Installation

go get github.com/lyft/gostats

Building & Testing

go test ./...

Usage

In order to start using gostats, import it into your project with:

import "github.com/lyft/gostats"

Mocking

A thread-safe mock sink is provided by the gostats/mock package. The mock sink also provides methods that are useful for testing (as demonstrated below).

package mock_test

import (
	"testing"

	"github.com/lyft/gostats"
	"github.com/lyft/gostats/mock"
)

type Config struct {
	Stats stats.Store
}

func TestMockExample(t *testing.T) {
	sink := mock.NewSink()
	conf := Config{
		Stats: stats.NewStore(sink, false),
	}
	conf.Stats.NewCounter("name").Inc()
	conf.Stats.Flush()
	sink.AssertCounterEquals(t, "name", 1)
}

If you do not need to assert on the contents of the sink the below example can be used to quickly create a thread-safe stats.Scope:

package config

import (
	"github.com/lyft/gostats"
	"github.com/lyft/gostats/mock"
)

type Config struct {
	Stats stats.Store
}

func NewConfig() *Config {
	return &Config{
		Stats: stats.NewDefaultStore(),
	}
}

func NewMockConfig() *Config {
	sink := mock.NewSink()
	return &Config{
		Stats: stats.NewStore(sink, false),
	}
}

Documentation

Overview

Package stats is a statistics library created by Engineers at Lyft with support for Counters, Gauges, and Timers.

Example (FlushCounter)
l := &loggingSink{writer: os.Stdout, now: foreverNow}
l.FlushCounter("counterName", 420)
Output:

{"level":"debug","ts":1640995200.000000,"logger":"gostats.loggingsink","msg":"flushing counter","json":{"name":"counterName","type":"counter","value":"420.000000"}}

Index

Examples

Constants

View Source
const (
	// DefaultUseStatsd use statsd as a stats sink, default is true.
	DefaultUseStatsd = true
	// DefaultStatsdHost is the default address where statsd is running at.
	DefaultStatsdHost = "localhost"
	// DefaultStatsdProtocol is TCP
	DefaultStatsdProtocol = "tcp"
	// DefaultStatsdPort is the default port where statsd is listening at.
	DefaultStatsdPort = 8125
	// DefaultFlushIntervalS is the default flushing interval in seconds.
	DefaultFlushIntervalS = 5
	// DefaultLoggingSinkDisabled is the default behavior of logging sink suppression, default is false.
	DefaultLoggingSinkDisabled = false
)

Variables

This section is empty.

Functions

func NewStatHandler

func NewStatHandler(scope Scope, handler http.Handler) http.Handler

NewStatHandler returns an http handler for stats.

Types

type Counter

type Counter interface {
	// Add increments the Counter by the argument's value.
	Add(uint64)

	// Inc increments the Counter by 1.
	Inc()

	// Set sets an internal counter value which will be written in the next flush.
	// Its use is discouraged as it may break the counter's "always incrementing" semantics.
	Set(uint64)

	// String returns the current value of the Counter as a string.
	String() string

	// Value returns the current value of the Counter as a uint64.
	Value() uint64
}

A Counter is an always incrementing stat.

type FlushableSink added in v0.2.12

type FlushableSink interface {
	Sink
	Flush()
}

FlushableSink is an extension of Sink that provides a Flush() function that will flush any buffered stats to the underlying store.

func NewLoggingSink

func NewLoggingSink() FlushableSink

NewLoggingSink returns a "default" logging Sink that flushes stats to os.StdErr. This sink is not fast, or flexible, it doesn't buffer, it exists merely to be convenient to use by default, with no configuration.

The format of this logger is similar to Zap, but not explicitly importing Zap to avoid the dependency. The format is as if you used a zap.NewProduction-generated logger, but also added a log.With(zap.Namespace("json")). This does not include any stacktrace for errors at the moment.

If these defaults do not work for you, users should provide their own logger, conforming to FlushableSink, instead.

func NewNetSink added in v0.3.10

func NewNetSink(opts ...SinkOption) FlushableSink

NewNetSink returns a FlushableSink that writes to a statsd sink over the network. By default settings are taken from the environment, but can be overridden via SinkOptions.

func NewNullSink

func NewNullSink() FlushableSink

NewNullSink returns a Sink that does not have a backing store attached to it.

func NewTCPStatsdSink added in v0.2.0

func NewTCPStatsdSink(opts ...SinkOption) FlushableSink

NewTCPStatsdSink returns a new NetStink. This function name exists for backwards compatibility.

type Gauge

type Gauge interface {
	// Add increments the Gauge by the argument's value.
	Add(uint64)

	// Sub decrements the Gauge by the argument's value.
	Sub(uint64)

	// Inc increments the Gauge by 1.
	Inc()

	// Dec decrements the Gauge by 1.
	Dec()

	// Set sets the Gauge to a value.
	Set(uint64)

	// String returns the current value of the Gauge as a string.
	String() string

	// Value returns the current value of the Gauge as a uint64.
	Value() uint64
}

A Gauge is a stat that can increment and decrement.

type Logger added in v0.4.9

type Logger interface {
	Errorf(msg string, args ...interface{})
	Warnf(msg string, args ...interface{})
}

Logger is used to log errors and other important operational information while using gostats.

For convenience of transitioning from logrus to zap, this interface conforms BOTH to logrus.Logger as well as the Zap's Sugared logger.

type MockSink added in v0.2.0

type MockSink struct {
	Counters map[string]uint64
	Timers   map[string]uint64
	Gauges   map[string]uint64
	// contains filtered or unexported fields
}

MockSink describes an in-memory Sink used for testing.

DEPRECATED: use "github.com/lyft/gostats/mock" instead.

func NewMockSink

func NewMockSink() (m *MockSink)

NewMockSink returns a MockSink that flushes stats to in-memory maps. An instance of MockSink is not safe for concurrent use.

DEPRECATED: use "github.com/lyft/gostats/mock" instead.

func (*MockSink) FlushCounter added in v0.2.0

func (m *MockSink) FlushCounter(name string, value uint64)

FlushCounter satisfies the Sink interface.

func (*MockSink) FlushGauge added in v0.2.0

func (m *MockSink) FlushGauge(name string, value uint64)

FlushGauge satisfies the Sink interface.

func (*MockSink) FlushTimer added in v0.2.0

func (m *MockSink) FlushTimer(name string, value float64)

FlushTimer satisfies the Sink interface.

type Scope

type Scope interface {
	// Scope creates a subscope.
	Scope(name string) Scope

	// ScopeWithTags creates a subscope with Tags to a store or scope. All child scopes and metrics
	// will inherit these tags by default.
	ScopeWithTags(name string, tags map[string]string) Scope

	// Store returns the Scope's backing Store.
	Store() Store

	// NewCounter adds a Counter to a store, or a scope.
	NewCounter(name string) Counter

	// NewCounterWithTags adds a Counter with Tags to a store, or a scope.
	NewCounterWithTags(name string, tags map[string]string) Counter

	// NewPerInstanceCounter adds a Per instance Counter with optional Tags to a store, or a scope.
	NewPerInstanceCounter(name string, tags map[string]string) Counter

	// NewGauge adds a Gauge to a store, or a scope.
	NewGauge(name string) Gauge

	// NewGaugeWithTags adds a Gauge with Tags to a store, or a scope.
	NewGaugeWithTags(name string, tags map[string]string) Gauge

	// NewPerInstanceGauge adds a Per instance Gauge with optional Tags to a store, or a scope.
	NewPerInstanceGauge(name string, tags map[string]string) Gauge

	// NewTimer adds a Timer to a store, or a scope that uses microseconds as its unit.
	NewTimer(name string) Timer

	// NewTimerWithTags adds a Timer with Tags to a store, or a scope with Tags that uses microseconds as its unit.
	NewTimerWithTags(name string, tags map[string]string) Timer

	// NewPerInstanceTimer adds a Per instance Timer with optional Tags to a store, or a scope that uses microseconds as its unit.
	NewPerInstanceTimer(name string, tags map[string]string) Timer

	// NewMilliTimer adds a Timer to a store, or a scope that uses milliseconds as its unit.
	NewMilliTimer(name string) Timer

	// NewMilliTimerWithTags adds a Timer with Tags to a store, or a scope with Tags that uses milliseconds as its unit.
	NewMilliTimerWithTags(name string, tags map[string]string) Timer

	// NewPerInstanceMilliTimer adds a Per instance Timer with optional Tags to a store, or a scope that uses milliseconds as its unit.
	NewPerInstanceMilliTimer(name string, tags map[string]string) Timer
}

A Scope namespaces Statistics.

store := stats.NewDefaultStore()
scope := stats.Scope("service")
// the following counter will be emitted at the stats tree rooted at `service`.
c := scope.NewCounter("success")

Additionally you can create subscopes:

store := stats.NewDefaultStore()
scope := stats.Scope("service")
networkScope := scope.Scope("network")
// the following counter will be emitted at the stats tree rooted at service.network.
c := networkScope.NewCounter("requests")

type Settings

type Settings struct {
	// Use statsd as a stats sink.
	UseStatsd bool `envconfig:"USE_STATSD" default:"true"`
	// Address where statsd is running at.
	StatsdHost string `envconfig:"STATSD_HOST" default:"localhost"`
	// Network protocol used to connect to statsd
	StatsdProtocol string `envconfig:"STATSD_PROTOCOL" default:"tcp"`
	// Port where statsd is listening at.
	StatsdPort int `envconfig:"STATSD_PORT" default:"8125"`
	// Flushing interval.
	FlushIntervalS int `envconfig:"GOSTATS_FLUSH_INTERVAL_SECONDS" default:"5"`
	// Disable the LoggingSink when USE_STATSD is false and use the NullSink instead.
	// This will cause all stats to be silently dropped.
	LoggingSinkDisabled bool `envconfig:"GOSTATS_LOGGING_SINK_DISABLED" default:"false"`
}

The Settings type is used to configure gostats. gostats uses environment variables to setup its settings.

func GetSettings

func GetSettings() Settings

GetSettings returns the Settings gostats will run with.

func (*Settings) FlushInterval added in v0.4.11

func (s *Settings) FlushInterval() time.Duration

FlushInterval returns the flush interval duration.

type Sink

type Sink interface {
	FlushCounter(name string, value uint64)
	FlushGauge(name string, value uint64)
	FlushTimer(name string, value float64)
}

A Sink is used by a Store to flush its data. These functions may buffer the given data.

type SinkOption added in v0.3.9

type SinkOption interface {
	// contains filtered or unexported methods
}

An SinkOption configures a Sink.

func WithLogger added in v0.3.9

func WithLogger(log Logger) SinkOption

WithLogger configures the sink to use the provided logger otherwise the built-in zap-like logger is used.

func WithStatsdHost added in v0.3.9

func WithStatsdHost(host string) SinkOption

WithStatsdHost sets the host of the statsd sink otherwise the host is read from the environment variable "STATSD_HOST".

func WithStatsdPort added in v0.3.9

func WithStatsdPort(port int) SinkOption

WithStatsdPort sets the port of the statsd sink otherwise the port is read from the environment variable "STATSD_PORT".

func WithStatsdProtocol added in v0.3.10

func WithStatsdProtocol(protocol string) SinkOption

WithStatsdProtocol sets the network protocol ("udp" or "tcp") of the statsd sink otherwise the protocol is read from the environment variable "STATSD_PROTOCOL".

type StatGenerator

type StatGenerator interface {
	// Runs the StatGenerator to generate Stats.
	GenerateStats()
}

A StatGenerator can be used to programatically generate stats. StatGenerators are added to a store via

AddStatGenerator(StatGenerator)

An example is https://github.com/lyft/gostats/blob/master/runtime.go.

func NewRuntimeStats

func NewRuntimeStats(scope Scope) StatGenerator

NewRuntimeStats returns a StatGenerator with common Go runtime stats like memory allocated, total mallocs, total frees, etc.

type Store

type Store interface {
	// Flush Counters and Gauges to the Sink attached to the Store.
	// To flush the store at a regular interval call the
	//  Start(*time.Ticker)
	// method on it.
	//
	// The store will flush either at the regular interval, or whenever
	//  Flush()
	// is called. Whenever the store is flushed,
	// the store will call
	//  GenerateStats()
	// on all of its stat generators,
	// and flush all the Counters and Gauges registered with it.
	Flush()

	// Start a timer for periodic stat flushes. This is a blocking
	// call and should be called in a goroutine.
	Start(*time.Ticker)

	// StartContext starts a timer for periodic stat flushes. This is
	// a blocking call and should be called in a goroutine.
	//
	// If the passed-in context is cancelled, then this call
	// exits. Flush will be called on exit.
	StartContext(context.Context, *time.Ticker)

	// Add a StatGenerator to the Store that programatically generates stats.
	AddStatGenerator(StatGenerator)
	Scope
}

A Store holds statistics. There are two options when creating a new store:

create a store backed by a tcp_sink to statsd
s := stats.NewDefaultStore()
create a store with a user provided Sink
s := stats.NewStore(sink, true)

Currently that only backing store supported is statsd via a TCP sink, https://github.com/lyft/gostats/blob/master/tcp_sink.go. However, implementing other Sinks (https://github.com/lyft/gostats/blob/master/sink.go) should be simple.

A store holds Counters, Gauges, and Timers. You can add unscoped Counters, Gauges, and Timers to the store with:

s := stats.NewDefaultStore()
c := s.New[Counter|Gauge|Timer]("name")

func NewDefaultStore

func NewDefaultStore() Store

NewDefaultStore returns a Store with a TCP statsd sink, and a running flush timer.

func NewStore

func NewStore(sink Sink, _ bool) Store

NewStore returns an Empty store that flushes to Sink passed as an argument. Note: the export argument is unused.

type Timer

type Timer interface {
	// AddValue flushs the timer with the argument's value.
	AddValue(float64)

	// AddDuration emits the duration as a timing measurement.
	AddDuration(time.Duration)

	// AllocateSpan allocates a Timespan.
	AllocateSpan() Timespan
}

A Timer is used to flush timing statistics.

type Timespan

type Timespan interface {
	// End the Timespan and flush it.
	Complete() time.Duration

	// End the Timespan and flush it. Adds additional time.Duration to the measured time
	CompleteWithDuration(time.Duration)
}

A Timespan is used to measure spans of time. They measure time from the time they are allocated by a Timer with

AllocateSpan()

until they call

Complete()

or

CompleteWithDuration(time.Duration)

When either function is called the timespan is flushed. When Complete is called the timespan is flushed.

A Timespan can be flushed at function return by calling Complete with golang's defer statement.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL