metrics

package
v1.0.3 Latest Latest
Warning

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

Go to latest
Published: May 16, 2024 License: Apache-2.0, BSD-2-Clause, BSD-3-Clause, + 2 more Imports: 6 Imported by: 18

README

English | 中文

Metrics

Metrics are can be simply understood as a series of numerical measurements. Different applications require different measurements. For example, For a web server, it might be request times; for a database, it might be the number of active connections or active queries, and so on.

Metrics play a crucial role in understanding why your application works in a certain way. Suppose you are running a web application and find it running slowly. To understand what happened to your application, you need some information. For example, the application may slow down when the number of requests is high. If you have request count metrics, you can determine the cause and increase the number of servers to handle the load.

Metric types

Metrics can be categorized into unidimensional and multidimensional based on their data dimensions.

Unidimensional metrics

Unidimensional metrics consist of three parts: metric name, metric value, and metric aggregation policy. A metric name uniquely identifies a unidimensional monitoring metric. The metric aggregation policy describes how to aggregate metric values, such as summing, averaging, maximizing, and minimizing. For example, if you want to monitor the average CPU load, you can define and report a unidimensional monitoring metric with the metric name "cpu.avg.load":

import (
    "trpc.group/trpc-go/trpc-go/log"
    "trpc.group/trpc-go/trpc-go/metrics"
)

if err := metrics.ReportSingleDimensionMetrics("cpu.avg.load", 70.0, metrics.PolicyAVG); err ! = nil {
    log.Infof("reporting cpu.avg.load metric failed: %v", err)
}
Common metrics

The metrics package provides several common types of unidimensional metrics such as counter, gauge, timer, and histogram, depending on the aggregation policy, the value range of the metric value, and the possible actions that can be taken on the metric value. It is recommended to prioritize the use of these built-in metrics, and then customize other types of unidimensional metrics if they do not meet your needs.

Counter

Counter is used to count the cumulative amount of a certain type of metrics, it will save the cumulative value continuously from system startup. It supports +1, -1, -n, +n operations on Counter. For example, if you want to monitor the number of requests for a particular microservice, you can define a Counter with the metric name "request.num":

import "trpc.group/trpc-go/trpc-go/metrics"

_ = metrics.Counter("request.num")
metrics.IncrCounter("request.num", 30)
Gauge

Gauge is used to count the amount of moments of a certain type of metric. For example, if you want to monitor the average CPU load, you can define and report a Gauge with the metric name "cpu.load.avg":

import "trpc.group/trpc-go/trpc-go/metrics"

_ = metrics.Gauge("cpu.avg.load")
metrics.SetGauge("cpu.avg.load", 0.75)
Timer

Timer is a special type of Gauge, which can count the time consumed by an operation according to its start time and end time. For example, if you want to monitor the time spent on an operation, you can define and report a timer with the name "operation.time.cost":

import "trpc.group/trpc-go/trpc-go/metrics"

_ = metrics.Timer("operation.time.cost")
// The operation took 2s.
timeCost := 2 * time.Second
metrics.RecordTimer("operation.time.cost", timeCost)
Histogram

Histograms are used to count the distribution of certain types of metrics, such as maximum, minimum, mean, standard deviation, and various quartiles, e.g. 90%, 95% of the data is distributed within a certain range. Histograms are created with pre-divided buckets, and the sample points collected are placed in the corresponding buckets when the Histogram is reported. For example, if you want to monitor the distribution of request sizes, you can create buckets and put the collected samples into a histogram with the metric "request.size":

buckets := metrics.NewValueBounds(1, 2, 5, 10)
metrics.AddSample("request.size", buckets, 3)
metrics.AddSample("request.size", buckets, 7)
Multidimensional metrics

Multidimensional metrics usually need to be combined with backend monitoring platforms to calculate and display data in different dimensions. Multidimensional metrics consist of a metric name, metric dimension information, and multiple unidimensional metrics. For example, if you want to monitor the requests received by a service based on different dimensions such as application name, service name, etc., you can create the following multidimensional metrics:

import (
    "trpc.group/trpc-go/trpc-go/log"
    "trpc.group/trpc-go/trpc-go/metrics"
)

if err := metrics.ReportMultiDimensionMetricsX("request",
    []*metrics.Dimension{
        {
            Name:  "app",
            Value: "trpc-go",
        },
        {
            Name:  "server",
            Value: "example",
        },
        {
            Name:  "service",
            Value: "hello",
        },
    },
    []*metrics.Metrics{
        metrics.NewMetrics("request-count", 1, metrics.PolicySUM),
        metrics.NewMetrics("request-cost", float64(time.Second), metrics.PolicyAVG),
        metrics.NewMetrics("request-size", 30, metrics.PolicyHistogram),
    }); err != nil {
        log.Infof("reporting request multi dimension metrics failed: %v", err)
}

Reporting to external monitoring systems

Metrics need to be reported to various monitoring systems, either internal to the company or external to the open source community, such as Prometheus. The metrics package provides a generic Sink interface for this purpose:

