All Projects → segmentio → Stats

segmentio / Stats

Licence: mit
Go package for abstracting stats collection

Programming Languages

go
31211 projects - #10 most used programming language
golang
3204 projects

Projects that are alternatives of or similar to Stats

Opencensus Java
A stats collection and distributed tracing framework
Stars: ✭ 640 (+290.24%)
Mutual labels:  metrics, prometheus, stats
Node Measured
A Node metrics library for measuring and reporting application-level metrics, inspired by Coda Hale, Yammer Inc's Dropwizard Metrics Libraries
Stars: ✭ 500 (+204.88%)
Mutual labels:  metrics, prometheus, datadog
Datav
📊https://datav.io is a modern APM, provide observability for your business, application and infrastructure. It's also a lightweight alternative to Grafana.
Stars: ✭ 2,757 (+1581.1%)
Mutual labels:  metrics, prometheus, datadog
Graylog Plugin Metrics Reporter
Graylog Metrics Reporter Plugins
Stars: ✭ 71 (-56.71%)
Mutual labels:  metrics, prometheus, datadog
Prometheus To Cloudwatch
Utility for scraping Prometheus metrics from a Prometheus client endpoint and publishing them to CloudWatch
Stars: ✭ 127 (-22.56%)
Mutual labels:  metrics, prometheus
Starlette Prometheus
Prometheus integration for Starlette.
Stars: ✭ 127 (-22.56%)
Mutual labels:  metrics, prometheus
Go Http Metrics
Go modular http middleware to measure HTTP requests independent of metrics backend (with Prometheus and OpenCensus as backend implementations) and http framework/library
Stars: ✭ 128 (-21.95%)
Mutual labels:  metrics, prometheus
Prometheus Sql
Service that exposes Prometheus metrics for a SQL result set.
Stars: ✭ 140 (-14.63%)
Mutual labels:  metrics, prometheus
Bigbluebutton Exporter
Prometheus exporter for BigBlueButton
Stars: ✭ 117 (-28.66%)
Mutual labels:  metrics, prometheus
Sidekiq Prometheus Exporter
All the basic metrics of Sidekiq with pluggable contribs prepared for Prometheus
Stars: ✭ 129 (-21.34%)
Mutual labels:  metrics, prometheus
Influxdb exporter
A server that accepts InfluxDB metrics via the HTTP API and exports them via HTTP for Prometheus consumption
Stars: ✭ 159 (-3.05%)
Mutual labels:  metrics, prometheus
Opencensus Csharp
Distributed tracing and stats collecting framework
Stars: ✭ 126 (-23.17%)
Mutual labels:  metrics, stats
Promplot
Create plots from Prometheus metrics and send them to you
Stars: ✭ 125 (-23.78%)
Mutual labels:  metrics, prometheus
Ecs Exporter
Export AWS ECS cluster metrics to Prometheus
Stars: ✭ 127 (-22.56%)
Mutual labels:  metrics, prometheus
Rabbitmq Prometheus
A minimalistic Prometheus exporter of core RabbitMQ metrics
Stars: ✭ 124 (-24.39%)
Mutual labels:  metrics, prometheus
Cerebral
Kubernetes cluster autoscaler with pluggable metrics backends and scaling engines
Stars: ✭ 138 (-15.85%)
Mutual labels:  metrics, prometheus
Pagespeed exporter
Prometheus pagespeed exporter
Stars: ✭ 149 (-9.15%)
Mutual labels:  metrics, prometheus
Bricks
A standard library for microservices.
Stars: ✭ 142 (-13.41%)
Mutual labels:  metrics, prometheus
Opencensus Go
A stats collection and distributed tracing framework
Stars: ✭ 1,895 (+1055.49%)
Mutual labels:  prometheus, stats
Stackdriver exporter
Google Stackdriver Prometheus exporter
Stars: ✭ 164 (+0%)
Mutual labels:  metrics, prometheus

stats CircleCI Go Report Card GoDoc

A Go package for abstracting stats collection.

Installation

go get github.com/segmentio/stats/v4

Migration to v4

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

type funcMetrics struct {
    calls struct {
        count int           `metric:"count" type:"counter"`
        time  time.Duration `metric:"time"  type:"histogram"`
    } `metric:"func.calls"`
}
t := time.Now()
f()
callTime := time.Now().Sub(t)

m := &funcMetrics{}
m.calls.count = 1
m.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 were removed in favor of this new approach, other were transformed to provide more flexibility and leverage new features.

The stats package used to only support float values, metrics can now be of various numeric types (see stats.MakeMeasure for a detailed description), therefore functions like stats.Add now accept an interface{} value instead of float64. stats.ObserveDuration was also removed since this new approach makes it obsolete (durations can be passed to stats.Observe directly).

The stats.Engine type used to be configured through a configuration object passed to its constructor function, and a few methods (like Register) were exposed to mutate engine instances. This required synchronization in order to be safe to modify an engine from multiple goroutines. We haven't had a use case for modifying an engine after creating it so the constraint on being thread-safe were lifted and the fields exposed on the stats.Engine struct type directly to communicate that they are unsafe to modify concurrently. The helper methods remain tho to make migration of existing code smoother.

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

