Skip to content

Commit

Permalink
Update documentation to reflect current interfaces and usage (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
robskillington authored Feb 16, 2017
1 parent 6354c4d commit 58c90d1
Show file tree
Hide file tree
Showing 14 changed files with 118 additions and 86 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ cover:

.PHONY: coveralls
coveralls:
goveralls -service=travis-ci .
goveralls -service=travis-ci || echo "Coveralls failed"

.PHONY: bench
BENCH ?= .
Expand Down
131 changes: 101 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,20 @@ Fast, buffered, hierarchical stats collection in Go.

## Abstract

Tally provides a common interface for emitting metrics, while letting you not worry about the velocity of metrics emission.
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.
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.
- 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.

### Acquire a Scope ###
```go
Expand All @@ -24,8 +29,12 @@ tags := map[string]string{
"dc": "east-1",
"type": "master",
}
reportEvery := 1 * time.Second
scope := tally.NewRootScope("some_prefix", tags, reporter, reportEvery, tally.DefaultSeparator)
reportEvery := time.Second

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

### Get/Create a metric, use it ###
Expand All @@ -43,68 +52,130 @@ Use the inbuilt statsd reporter:

```go
import (
"io"
"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",
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: r,
}, time.Second)

return scope, closer
}
reportEvery := 1 * time.Second
scope := tally.NewRootScope("some_prefix", tags, reporter, reportEvery, tally.DefaultSeparator)
```

Implement your own reporter using the `StatsReporter` interface:

```go

// 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)
ReportCounter(
name string,
tags map[string]string,
value int64,
)

// ReportGauge reports a gauge value
ReportGauge(name string, tags map[string]string, value float64)
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()
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:

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

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

// Timer returns the Timer object corresponding to the name
// 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
// 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 returns a new child scope appending a further name prefix.
SubScope(name string) Scope

// Capabilities returns a description of metrics reporting capabilities
// 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
Expand Down
4 changes: 0 additions & 4 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,6 @@ func (r *printStatsReporter) Tagging() bool {
return false
}

func (r *printStatsReporter) Histograms() bool {
return true
}

func (r *printStatsReporter) Flush() {
fmt.Printf("flush\n")
}
Expand Down
4 changes: 0 additions & 4 deletions m3/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,10 +463,6 @@ func (r *reporter) Tagging() bool {
return true
}

func (r *reporter) Histograms() bool {
return true
}

func (r *reporter) process() {
mets := make([]*m3thrift.Metric, 0, (r.freeBytes / 10))
bytes := int32(0)
Expand Down
5 changes: 0 additions & 5 deletions multi/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ func (r multiBaseReporters) Capabilities() tally.Capabilities {
for _, r := range r {
c.reporting = c.reporting && r.Capabilities().Reporting()
c.tagging = c.tagging && r.Capabilities().Tagging()
c.histograms = c.histograms && r.Capabilities().Histograms()
}
return c
}
Expand All @@ -271,7 +270,3 @@ func (c *capabilities) Reporting() bool {
func (c *capabilities) Tagging() bool {
return c.tagging
}

func (c *capabilities) Histograms() bool {
return c.histograms
}
4 changes: 0 additions & 4 deletions multi/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,6 @@ func (r *capturingStatsReporter) Tagging() bool {
return true
}

func (r *capturingStatsReporter) Histograms() bool {
return true
}

func (r *capturingStatsReporter) Flush() {
r.flush++
}
Expand Down
4 changes: 0 additions & 4 deletions prometheus/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,10 +555,6 @@ func (r *reporter) Tagging() bool {
return true
}

func (r *reporter) Histograms() bool {
return true
}

// Flush does nothing for prometheus
func (r *reporter) Flush() {}

Expand Down
3 changes: 3 additions & 0 deletions reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import "time"

// BaseStatsReporter implements the shared reporter methods.
type BaseStatsReporter interface {
// Capabilities returns the capabilities description of the reporter.
Capabilities() Capabilities

// Flush asks the reporter to flush all reported values.
Flush()
}

Expand Down
2 changes: 1 addition & 1 deletion scope_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ func (r *testStatsReporter) ReportHistogramDurationSamples(
}

func (r *testStatsReporter) Capabilities() Capabilities {
return capabilitiesReportingNoTaggingNoHistograms // TODO: add support for test stats reporter for histograms
return capabilitiesReportingNoTagging
}

func (r *testStatsReporter) Flush() {}
Expand Down
35 changes: 11 additions & 24 deletions stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,22 @@ import (

var (
capabilitiesNone = &capabilities{
reporting: false,
tagging: false,
histograms: false,
reporting: false,
tagging: false,
}
capabilitiesReportingNoTaggingNoHistograms = &capabilities{
reporting: true,
tagging: false,
histograms: false,
capabilitiesReportingNoTagging = &capabilities{
reporting: true,
tagging: false,
}
capabilitiesReportingTaggingNoHistograms = &capabilities{
reporting: true,
tagging: true,
histograms: false,
}
capabilitiesReportingTaggingHistograms = &capabilities{
reporting: true,
tagging: true,
histograms: true,
capabilitiesReportingTagging = &capabilities{
reporting: true,
tagging: true,
}
)

type capabilities struct {
reporting bool
tagging bool
histograms bool
reporting bool
tagging bool
}

func (c *capabilities) Reporting() bool {
Expand All @@ -65,10 +56,6 @@ func (c *capabilities) Tagging() bool {
return c.tagging
}

func (c *capabilities) Histograms() bool {
return c.histograms
}

type counter struct {
prev int64
curr int64
Expand Down Expand Up @@ -270,7 +257,7 @@ func (r *timerNoReporterSink) ReportHistogramDurationSamples(
}

func (r *timerNoReporterSink) Capabilities() Capabilities {
return capabilitiesReportingTaggingNoHistograms
return capabilitiesReportingTagging
}

func (r *timerNoReporterSink) Flush() {
Expand Down
2 changes: 1 addition & 1 deletion stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (r *statsTestReporter) ReportHistogramDurationSamples(
}

func (r *statsTestReporter) Capabilities() Capabilities {
return capabilitiesReportingNoTaggingNoHistograms
return capabilitiesReportingNoTagging
}

func (r *statsTestReporter) Flush() {}
Expand Down
4 changes: 0 additions & 4 deletions statsd/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,6 @@ func (r *cactusStatsReporter) Tagging() bool {
return false
}

func (r *cactusStatsReporter) Histograms() bool {
return true
}

func (r *cactusStatsReporter) Flush() {
// no-op
}
1 change: 0 additions & 1 deletion statsd/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,4 @@ func TestCapabilities(t *testing.T) {
r := NewReporter(nil, Options{})
assert.True(t, r.Capabilities().Reporting())
assert.False(t, r.Capabilities().Tagging())
assert.True(t, r.Capabilities().Histograms())
}
3 changes: 0 additions & 3 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,4 @@ type Capabilities interface {

// Tagging returns whether the reporter has the capability for tagged metrics.
Tagging() bool

// Histograms returns whether the reporter has the capability for histogram metrics.
Histograms() bool
}

0 comments on commit 58c90d1

Please sign in to comment.