stats

package module
v2.2.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2018 License: MIT Imports: 6 Imported by: 1

README

go-stats

GoDoc Build Status

Exposes a Statser interface.

// Statser can submit metrics
type Statser interface {
  // Timing submits a timing metric
  Timing(name string, dur time.Duration, tags ...Tags)
  // Count submits a count metric
  Count(name string, count int64, tags ...Tags)
  // Gauge submits a gauge metric
  Gauge(name string, value float64, tags ...Tags)

  WithPrefix(prefix string) Statser
  WithTags(tags Tags) Statser
  WithTag(tagKey, tagValue string) Statser
}

Usage

There are several New functions that will take an existing metrics collection client and output a Statser, meaning this repo doesn't create the initial client for you.

Datadog Statser

func main() {
  statser := stats.NewDatadogStatser(c)
  ...

  statser.Timing("requests", dur)
}

Global Statser

We can pass around a statser, but we can also set a global default Statser, which can later be retrieved using stats.DefaultStatser().

func main() {
  // Set the default statser
  statser := stats.NewDatadogStatser(c)
  stats.SetDefaultStatser(statser)
  ...

  // Use the default statser
  stats.Timing("requests", dur)
  stats.Count("events", 10)
  stats.Gauge("load", 5)

  // Can also get the default statser
  statser = stats.DefaultStatser()
  statser.Timing("requests", dur)
}

Applying Prefixes/Tags

We can also extend a Statser with prefixes and tags. WithPrefix, WithTag and WithTags all return a new Statser.

Prefixes

statser.WithPrefix("sub-worker").Count("domains", 1000)

Tags

// Single Tag
statser.WithTag("status", "success").Count("request", 1)

// Multiple Tags
statser.WithTags(stats.Tags{
    "status": "failure",
    "code": "400",
}).Count("request", 1)

Sampling

When a Statser is called many times in a small period of time, UDP overhead can become significant enough to warrant sampling. Use a sampled Statser to lower the number of outgoing requests.

// Set a Sample Rate of 1%
sampledStatser := stats.WithSample(statser, 0.01)

// Timing will only be called once every 100 calls
sampledStatser.Timing("request", time.Since(start))

// Count will only be called once every 100 calls
// the count will be adjusted (1 -> 100)
// according to the sample rate
sampledStatser.Count("request", 1)

Logging

At times, it can be useful, mostly for debugging purposes, to wrap a statser with some logging functionality.

// Assuming we have `logger` which conform to the stats.Logger interface
// This is usually applicable to logrus and friends

// Apply the logger to the statser
loggedStatser := stats.WithLogger(statser, logger).WithPrefix("test")

// Calls to the statser will be logged via the given logger
loggedStatser.Count("event", 1, stats.Tags{"key": "value"})

// expected output
// test.event [key=value] - 1

Example Usage

ddStatsd, _ := statsd.New(ddEndpoint)
statser := stats.NewDatadogStatser(ddStatsd)
statser = statser.WithPrefix("subdomain-discovery").WithTag("worker", workerType)
stats.SetDefaultStatser(statser)

type Worker struct {
    statser stats.Statser
}

func NewWorker() *Worker {
    return &Worker{
        statser: stats.DefaultStatser().WithPrefix("discoverer"),
    }
}

func (w *Worker) DoWork() {
    startTime := time.Now()
    ...
    w.statser.WithTag("status", workStatus).Timing("work", time.Since(startTime))
}

Utilities - Timer/Counter

Timer

func main() {
  statser := stats.NewDatadogStatser(c)
  ...

  // Create a new timer
  timer := stats.NewTimer("requests", tags)
  defer timer.Finish(statser) // use `nil` for default statser
  // OR
  d := timer.Finish(statser) // if you need to use the duration
  ...
}

Counter

