metric

package
v0.0.0-...-059b1e2 Latest Latest
Warning

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

Go to latest
Published: May 10, 2021 License: MIT Imports: 7 Imported by: 9

README

gone/metric

Fast Golang metrics library GoDoc GoReportCard Coverage

Package gone/metric is an expandable library for metrics. Initially only a sink for sending data to statsd is implemented.

The design goals:

  • Basic statsd metric types (gauge, counter, timer)
  • Client side buffered if needed.
  • Fast

Timer and Histogram is basically the same except for the argument type.

Counter is reset to zero on each flush. Gauges are not.

Permanent and ad-hoc meters

The library provides APIs for generating metrics events.

If you need Permanent meters (gauges/counters/timers...) which will be updated often with lots of data and want to use the lock free client side buffering to make it really fast, you can create explicit gauge/counter/timer/histogram objects using the client.RegisterXXX() methods.

If you, on the other hand, rarely record a metric event more than once, but have a lot of different named events, you can bypass the buffering data structures and send the metric event directly to the sink by using client.AdhocGauge(), client.AdhocCount(), client.AdhocTime() ...

Such direct recording of metrics events will still (depending on sink implementation) be bufferend in the protocol layer - unless you request an explicit flush.

This is maybe best illustrated with a Counter example:

If you do:

{
    client := metric.NewClient(sink)
    counter := client.RegisterCounter("name")
    counter.Inc(1)
    counter.Inc(1)
}

Then buffering will only send an increase of "2" to the sink - and only put it on the wire when the sink flushes.

On the other hand, if you do:

{
    client.AdhocCount("name",1, false)
    client.AdhocCount("name",1, true)
}

Then both metric events will be sent to the sink and the latter will also ask the sink to flush data to the wire immediately.

Example

package main

import (
	"github.com/One-com/gone/metric"
	"github.com/One-com/gone/metric/sink/statsd"
	"log"
	"time"
)

func main() {

	flushPeriod  := metric.FlushInterval(4*time.Second)
	timerFlushPeriod := metric.FlushInterval(2*time.Second)

	var sink metric.Sink
	var err error

	sink, err = statsd.New(
		statsd.Buffer(512),
		//statsd.Peer("statsdhost:8125"), // uncomment to send UDP data.
		statsd.Prefix("prefix"))
	if err != nil {
		log.Fatal(err)
	}

	client := metric.NewClient(sink, flushPeriod)

	gauge   := client.RegisterGauge("gauge")
	timer   := client.RegisterTimer("timer", timerFlushPeriod)
	histo   := client.RegisterHistogram("histo")
	counter := client.RegisterCounter("counter")  // all using default client flushperiod

	client.Start()

	var g int
	for g < 100 {
		counter.Inc(1)
		gauge.Set(uint64(g))
		timer.Sample(time.Duration(g)*time.Millisecond)
		histo.Sample(int64(g))

		time.Sleep(time.Second)
		g++
	}
	client.Stop()
	client.Flush()
}

Documentation

Overview

Package metric is a generic metric package for the standard metric types gauges/counters/timers/histograms. It ships with a statsd sink implementation, but can be extended with new sinks.

This implementation is aimed at being as fast as possible to not discourage metrics on values in hotpaths just because of locking overhead. This requires some client side buffering (and flusher go-routines) and, especially for the timer/histogram event type, a relatively large data structure to create a ring-buffer with mostly lock-free writes. (it uses condition variables for flushing). This design is for the use case where you have a lot of timer/histogram metric events going to a few buckets.

The API consists of 3 main types of objects:

  • Meter - the object doing the actual measuring. (possibly buffering measurements)
  • Sink - an object to which Meter readings can be sent. Sinks can have internal buffering which can be flushed
  • Client - an object responsible for sending Meter readings to an assigned Sink, possibly at configured flushing intervals.

The API supports 3 approaches to maintaining your metrics:

Ad-hoc