// Sink defines the interface an external monitor system should provide.
type Sink interface {
// Name returns the name of the monitor system.
Name() string
// Name returns the name of the monitor system. Name() string // Report reports a record to monitor system.
Report(rec Record, opts .... Option) error
Option) error }

To integrate with different monitoring systems, you only need to implement the Sink interface and register the implementation to the metrics package. For example, to report metrics to the console, the following three steps are usually required.

  1. Create a ConsoleSink struct that implements the Sink interface. The metrics package already has a built-in implementation of ConsoleSink, which can be created directly via metrics.NewConsoleSink()

  2. Register the ConsoleSink to the metrics package.

  3. Create various metrics and report them.

The following code snippet demonstrates the above three steps:

import "trpc.group/trpc-go/trpc-go/log"

// 1. Create a `ConsoleSink` struct that implements the `Sink` interface.
s := metrics.NewConsoleSink()

// 2. Register the `ConsoleSink` to the metrics package.
metrics.RegisterMetricsSink(s)

// 3. Create various metrics and report them.
_ = metrics.Counter("request.num")
metrics.IncrCounter("request.num", 30)

Documentation

Overview

Package metrics defines some common metrics, such as Counter, IGauge, ITimer and IHistogram. The method MetricsSink is used to adapt to external monitor systems, such as monitors in our company or open source prometheus.

For convenience, we provide two sorts of methods:

  1. counter - reqNumCounter := metrics.Counter("req.num") reqNumCounter.Incr() - metrics.IncrCounter("req.num", 1)

  2. gauge - cpuAvgLoad := metrics.Gauge("cpu.avgload") cpuAvgLoad.Set(0.75) - metrics.SetGauge("cpu.avgload", 0.75)

  3. timer - timeCostTimer := metrics.Timer("req.proc.timecost") timeCostTimer.Record() - timeCostDuration := time.Millisecond * 2000 metrics.RecordTimer("req.proc.timecost", timeCostDuration)

  4. histogram - buckets := metrics.NewDurationBounds(time.Second, time.Second*2, time.Second*5), timeCostDist := metrics.Histogram("timecost.distribution", buckets) timeCostDist.AddSample(float64(time.Second*3)) - metrics.AddSample("timecost.distribution", buckets, float64(time.Second*3))

Index

Constants

View Source
const (
	PolicyNONE      = 0 // Undefined
	PolicySET       = 1 // instantaneous value
	PolicySUM       = 2 // summary
	PolicyAVG       = 3 // average
	PolicyMAX       = 4 // maximum
	PolicyMIN       = 5 // minimum
	PolicyMID       = 6 // median
	PolicyTimer     = 7 // timer
	PolicyHistogram = 8 // histogram
)

All available Policy(s).

Variables

This section is empty.

Functions

func AddSample

func AddSample(key string, buckets BucketBounds, value float64)

AddSample adds one sample key with value.

func IncrCounter

func IncrCounter(key string, value float64)

IncrCounter increases counter key by value. Counters should accumulate values.

func RecordTimer

func RecordTimer(key string, duration time.Duration)

RecordTimer records timer named key with duration.

func RegisterHistogram

func RegisterHistogram(name string, o HistogramOption)

RegisterHistogram registers all named Histogram configurations to all Sink(s) which implement HistogramSink.

func RegisterMetricsSink

func RegisterMetricsSink(sink Sink)

RegisterMetricsSink registers a Sink.

func Report

func Report(rec Record, opts ...Option) (err error)

Report reports a multi-dimension record.

func ReportMultiDimensionMetricsX

func ReportMultiDimensionMetricsX(
	name string,
	dimensions []*Dimension,
	metrics []*Metrics,
	opts ...Option,
) error

ReportMultiDimensionMetricsX creates and reports a named Record with multiple dimensions and metrics.

func ReportSingleDimensionMetrics

func ReportSingleDimensionMetrics(name string, value float64, policy Policy, opts ...Option) error

ReportSingleDimensionMetrics creates and reports a Record with no dimension and only one metric.

func SetGauge

func SetGauge(key string, value float64)

SetGauge sets gauge key to value. An IGauge retains the last set value.

Types

type BucketBounds

type BucketBounds []float64

BucketBounds allows developers to customize Buckets of histogram.

func NewDurationBounds

func NewDurationBounds(durations ...time.Duration) BucketBounds

NewDurationBounds creates duration bounds.

func NewValueBounds

func NewValueBounds(bounds ...float64) BucketBounds

NewValueBounds creates a value bounds.

func (BucketBounds) Len

func (v BucketBounds) Len() int

Len implements sort.Interface.

func (BucketBounds) Less

func (v BucketBounds) Less(i, j int) bool

Less implements sort.Interface.

func (BucketBounds) Swap

func (v BucketBounds) Swap(i, j int)

Swap implements sort.Interface.

type ConsoleSink

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

ConsoleSink defines the console sink.

func (*ConsoleSink) Name

func (c *ConsoleSink) Name() string

Name returns console sink name.

func (*ConsoleSink) Report

func (c *ConsoleSink) Report(rec Record, opts ...Option) error

