1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package event
import (
"context"
"time"
)
// A Unit is a unit of measurement for a metric.
type Unit string
const (
UnitDimensionless Unit = "1"
UnitBytes Unit = "By"
UnitMilliseconds Unit = "ms"
)
// A Metric represents a kind of recorded measurement.
type Metric interface {
Name() string
Options() MetricOptions
}
type MetricOptions struct {
// A string that should be common for all metrics of an application or
// service. Defaults to the import path of the package calling
// the metric construction function (NewCounter, etc.).
Namespace string
// Optional description of the metric.
Description string
// Optional unit for the metric. Defaults to UnitDimensionless.
Unit Unit
}
// A Counter is a metric that counts something cumulatively.
type Counter struct {
name string
opts MetricOptions
}
func initOpts(popts *MetricOptions) MetricOptions {
var opts MetricOptions
if popts != nil {
opts = *popts
}
if opts.Namespace == "" {
opts.Namespace = scanStack().Space
}
if opts.Unit == "" {
opts.Unit = UnitDimensionless
}
return opts
}
// NewCounter creates a counter with the given name.
func NewCounter(name string, opts *MetricOptions) *Counter {
return &Counter{name, initOpts(opts)}
}
func (c *Counter) Name() string { return c.name }
func (c *Counter) Options() MetricOptions { return c.opts }
// Record delivers a metric event with the given metric, value and labels to the
// exporter in the context.
func (c *Counter) Record(ctx context.Context, v int64, labels ...Label) {
ev := New(ctx, MetricKind)
if ev != nil {
record(ev, c, Int64(string(MetricVal), v))
ev.Labels = append(ev.Labels, labels...)
ev.Deliver()
}
}
// A FloatGauge records a single floating-point value that may go up or down.
// TODO(generics): Gauge[T]
type FloatGauge struct {
name string
opts MetricOptions
}
// NewFloatGauge creates a new FloatGauge with the given name.
func NewFloatGauge(name string, opts *MetricOptions) *FloatGauge {
return &FloatGauge{name, initOpts(opts)}
}
func (g *FloatGauge) Name() string { return g.name }
func (g *FloatGauge) Options() MetricOptions { return g.opts }
// Record converts its argument into a Value and returns a MetricValue with the
// receiver and the value.
func (g *FloatGauge) Record(ctx context.Context, v float64, labels ...Label) {
ev := New(ctx, MetricKind)
if ev != nil {
record(ev, g, Float64(string(MetricVal), v))
ev.Labels = append(ev.Labels, labels...)
ev.Deliver()
}
}
// A DurationDistribution records a distribution of durations.
// TODO(generics): Distribution[T]
type DurationDistribution struct {
name string
opts MetricOptions
}
// NewDuration creates a new Duration with the given name.
func NewDuration(name string, opts *MetricOptions) *DurationDistribution {
return &DurationDistribution{name, initOpts(opts)}
}
func (d *DurationDistribution) Name() string { return d.name }
func (d *DurationDistribution) Options() MetricOptions { return d.opts }
// Record converts its argument into a Value and returns a MetricValue with the
// receiver and the value.
func (d *DurationDistribution) Record(ctx context.Context, v time.Duration, labels ...Label) {
ev := New(ctx, MetricKind)
if ev != nil {
record(ev, d, Duration(string(MetricVal), v))
ev.Labels = append(ev.Labels, labels...)
ev.Deliver()
}
}
// An IntDistribution records a distribution of int64s.
type IntDistribution struct {
name string
opts MetricOptions
}
func (d *IntDistribution) Name() string { return d.name }
func (d *IntDistribution) Options() MetricOptions { return d.opts }
// NewIntDistribution creates a new IntDistribution with the given name.
func NewIntDistribution(name string, opts *MetricOptions) *IntDistribution {
return &IntDistribution{name, initOpts(opts)}
}
// Record converts its argument into a Value and returns a MetricValue with the
// receiver and the value.
func (d *IntDistribution) Record(ctx context.Context, v int64, labels ...Label) {
ev := New(ctx, MetricKind)
if ev != nil {
record(ev, d, Int64(string(MetricVal), v))
ev.Labels = append(ev.Labels, labels...)
ev.Deliver()
}
}
func record(ev *Event, m Metric, l Label) {
ev.Labels = append(ev.Labels, l, MetricKey.Of(m))
}
|