Ad-hoc generation of metric events without a Meter object (explicitly flushing the Client sink): This is a relative slow, but simple way to generate metric data. This allows for use cases where you don't have a small set of known metrics receiving many events, but rather many metrics receiving few events each:

metric.SetDefaultSink(sink)
metric.AdhocGauge("gauge", 17, true)

Manually

Manually making readings of a meter directly to a Sink. (use this only if strictly needed)

gauge := metric.NewGauge("gauge")
gauge.Set(17)
gauge.FlushReading(sink)
sink.Flush()

Managed

Registring a buffered Meter object with a client. This is the fastest method. The low latency API is accessed via Client objects. (There's a default global client). The speed is achieved by creating permanent buffering metrics objects for each metric.

client := metric.NewClient(sink, metric.FlushInterval(time.Second))
gauge := client.RegisterGauge("gauge")
gauge.Set(17)

The statsd sink also does client side buffering before sending UDP packages and is flushed when asked, or when running full. You can set the max size of the UDP datagrams created.

Index

Examples

Constants

View Source
const (
	MeterGauge     = iota // A client side maintained value
	MeterCounter          // A server side maintained value
	MeterHistogram        // A general distribution of measurements events.
	MeterTimer            // ... when those measurements are milliseconds
	MeterSet              // free form string events
)

Conceptual meter types Gauge: A client side maintained counter Counter: A server side maintained counter Historam: A series of events analyzed on the server Timer: A series of time.Duration events analyzed on the server Set: Discrete strings added to a set maintained on the server

Variables

This section is empty.

Functions

func AdhocCount

func AdhocCount(name string, val int, flush bool)

AdhocCount creates an ad-hoc counter metric event at the default client. If flush is true, the sink will be instructed to flush data immediately

func AdhocGauge

func AdhocGauge(name string, val uint64, flush bool)

AdhocGauge creates an ad-hoc gauge metric event at the default client. If flush is true, the sink will be instructed to flush data immediately

func AdhocSample

func AdhocSample(name string, val int64, flush bool)

AdhocSample creates an ad-hoc histogram metric event at the default client. If flush is true, the sink will be instructed to flush data immediately

func AdhocSetMember

func AdhocSetMember(name string, member string, flush bool)

AdhocSetMember generates an ad-hoc set membership event with the default client. If flush is true, the sink will be instructed to flush data immediately

func AdhocTime

func AdhocTime(name string, d time.Duration, flush bool)

AdhocTime creates an ad-hoc timer metric event at the default client. If flush is true, the sink will be instructed to flush data immediately

func Flush

func Flush()

Flush calls Flush() on the default client.

func Mark

func Mark(name string)

Mark - send a ad-hoc zero histogram event at the default client. - see Client.Mark()

func SetDefaultOptions

func SetDefaultOptions(opts ...MOption)

SetDefaultOptions sets options on the default metric client

func SetDefaultSink

func SetDefaultSink(sink Sink)

SetDefaultSink sets the sink for the default metics client The default client has no sink set initially. You need to set it calling this function.

func Start

func Start()

Start the default Client if stopped.

func Stop

func Stop()

Stop the global default metrics Client

Types

type Client

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

Client is the main object the applications holds to do metrics. It can be used directly for ad-hoc events, or be used to create persistent gauge/conter/timer/... objects optimised for bulk metric generation. A default metric Client with no FlushInterval set is Start()'ed by init()

func Default

func Default() *Client

Default returns the default metric Client

func NewClient

func NewClient(sink Sink, opts ...MOption) (client *Client)

NewClient returns you a client handle directly if you do not want to use the global default client. This creates a new metric client with a factory object for the sink. If sink == nil, the client will not emit metrics until a Sink is set using SetSink.

Example
package main

import (
	"github.com/One-com/gone/metric"
	"github.com/One-com/gone/metric/sink/statsd"
	"log"
	"time"

	"os"
)

func main() {

	sink, err := statsd.New(
		statsd.Buffer(512),
		statsd.Output(os.Stdout),
		statsd.Prefix("prefix"))
	if err != nil {
		log.Fatal(err)
	}

	c := metric.NewClient(sink)

	gauge1 := c.RegisterGauge("gauge1")
	gauge2 := metric.NewGauge("gauge2")
	c.Register(gauge2)
	counter := c.RegisterCounter("counter")
	timer := c.RegisterTimer("timer")
	histo := c.RegisterHistogram("histo")

	gauge1.Set(17)
	gauge2.Set(18)
	counter.Inc(1)
	timer.Sample(time.Duration(10 * time.Millisecond))
	histo.Sample(17)

	c.Flush()
}
Output:

prefix.gauge1:17|g
prefix.gauge2:18|g
prefix.counter:1|c
prefix.timer:10|ms
prefix.histo:17|ms

func (*Client) AdhocCount

func (c *Client) AdhocCount(name string, val int, flush bool)

AdhocCount creates an ad-hoc counter metric event. If flush is true, the sink will be instructed to flush data immediately

func (*Client) AdhocGauge

func (c *Client) AdhocGauge(name string, val uint64, flush bool)

AdhocGauge creates an ad-hoc gauge metric event. If flush is true, the sink will be instructed to flush data immediately

func (*Client) AdhocSample

func (c *Client) AdhocSample(name string, val int64, flush bool)

AdhocSample creates an ad-hoc histogram metric event. If flush is true, the sink will be instructed to flush data immediately

func (*Client) AdhocSetMember

func (c *Client) AdhocSetMember(name string, member string, flush bool)

AdhocSetMember creates an ad-hoc set membership event. If flush is true, the sink will be instructed to flush data immediately

func (*Client) AdhocTime

func (c *Client) AdhocTime(name string, d time.Duration, flush bool)

AdhocTime creates an ad-hoc timer metric event. If flush is true, the sink will be instructed to flush data immediately

func (*Client) Deregister

func (c *Client) Deregister(m Meter) error

Deregister detaches a Meter (gauge/counter/timer...) from the client. It will no longer be flushed. An error is returned if the Meter was not registered.

func (*Client) Flush

func (c *Client) Flush()

Flush the client default so no data is left in any pipeline buffers.

func (*Client) Mark

func (c *Client) Mark(name string)

Mark - send a ad-hoc zero histogram event immediately to allow the server side to indicate a unique event happened. This equivalent to calling Sample(name, 0, true) and can be used as a poor mans way to make qualitative events to be marked in the overall view of metrics. Like "process restart". Graphical views might allow you to draw these as special marks. For some sinks (like statsd) there's not dedicated way to send such events. Mark is equivalent to AdhocSample(name, 0, true)

func (*Client) Register

func (c *Client) Register(m Meter, opts ...MOption)

Register a Meter with the client, finding a flusher with the appropriate interval, if possible, else create a new flusher.

func (*Client) RegisterCounter

func (c *Client) RegisterCounter(name string, opts ...MOption) *Counter

RegisterCounter is equivalent to Register(NewCounter(), opts) with the default Client.

func (*Client) RegisterGauge

func (c *Client) RegisterGauge(name string, opts ...MOption) *GaugeUint64

RegisterGauge is equivalent to Register(NewGauge(), opts) with the default Client.

func (*Client) RegisterHistogram

func (c *Client) RegisterHistogram(name string, opts ...MOption) Histogram

RegisterHistogram is equivalent to Register(NewHistogram(), opts) with the default Client.

func (*Client) RegisterSet

func (c *Client) RegisterSet(name string, opts ...MOption) *Set

func (*Client) RegisterTimer

func (c *Client) RegisterTimer(name string, opts ...MOption) Timer

RegisterTimer is equivalent to Register(NewTimer(), opts) with the default Client.

func (*Client) SetOptions

func (c *Client) SetOptions(opts ...MOption)

SetOptions sets options on a client - like the flush interval for metrics which haven't them selves a fixed flush interval

func (*Client) SetSink

func (c *Client) SetSink(sink Sink)

SetSink sets the Sink factory of the client. You'll need to set a sink before any metrics will be emitted.

func (*Client) Start

func (c *Client) Start()

Start a stopped client

func (*Client) Stop

func (c *Client) Stop()

Stop a Client from flushing data. If any autoFlusher meters are still in use they will still flush when overflown.

type Counter

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

Counter is different from a GaugeInt64 in that it is reset to zero every time its flushed - and thus being server-side maintained.

func NewCounter

func NewCounter(name string) *Counter

NewCounter returns a client side buffered counter (a counter is a server side maintained value). "Server side" meaning that it's reset to 0 every time it's sent to the server and the total tally is kept on the server. This poses the risk of the server-side absolute value to drift in case of increments lost in transit. However, it also allows several distributed processes to update the same counter. If you want to have a pure client side counter, use GaugeInt64

func RegisterCounter

func RegisterCounter(name string, opts ...MOption) *Counter

RegisterCounter is equivalent to Register(NewCounter(), opts) with the default Client.

func (*Counter) Dec

func (c *Counter) Dec(i int64)

Dec decreased the counter by the supplied value

func (*Counter) FlushReading

func (c *Counter) FlushReading(s Sink)

FlushReading flushes the accumulated counter value to the supplied Sink

func (*Counter) Inc

func (c *Counter) Inc(i int64)

Inc increased the counter by the supplied value

func (*Counter) Name

func (c *Counter) Name() string

Name returns the name of the counter

type GaugeFloat64

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

GaugeFloat64 is a float64 gauge which stores its value as a uint64 to implement FlushReading() fast (saving an interface allocation)

func NewGaugeFloat64

func NewGaugeFloat64(name string) *GaugeFloat64

NewGaugeFloat64 creates a gauge holding a Float64 value.

func (*GaugeFloat64) FlushReading

func (g *GaugeFloat64) FlushReading(s Sink)

FlushReading sends the current gauge value to the Sink

func (*GaugeFloat64) Name

func (g *GaugeFloat64) Name() string

Name returns the name of the gauge

func (*GaugeFloat64) Set

func (g *GaugeFloat64) Set(v float64)

Set updates the gauge's value.

func (*GaugeFloat64) Value

func (g *GaugeFloat64) Value() float64

Value returns the gauge's current value.

type GaugeInt64

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

GaugeInt64 is a gauge using an int64 - meaning it can be decremented to negaive values

func NewGaugeInt64

func NewGaugeInt64(name string) *GaugeInt64

NewGaugeInt64 creates a int64 Gauge. Can be used as a go-metric client side gauge or counter

func (*GaugeInt64) Dec

func (g *GaugeInt64) Dec(i int64)

Dec decrements the counter by the given amount.

func (*GaugeInt64) FlushReading

func (g *GaugeInt64) FlushReading(s Sink)

FlushReading sends the gauge value to the sink

func (*GaugeInt64) Inc

func (g *GaugeInt64) Inc(i int64)

Inc increments the counter by the given amount.

func (*GaugeInt64) Name

func (g *GaugeInt64) Name() string

Name returns the name of the gauge.

func (*GaugeInt64) Set

func (g *GaugeInt64) Set(val int64)

Set sets the gauge value

func (*GaugeInt64) Value

func (g *GaugeInt64) Value() int64

Value returns the current gauge value

type GaugeUint64

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

GaugeUint64 is the default gauge type using a uint64

func NewGauge

func NewGauge(name string) *GaugeUint64

NewGauge is alias for NewGaugeUint64

func NewGaugeUint64

func NewGaugeUint64(name string) *GaugeUint64

NewGaugeUint64 returns a standard gauge.

func RegisterGauge

func RegisterGauge(name string, opts ...MOption) *GaugeUint64

RegisterGauge is equivalent to Register(NewGauge(), opts) with the default Client.

func (*GaugeUint64) Dec

func (g *GaugeUint64) Dec(i int64)

Dec will decrement the gauge value

func (*GaugeUint64) FlushReading

func (g *GaugeUint64) FlushReading(s Sink)

FlushReading to implement Meter interface

func (*GaugeUint64) Inc

func (g *GaugeUint64) Inc(i uint64)

Inc will increment the gauge value

func (*GaugeUint64) Name

func (g *GaugeUint64) Name() string

Name to implement Meter interface

func (*GaugeUint64) Set

func (g *GaugeUint64) Set(val uint64)

Set will update the gauge value

func (*GaugeUint64) Value

func (g *GaugeUint64) Value() uint64

Value returns the gauge value

type Histogram

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

Histogram is a series of int64 events all sent to the server

func NewHistogram

func NewHistogram(name string) Histogram

NewHistogram creates a new persistent metric object measuring arbitrary sample values by allocating a client side FIFO buffer for recording and flushing measurements

func RegisterHistogram

func RegisterHistogram(name string, opts ...MOption) Histogram

RegisterHistogram is equivalent to Register(NewHistogram(), opts) with the default Client.

func (Histogram) FlushReading

func (e Histogram) FlushReading(s Sink)

FlushReading - flush as much as possible.

func (Histogram) Name

func (e Histogram) Name() string

func (Histogram) Sample

func (e Histogram) Sample(d int64)

Sample records new event for the histogram

type MConfig

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

MConfig holds configuration state for metric clients. This is an internal type.

type MOption

type MOption func(MConfig)

MOption is a function manipulating configuration state for a metrics Client.

func FlushInterval

func FlushInterval(d time.Duration) MOption

FlushInterval returns a configuration option for a metrics Client. Provide this to NewClient or to Register*

type Meter

type Meter interface {
	Name() string
	FlushReading(Sink) // Read the meter, by flushing all unread values.
}

Meter is a measurement instrument - a named metric. It measures stuff and can be registered with a client to be periodically reported to the Sink. This interface doesn't describe how measurements are done. That depends on the specific meter it self. This interface only makes the Client able to flush/read the meter to a sink.

type Set

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

Set is a not too efficient implementation of that statsd "set" concept. The client will send set membership notifications. Statsd will periodically further propagate the current set size as a gauge. It is client side buffered for the use cases where there will be a lot of membership Add events for the same Set member. This is often not the case, so the AdHocSetMember is often a simpler solution.

func NewSet

func NewSet(name string) *Set

NewSet creates a new named Set object

func (*Set) Add

func (s *Set) Add(val string)

Add a member to the set.

func (*Set) FlushReading

func (s *Set) FlushReading(f Sink)

Flush sends the current set members to the Sink and resets the Set to empty.

func (*Set) Name

func (s *Set) Name() string

Name returns the name of the Set

type Sink

type Sink interface {
	// Record a named value of any time with the Sink
	Record(mtype int, name string, value interface{})
	// RecordNumeric64 is a performance optimation for recording 64-bit values
	// using the num64 internal sub-package to create a "union" type for
	// int/uint/float 64 bit values.
	// Due to the nature of the metric event FIFO queue, using an interface{}
	// would have requires an additional heap-allocation due to escape analysis
	// not being able to guarantee the values can be stack allocated.
	RecordNumeric64(mtype int, name string, value num64.Numeric64)

	// Flush flushes the record values from the program internal Sink buffers.
	Flush()
}

Sink is a sink for metrics data which methods need to be go-routine safe

type Timer

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

Timer is like Histogram, but the event is a time.Duration. values are remembered as milliseconds

func NewTimer

func NewTimer(name string) Timer

NewTimer creates a new persistent metric object measuring timing values. by allocating a client side FIFO buffer for recording and flushing measurements

func RegisterTimer

func RegisterTimer(name string, opts ...MOption) Timer

RegisterTimer is equivalent to Register(NewTimer(), opts) with the default Client.

func (Timer) FlushReading

func (e Timer) FlushReading(s Sink)

FlushReading - flush as much as possible.

func (Timer) Name

func (e Timer) Name() string

func (Timer) Sample

func (e Timer) Sample(d time.Duration)

Sample records a new duration event.

Directories

Path Synopsis
sink

Jump to

Keyboard shortcuts

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