Report reports a record.

type Dimension

type Dimension struct {
	Name  string
	Value string
}

Dimension defines the dimension.

type HistogramOption

type HistogramOption struct {
	BucketBounds BucketBounds
}

HistogramOption defines configurations when register a histogram.

type HistogramSink

type HistogramSink interface {
	Register(name string, o HistogramOption)
}

HistogramSink extends Sink in a way that allows to load a named Histogram configuration. Those who do not implement HistogramSink must define their own default bucket configuration.

type ICounter

type ICounter interface {
	// Incr increments the counter by one.
	Incr()

	// IncrBy increments the counter by delta.
	IncrBy(delta float64)
}

ICounter is the interface that emits counter type metrics.

func Counter

func Counter(name string) ICounter

Counter creates a named counter.

type IGauge

type IGauge interface {
	// Set sets the gauges absolute value.
	Set(value float64)
}

IGauge is the interface that emits gauge metrics.

func Gauge

func Gauge(name string) IGauge

Gauge creates a named gauge.

type IHistogram

type IHistogram interface {
	// AddSample records a sample into histogram.
	AddSample(value float64)
	// GetBuckets get histogram buckets.
	GetBuckets() []*bucket
}

IHistogram is the interface that emits histogram metrics.

func GetHistogram

func GetHistogram(key string) (v IHistogram, ok bool)

GetHistogram gets the histogram by key.

func Histogram

func Histogram(name string, buckets BucketBounds) IHistogram

Histogram creates a named histogram with buckets.

type ITimer

type ITimer interface {

	// Record records the duration since timer.start, and reset timer.start.
	Record() time.Duration

	// RecordDuration records duration into timer, and reset timer.start.
	RecordDuration(duration time.Duration)

	// Reset resets the timer.start.
	Reset()
}

ITimer is the interface that emits timer metrics.

func NewTimer

func NewTimer(name string) ITimer

NewTimer creates a named timer whose start is set to time.Now().

func Timer

func Timer(name string) ITimer

Timer creates a named timer.

type Metrics

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

Metrics defines the metric.

func NewMetrics

func NewMetrics(name string, value float64, policy Policy) *Metrics

NewMetrics creates a new Metrics.

func (*Metrics) Name

func (m *Metrics) Name() string

Name returns the metrics name.

func (*Metrics) Policy

func (m *Metrics) Policy() Policy

Policy returns the metrics policy.

func (*Metrics) Value

func (m *Metrics) Value() float64

Value returns the metrics value.

type NoopSink

type NoopSink struct{}

NoopSink defines the noop Sink.

func (*NoopSink) Name

func (n *NoopSink) Name() string

Name returns noop.

func (*NoopSink) Report

func (n *NoopSink) Report(rec Record, opts ...Option) error

Report does nothing.

type Option

type Option func(opts *Options)

Option modifies the Options.

func WithMeta

func WithMeta(meta map[string]interface{}) Option

WithMeta returns an Option which sets the metadata, such as a map between metric name and metric id.

type Options

type Options struct {
	// Meta is used to adapt some complex scenes. For example, a monitor may map the metric name to
	// monitor id.
	Meta map[string]interface{}
}

Options defines the report options.

func GetOptions

func GetOptions() Options

GetOptions gets options.

type Policy

type Policy int

Policy is the metrics aggregation policy.

type Record

type Record struct {
	Name string // the name of the record
	// contains filtered or unexported fields
}

Record is the single record.

terminologies:

  • dimension name is an attribute of a data, often used to filter data, such as a photo album business module includes region and server room.
  • dimension value refines the dimension. For example, the regions of the album business module include Shenzhen, Shanghai, etc., the region is the dimension, and Shenzhen and Shanghai are the dimension values.
  • metric is a measurement, used to aggregate and calculate. For example, request count of album business module in ShenZhen Telecom is a metric.

func NewMultiDimensionMetricsX

func NewMultiDimensionMetricsX(name string, dimensions []*Dimension, metrics []*Metrics) Record

NewMultiDimensionMetricsX creates a named Record with multiple dimensions and metrics.

func NewSingleDimensionMetrics

func NewSingleDimensionMetrics(name string, value float64, policy Policy) Record

NewSingleDimensionMetrics creates a Record with no dimension and only one metric.

func (*Record) GetDimensions

func (r *Record) GetDimensions() []*Dimension

GetDimensions returns dimensions.

func (*Record) GetMetrics

func (r *Record) GetMetrics() []*Metrics

GetMetrics returns metrics.

func (*Record) GetName

func (r *Record) GetName() string

GetName returns the record name.

type Sink

type Sink interface {
	// Name returns the name of the monitor system.
	Name() string
	// Report reports a record to monitor system.
	Report(rec Record, opts ...Option) error
}

Sink defines the interface an external monitor system should provide.

func GetMetricsSink

func GetMetricsSink(name string) (Sink, bool)

GetMetricsSink gets a Sink by name

func NewConsoleSink

func NewConsoleSink() Sink

NewConsoleSink creates a new console sink.

Jump to

Keyboard shortcuts

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