The data model also changed a little. Handlers for metrics produced by an engine now accept a list of measures instead of single metrics, each measure being made of a name, a set of fields, and tags to apply to each of those fields. This allows a more generic and more efficient approach to metric production, better fits the influxdb data model, while still being compatible with other clients (datadog, prometheus, ...). A single timeseries is usually identified by the combination of the measure name, a field name and value, and the set of tags set on that measure. Refer to each client for a details about how measures are translated to individual metrics.

Note that no changes were made to the end metrics being produced by each sub-package (httpstats, procstats, ...). This was important as we must keep the behavior backward compatible since making changes here would implicitly break dashboards or monitors set on the various metric collection systems that this 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 the stats package is the Engine. Every program importing the package gets a default engine where all metrics produced are aggregated. The program then has to instantiate clients that will consume from the engine at regular time intervals and report the state of the engine to metrics collection platforms.

package main

import (
    "github.com/segmentio/stats/v4"
    "github.com/segmentio/stats/v4/datadog"
)

func main() {
    // Creates a new datadog client publishing metrics to localhost:8125
    dd := 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.
    defer stats.Flush()

    // That's it! Metrics produced by the application will now be reported!
    // ...
}

Metrics

package main

import (
    "github.com/segmentio/stats/v4"
    "github.com/segmentio/stats/v4/datadog"
)

func main() {
    stats.Register(datadog.NewClient("localhost:8125"))
    defer stats.Flush()

    // Increment counters.
    stats.Incr("user.login")
    defer stats.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 its capacity. 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 that stay in the buffer and never get sent out. In that case, you can manually trigger stats flushes like so:

func main() {
    stats.Register(datadog.NewClient("localhost:8125"))
    defer stats.Flush()

    // Force a metrics flush every second
    go func() {
      for range time.Tick(time.Second) {
        stats.Flush()
      }
    }()

    // ...
}

Monitoring

Processes

🚧 Go metrics reported with the procstats package were previously tagged with a version label that reported the Go runtime version. This label was renamed to go_version in v4.6.0.

The github.com/segmentio/stats/procstats package exposes an API for creating a statistics collector on local processes. Statistics are collected for the current process and metrics including Goroutine count and memory usage are reported.

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

package main

import (
    "github.com/segmentio/stats/v4/datadog"
    "github.com/segmentio/stats/v4/procstats"
)


func main() {
     stats.Register(datadog.NewClient("localhost:8125"))
     defer stats.Flush()

    // Start a new collector for the current process, reporting Go metrics.
    c := procstats.StartCollector(procstats.NewGoMetrics())

    // Gracefully stops stats collection.
    defer c.Close()

    // ...
}

One can also collect additional statistics on resource delays, such as CPU delays, block I/O delays, and paging/swapping delays. This capability is 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

The github.com/segmentio/stats/httpstats package exposes a decorator of http.Handler that automatically adds metric collection 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 main

import (
    "net/http"

    "github.com/segmentio/stats/v4/datadog"
    "github.com/segmentio/stats/v4/httpstats"
)

func main() {
     stats.Register(datadog.NewClient("localhost:8125"))
     defer stats.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

The github.com/segmentio/stats/httpstats package exposes a decorator of http.RoundTripper which collects and reports metrics for client requests the same way it's done on the server side.

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

package main

import (
    "net/http"

    "github.com/segmentio/stats/v4/datadog"
    "github.com/segmentio/stats/v4/httpstats"
)

func main() {
     stats.Register(datadog.NewClient("localhost:8125"))
     defer stats.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 all packages using it, this is very convinient to get insights into dependencies.

package main

import (
    "net/http"

    "github.com/segmentio/stats/v4/datadog"
    "github.com/segmentio/stats/v4/httpstats"
)

func main() {
     stats.Register(datadog.NewClient("localhost:8125"))
     defer stats.Flush()

    // Wraps the default HTTP client's transport.
    http.DefaultClient.Transport = httpstats.NewTransport(http.DefaultClient.Transport)

    // ...
}

Redis

The github.com/segmentio/stats/redisstats package exposes:

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

package main

import (
    "github.com/segmentio/redis-go"
    "github.com/segmentio/stats/v4/redisstats"
)

func main() {
    stats.Register(datadog.NewClient("localhost:8125"))
    defer stats.Flush()

    client := redis.Client{
        Addr:      "127.0.0.1:6379",
        Transport: redisstats.NewTransport(&redis.Transport{}),
    }

    // ...
}

And on the server side:

package main

import (
    "github.com/segmentio/redis-go"
    "github.com/segmentio/stats/v4/redisstats"
)

func main() {
    stats.Register(datadog.NewClient("localhost:8125"))
    defer stats.Flush()

    handler := redis.HandlerFunc(func(res redis.ResponseWriter, req *redis.Request) {
      // Implement handler function here
    })

    server := redis.Server{
        Handler: redisstats.NewHandler(&handler),
    }

    server.ListenAndServe()

    // ...
}
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].