func main() {
  statser := stats.NewDatadogStatser(c)
  ...

  // Create a new counter
  counter := stats.NewCounter("events", tags)

  // Do stuff that increment count
  counter.Inc(3)
  ...

  // if you need to know what the count was increased to
  c := counter.Inc(1)

  counter.Finish(statser) // use `nil` for default statser
  // OR
  c := counter.Finish(statser) // if you need the final count
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Count

func Count(name string, count int64, tags ...Tags)

Count submits a count metric using the default statser

func Gauge

func Gauge(name string, value float64, tags ...Tags)

Gauge submits a gauge metric using the default statser

func SetDefaultStatser

func SetDefaultStatser(s Statser)

SetDefaultStatser sets the default statser

func Timing

func Timing(name string, dur time.Duration, tags ...Tags)

Timing submits a timing metric using the default statser

Example
// suppose we have a Statser
var s Statser = &MockStatser{}

startTime := time.Now()

// now Statser has WithPrefix, WithTags and WithTag and they all return Statser
s = s.WithPrefix("api").
	WithTags(Tags{
		"route":  "/ping",
		"status": "200",
	}).
	WithTag("env", "qa")

// without tags
s.Timing("request", time.Since(startTime))

// with tags
s.Timing("request", time.Since(startTime), Tags{"i haz": "tagz"})

// also can do
s.WithTag("i haz", "more tagz").Timing("request", time.Since(startTime))
Output:

Types

type Counter

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

Counter is a wrapper around the Count method

func NewCounter

func NewCounter(name string, tags ...Tags) *Counter

NewCounter creates a new Counter

func (*Counter) Finish

func (c *Counter) Finish(s Statser) int64

Finish submits a count metric to the given statser or uses the default statser if none given. returns the accumulated count

func (*Counter) Inc

func (c *Counter) Inc(count int64) int64

Inc increments the counter by `count` and returns the accumulated count

type Logger added in v1.0.7

type Logger interface {
	Printf(format string, args ...interface{})
}

Logger is an interface for simple loggers It should be already satisfied by most common loggers

type MockStatser

type MockStatser struct {
	TimingFn func(name string, dur time.Duration, tags ...Tags)
	CountFn  func(name string, count int64, tags ...Tags)
	GaugeFn  func(name string, value float64, tags ...Tags)
}

MockStatser is a mockable Statser

func (*MockStatser) Count

func (s *MockStatser) Count(name string, count int64, tags ...Tags)

Count will call the underlying Count method

func (*MockStatser) Gauge

func (s *MockStatser) Gauge(name string, value float64, tags ...Tags)

Gauge will call the underlying Gauge method

func (*MockStatser) Timing

func (s *MockStatser) Timing(name string, dur time.Duration, tags ...Tags)

Timing will call the underlying Timing method

func (*MockStatser) WithPrefix

func (s *MockStatser) WithPrefix(prefix string) Statser

func (*MockStatser) WithTag

func (s *MockStatser) WithTag(tagKey, tagValue string) Statser

func (*MockStatser) WithTags

func (s *MockStatser) WithTags(tags Tags) Statser

type Statser

type Statser interface {
	// Timing submits a timing metric
	Timing(name string, dur time.Duration, tags ...Tags)
	// Count submits a count metric
	Count(name string, count int64, tags ...Tags)
	// Gauge submits a gauge metric
	Gauge(name string, value float64, tags ...Tags)

	WithPrefix(prefix string) Statser
	WithTags(tags Tags) Statser
	WithTag(tagKey, tagValue string) Statser
}

Statser can submit metrics

func DefaultStatser

func DefaultStatser() Statser

DefaultStatser should return the currently set default statser

func NewDatadogStatser

func NewDatadogStatser(ddEndpoint string) (Statser, error)

NewDatadogStatser creates a new Datadog Statser

func NewNOOPStatser

func NewNOOPStatser() Statser

NewNOOPStatser returns a statser that does nothing.

func WithLogger added in v1.0.7

func WithLogger(statser Statser, logger Logger) Statser

WithLogger wraps an existing Statser so that stats get logged

func WithPrefix

func WithPrefix(statser Statser, prefix string) Statser

WithPrefix returns a new Statser with the given prefix applied to the name of the metrics E.g. WithPrefix(s, "prefix").Count("suffix", ...) will create a metric with name "prefix.suffix" WithPrefix can be called multiple times (See example in test code)

func WithSample

func WithSample(statser Statser, rate float64) Statser

WithSample returns a new Statser that samples stat submissions

func WithTag

func WithTag(statser Statser, tagKey, tagValue string) Statser

WithTag will call WithTags with a map containing the given tag key-value pair

func WithTags

func WithTags(statser Statser, tags Tags) Statser

WithTags returns a new Statser which will always output the given tags in its metrics Further calls are able to overwrite previously set values

type Tags

type Tags map[string]string

type Timer

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

Timer is a wrapper around the Timing method

func NewTimer

func NewTimer(name string, tags ...Tags) *Timer

NewTimer creates a new Timer

func (*Timer) Finish

func (t *Timer) Finish(s Statser) time.Duration

Finish submits a timing metric to the given statser or uses the default statser if none given

Jump to

Keyboard shortcuts

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