• Stars
    star
    810
  • Rank 54,007 (Top 2 %)
  • Language
    Go
  • License
    MIT License
  • Created over 7 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Go metrics interface with fast buffered metrics and third party reporters

✔️ 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, gauges and histograms 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 summaries or histograms independently by a reporter.

Structure

  • Scope: Keeps track of metrics, and their common metadata.
  • Metrics: Counters, Gauges, Timers and Histograms.
  • Reporter: Implemented by you. Accepts aggregated values from the scope. Forwards the aggregated values to your metrics ingestion pipeline.
    • The reporters already available listed alphabetically are:
      • github.com/uber-go/tally/m3: Report m3 metrics, timers are not sampled and forwarded directly.
      • github.com/uber-go/tally/multi: Report to multiple reporters, you can multi-write metrics to other reporters simply.
      • github.com/uber-go/tally/prometheus: Report prometheus metrics, timers by default are made summaries with an option to make them histograms instead.
      • github.com/uber-go/tally/statsd: Report statsd metrics, no support for tags.

Basics

  • Scopes created with tally provide race-safe registration and use of all metric types Counter, Gauge, Timer, Histogram.
  • NewRootScope(...) returns a Scope and io.Closer, the second return value is used to stop the scope's goroutine reporting values from the scope to it's reporter. This is to reduce the footprint of Scope from the public API for those implementing it themselves to use in Go packages that take a tally Scope.

Acquire a Scope

reporter = NewMyStatsReporter()  // Implement as you will
tags := map[string]string{
	"dc": "east-1",
	"type": "master",
}
reportEvery := time.Second

scope := tally.NewRootScope(tally.ScopeOptions{
	Tags: tags,
	Reporter: reporter,
}, reportEvery)

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 (
	"io"
	"github.com/cactus/go-statsd-client/v5/statsd"
	"github.com/uber-go/tally"
	tallystatsd "github.com/uber-go/tally/statsd"
	// ...
)

func newScope() (tally.Scope, io.Closer) {
	statter, _ := statsd.NewBufferedClient("127.0.0.1:8125",
		"stats", 100*time.Millisecond, 1440)

	reporter := tallystatsd.NewReporter(statter, tallystatsd.Options{
		SampleRate: 1.0,
	})

	scope, closer := tally.NewRootScope(tally.ScopeOptions{
		Prefix:   "my-service",
		Tags:     map[string]string{},
		Reporter: reporter,
	}, time.Second)

	return scope, closer
}

Implement your own reporter using the StatsReporter interface:

// BaseStatsReporter implements the shared reporter methods.
type BaseStatsReporter interface {
	Capabilities() Capabilities
	Flush()
}

// StatsReporter is a backend for Scopes to report metrics to.
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,
	)

	// ReportHistogramValueSamples reports histogram samples for a bucket
	ReportHistogramValueSamples(
		name string,
		tags map[string]string,
		buckets Buckets,
		bucketLowerBound,
		bucketUpperBound float64,
		samples int64,
	)

	// ReportHistogramDurationSamples reports histogram samples for a bucket
	ReportHistogramDurationSamples(
		name string,
		tags map[string]string,
		buckets Buckets,
		bucketLowerBound,
		bucketUpperBound time.Duration,
		samples int64,
	)
}

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

	// Histogram returns the Histogram object corresponding to the name.
	// To use default value and duration buckets configured for the scope
	// simply pass tally.DefaultBuckets or nil.
	// You can use tally.ValueBuckets{x, y, ...} for value buckets.
	// You can use tally.DurationBuckets{x, y, ...} for duration buckets.
	// You can use tally.MustMakeLinearValueBuckets(start, width, count) for linear values.
	// You can use tally.MustMakeLinearDurationBuckets(start, width, count) for linear durations.
	// You can use tally.MustMakeExponentialValueBuckets(start, factor, count) for exponential values.
	// You can use tally.MustMakeExponentialDurationBuckets(start, factor, count) for exponential durations.
	Histogram(name string, buckets Buckets) Histogram

	// 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
}

// Capabilities is a description of metrics reporting 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
}

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.

More Repositories

1

zap

Blazing fast, structured, leveled logging in Go.
Go
20,876
star
2

guide

The Uber Go Style Guide.
Makefile
15,131
star
3

fx

A dependency injection based application framework for Go.
Go
5,186
star
4

goleak

Goroutine leak detector
Go
4,263
star
5

ratelimit

A Go blocking leaky-bucket rate limit implementation
Go
3,934
star
6

dig

A reflection based dependency injection toolkit for Go.
Go
3,596
star
7

automaxprocs

Automatically set GOMAXPROCS to match Linux container CPU quota.
Go
3,459
star
8

mock

GoMock is a mocking framework for the Go programming language.
Go
1,582
star
9

atomic

Wrapper types for sync/atomic which enforce atomic access
Go
1,250
star
10

multierr

Combine one or more Go errors together
Go
907
star
11

gopatch

Refactoring and code transformation tool for Go.
Go
681
star
12

nilaway

Static Analysis tool to detect potential Nil panics in Go code
Go
400
star
13

config

Configuration for Go applications
Go
382
star
14

cadence-client

Framework for authoring workflows and activities running on top of the Cadence orchestration engine.
Go
322
star
15

sally

A tiny HTTP server for supporting custom Golang import paths
Go
228
star
16

kafka-client

Go client library for Apache Kafka
Go
221
star
17

dosa

DOSA is a data object abstraction layer
Go
197
star
18

cff

Concurrency toolkit for Go
Go
124
star
19

tools

A collection of golang tools used at Uber
Go
58
star
20

go-helix

A Go implementation of Apache Helix (currently the participant part only).
Go
56
star
21

icu4go

A Go binding for the icu4c library
Go
49
star
22

mapdecode

Implement YAML/JSON decoding in one place.
Go
48
star
23

hackeroni

A Go API client for HackerOne (api.hackerone.com)
Go
41
star
24

gwr

Get / Watch / Report -ing of operational data. This project is deprecated and not maintained.
Go
38
star
25

flagoverride

An automatic way of creating command line options to override fields from a struct.
Go
20
star