go-stats
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)
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)
}
Also available: stats.NewInfluxDBStatser
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)
// 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)
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
...
}
Counter
func main() {
statser := stats.NewDatadogStatser(c)
...
// Create a new counter
counter := stats.NewCounter("events", tags)
// Do stuff that increment count
counter.Inc(3)
...
counter.Finish(statser) // use `nil` for default statser
}