Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Go package for abstracting stats collection

License

NotificationsYou must be signed in to change notification settings

segmentio/stats

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A Go package for abstracting stats collection.

Installation

go get github.com/segmentio/stats/v5

Migration to v4/v5

Version 4 of the stats package introduced a new way of producing metrics basedon defining struct types with tags on certain fields that define how to interpretthe values. This approach allows for much more efficient metric production as itallows the program to do quick assignments and increments of the struct fields toset the values to be reported, and submit them all with one call to the statsengine, resulting in orders of magnitude faster metrics production. Here's anexample:

typefuncMetricsstruct {callsstruct {countint`metric:"count" type:"counter"`time  time.Duration`metric:"time"  type:"histogram"`    }`metric:"func.calls"`}
t:=time.Now()f()callTime:=time.Since(t)m:=&funcMetrics{}m.calls.count=1m.calls.time=callTime// Equivalent to:////   stats.Incr("func.calls.count")//   stats.Observe("func.calls.time", callTime)//stats.Report(m)

To avoid greatly increasing the complexity of the codebase some old APIs wereremoved in favor of this new approach, other were transformed to provide moreflexibility and leverage new features.

The stats package used to only support float values. Metrics can now be ofvarious numeric types (see stats.MakeMeasure for a detailed description),therefore functions likestats.Add now accept aninterface{} value insteadoffloat64.stats.ObserveDuration was also removed since this new approachmakes it obsolete (durations can be passed tostats.Observe directly).

Thestats.Engine type used to be configured through a configuration objectpassed to its constructor function, and a few methods (likeRegister) wereexposed to mutate engine instances. This required synchronization in order tobe safe to modify an engine from multiple goroutines. We haven't had a use casefor modifying an engine after creating it so the constraint on being thread-safewere lifted and the fields exposed on thestats.Engine struct type directly tocommunicate that they are unsafe to modify concurrently. The helper methodsremain tho to make migration of existing code smoother.

Histogram buckets (mostly used for the prometheus client) are now defined bydefault on thestats.Buckets global variable instead of within the engine.This decoupling was made to avoid paying the cost of doing histogram bucketlookups when producing metrics to backends that don't use them (like datadogor influxdb for example).

The data model also changed a little. Handlers for metrics produced by an enginenow accept a list of measures instead of single metrics, each measure being madeof a name, a set of fields, and tags to apply to each of those fields. Thisallows a more generic and more efficient approach to metric production, betterfits the influxdb data model, while still being compatible with other clients(datadog, prometheus, ...). A single timeseries is usually identified by thecombination of the measure name, a field name and value, and the set of tags seton that measure. Refer to each client for a details about how measures aretranslated to individual metrics.

Note that no changes were made to the end metrics being produced by eachsub-package (httpstats, procstats, ...). This was important as we must keepthe behavior backward compatible since making changes here would implicitlybreak dashboards or monitors set on the various metric collection systems thatthis package supports, potentially causing production issues.

If you find a bug or an API is not available anymore but deserves to be ported feel free to open an issue.

Quick Start

Engine

A core concept of thestats package is theEngine. Every program importingthe package gets a default engine where all metrics produced are aggregated.The program then has to instantiate clients that will consume from the engineat regular time intervals and report the state of the engine to metricscollection platforms.

package mainimport ("github.com/segmentio/stats/v5""github.com/segmentio/stats/v5/datadog")funcmain() {// Creates a new datadog client publishing metrics to localhost:8125dd:=datadog.NewClient("localhost:8125")// Register the client so it receives metrics from the default engine.stats.Register(dd)// Flush the default stats engine on return to ensure all buffered// metrics are sent to the dogstatsd server.deferstats.Flush()// That's it! Metrics produced by the application will now be reported!// ...}

Metrics

package mainimport ("github.com/segmentio/stats/v5""github.com/segmentio/stats/v5/datadog")funcmain() {stats.Register(datadog.NewClient("localhost:8125"))deferstats.Flush()// Increment counters.stats.Incr("user.login")deferstats.Incr("user.logout")// Set a tag on a counter increment.stats.Incr("user.login", stats.Tag{"user","luke"})// ...}

Flushing Metrics

Metrics are stored in a buffer, which will be flushed when it reaches itscapacity.For most use-cases, you do not need to explicitly send out metrics.

If you're producing metrics only very infrequently, you may have metrics thatstay in the buffer and never get sent out. In that case, you can manuallytrigger stats flushes like so:

funcmain() {stats.Register(datadog.NewClient("localhost:8125"))deferstats.Flush()// Force a metrics flush every secondgofunc() {forrangetime.Tick(time.Second) {stats.Flush()      }    }()// ...}

Troubleshooting

Use thedebugstats package to print all stats to the console.

handler:=&debugstats.Client{Dst:os.Stdout}// to use as a standalone engine:engine:=stats.NewEngine("engine-name",handler)engine.Incr("server.start")// or, register on the default stats engine:stats.Register(handler)// Sample output:// server.start:1|c

You can use theGrep property to filter the printed metrics for only ones youcare about:

handler:= debugstats.Client{Dst:os.Stdout,Grep:regexp.MustCompile("server.start")}

Monitoring

Processes

🚧 Go metrics reported with theprocstats package were previously tagged with aversion label that reported the Go runtime version. This label was renamed togo_version in v4.6.0.

Thegithub.com/segmentio/stats/v5/procstatspackage exposes an API for creating a statistics collector on local processes.Statistics are collected for the current process and metrics including Goroutinecount and memory usage are reported.

Here's an example of how to use the collector:

package mainimport ("github.com/segmentio/stats/v5/datadog""github.com/segmentio/stats/v5/procstats")funcmain() {stats.Register(datadog.NewClient("localhost:8125"))deferstats.Flush()// Start a new collector for the current process, reporting Go metrics.c:=procstats.StartCollector(procstats.NewGoMetrics())// Gracefully stops stats collection.deferc.Close()// ...}

One can also collect additional statistics on resource delays, such asCPU delays, block I/O delays, and paging/swapping delays. This capabilityis currently only available on Linux, and can be optionally enabled as follows:

func main() {    // As above...    // Start a new collector for the current process, reporting Go metrics.    c := procstats.StartCollector(procstats.NewDelayMetrics())    defer c.Close()}

HTTP Servers

Thegithub.com/segmentio/stats/v5/httpstatspackage exposes a decorator ofhttp.Handler that automatically adds metriccollection to a HTTP handler, reporting things like request processing time,error counters, header and body sizes...

Here's an example of how to use the decorator:

package mainimport ("net/http""github.com/segmentio/stats/v5/datadog""github.com/segmentio/stats/v5/httpstats")funcmain() {stats.Register(datadog.NewClient("localhost:8125"))deferstats.Flush()// ...http.ListenAndServe(":8080",httpstats.NewHandler(http.HandlerFunc(func(res http.ResponseWriter,req*http.Request) {// This HTTP handler is automatically reporting metrics for all// requests it handles.// ...        }),    ))}

HTTP Clients

Thegithub.com/segmentio/stats/v5/httpstatspackage exposes a decorator ofhttp.RoundTripper which collects and reportsmetrics for client requests the same way it's done on the server side.

Here's an example of how to use the decorator:

package mainimport ("net/http""github.com/segmentio/stats/v5/datadog""github.com/segmentio/stats/v5/httpstats")funcmain() {stats.Register(datadog.NewClient("localhost:8125"))deferstats.Flush()// Make a new HTTP client with a transport that will report HTTP metrics,// set the engine to nil to use the default.httpc:=&http.Client{Transport:httpstats.NewTransport(&http.Transport{},        ),    }// ...}

You can also modify the default HTTP client to automatically get metrics for allpackages using it, this is very convenient to get insights into dependencies.

package mainimport ("net/http""github.com/segmentio/stats/v5/datadog""github.com/segmentio/stats/v5/httpstats")funcmain() {stats.Register(datadog.NewClient("localhost:8125"))deferstats.Flush()// Wraps the default HTTP client's transport.http.DefaultClient.Transport=httpstats.NewTransport(http.DefaultClient.Transport)// ...}

Addendum

By default, the stats library will report the running go version when youinvoke NewEngine() as a metric:

  • go_version with value 1 and atag set to the current version.
  • stats_version with valueand atag` set to the tag value ofsegmentio/stats.

SetSTATS_DISABLE_GO_VERSION_REPORTING totrue in your environment, or setstats.GoVersionReportingEnabled tofalse before collecting any metrics, todisable this behavior.


[8]ページ先頭

©2009-2025 Movatter.jp