mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-01-01 22:09:57 +02:00
Update metrics API to match current spec (#228)
* Update metrics API to match current spec * update options to match the spec * drop the global meter API * more docs * get rid of leftover mentions about descriptor
This commit is contained in:
parent
a6e139e1d4
commit
b3247f04fc
@ -12,8 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:generate stringer -type=Kind,ValueKind
|
||||
|
||||
package metric
|
||||
|
||||
import (
|
||||
@ -23,25 +21,24 @@ import (
|
||||
"go.opentelemetry.io/api/unit"
|
||||
)
|
||||
|
||||
// Kind categorizes different kinds of metric.
|
||||
type Kind int
|
||||
|
||||
const (
|
||||
// Invalid describes an invalid metric.
|
||||
Invalid Kind = iota
|
||||
// CounterKind describes a metric that supports Add().
|
||||
CounterKind
|
||||
// GaugeKind describes a metric that supports Set().
|
||||
GaugeKind
|
||||
// MeasureKind describes a metric that supports Record().
|
||||
MeasureKind
|
||||
)
|
||||
// Instrument is the implementation-level interface Set/Add/Record
|
||||
// individual metrics without precomputed labels.
|
||||
type Instrument interface {
|
||||
// AcquireHandle creates a Handle to record metrics with
|
||||
// precomputed labels.
|
||||
AcquireHandle(labels LabelSet) Handle
|
||||
// RecordOne allows the SDK to observe a single metric event.
|
||||
RecordOne(ctx context.Context, value MeasurementValue, labels LabelSet)
|
||||
}
|
||||
|
||||
// Handle is the implementation-level interface to Set/Add/Record
|
||||
// individual metrics.
|
||||
// individual metrics with precomputed labels.
|
||||
type Handle interface {
|
||||
// RecordOne allows the SDK to observe a single metric event
|
||||
// RecordOne allows the SDK to observe a single metric event.
|
||||
RecordOne(ctx context.Context, value MeasurementValue)
|
||||
// Release frees the resources associated with this handle. It
|
||||
// does not affect the metric this handle was created through.
|
||||
Release()
|
||||
}
|
||||
|
||||
// TODO this belongs outside the metrics API, in some sense, but that
|
||||
@ -49,135 +46,115 @@ type Handle interface {
|
||||
// a LabelSet between metrics and tracing, even when they are the same
|
||||
// SDK.
|
||||
|
||||
// LabelSet represents a []core.KeyValue for use as pre-defined labels
|
||||
// in the metrics API.
|
||||
// TODO(krnowak): I wonder if this should just be:
|
||||
//
|
||||
// type LabelSet interface{}
|
||||
//
|
||||
// Not sure how the Meter function is useful.
|
||||
|
||||
// LabelSet is an implementation-level interface that represents a
|
||||
// []core.KeyValue for use as pre-defined labels in the metrics API.
|
||||
type LabelSet interface {
|
||||
Meter() Meter
|
||||
}
|
||||
|
||||
// WithDescriptor is an interface that all metric implement.
|
||||
type WithDescriptor interface {
|
||||
// Descriptor returns a descriptor of this metric.
|
||||
Descriptor() *Descriptor
|
||||
// Options contains some options for metrics of any kind.
|
||||
type Options struct {
|
||||
// Description is an optional field describing the metric
|
||||
// instrument.
|
||||
Description string
|
||||
// Unit is an optional field describing the metric instrument.
|
||||
Unit unit.Unit
|
||||
// Keys are recommended keys determined in the handles
|
||||
// obtained for the metric.
|
||||
Keys []core.Key
|
||||
// Alternate defines the property of metric value dependent on
|
||||
// a metric type.
|
||||
//
|
||||
// - for Counter, true implies that the metric is an up-down
|
||||
// Counter
|
||||
//
|
||||
// - for Gauge, true implies that the metric is a
|
||||
// non-descending Gauge
|
||||
//
|
||||
// - for Measure, true implies that the metric supports
|
||||
// positive and negative values
|
||||
Alternate bool
|
||||
}
|
||||
|
||||
type hiddenType struct{}
|
||||
// CounterOptionApplier is an interface for applying metric options
|
||||
// that are valid only for counter metrics.
|
||||
type CounterOptionApplier interface {
|
||||
// ApplyCounterOption is used to make some general or
|
||||
// counter-specific changes in the Options.
|
||||
ApplyCounterOption(*Options)
|
||||
}
|
||||
|
||||
// ExplicitReportingMetric is an interface that is implemented only by
|
||||
// metrics that support getting a Handle.
|
||||
type ExplicitReportingMetric interface {
|
||||
WithDescriptor
|
||||
// SupportHandle is a dummy function that can be only
|
||||
// implemented in this package.
|
||||
SupportHandle() hiddenType
|
||||
// GaugeOptionApplier is an interface for applying metric options that
|
||||
// are valid only for gauge metrics.
|
||||
type GaugeOptionApplier interface {
|
||||
// ApplyGaugeOption is used to make some general or
|
||||
// gauge-specific changes in the Options.
|
||||
ApplyGaugeOption(*Options)
|
||||
}
|
||||
|
||||
// MeasureOptionApplier is an interface for applying metric options
|
||||
// that are valid only for measure metrics.
|
||||
type MeasureOptionApplier interface {
|
||||
// ApplyMeasureOption is used to make some general or
|
||||
// measure-specific changes in the Options.
|
||||
ApplyMeasureOption(*Options)
|
||||
}
|
||||
|
||||
// Measurement is used for reporting a batch of metric
|
||||
// values. Instances of this type should be created by instruments
|
||||
// (Int64Counter.Measurement()).
|
||||
type Measurement struct {
|
||||
instrument Instrument
|
||||
value MeasurementValue
|
||||
}
|
||||
|
||||
// Instrument returns an instrument that created this measurement.
|
||||
func (m Measurement) Instrument() Instrument {
|
||||
return m.instrument
|
||||
}
|
||||
|
||||
// Value returns a value recorded in this measurement.
|
||||
func (m Measurement) Value() MeasurementValue {
|
||||
return m.value
|
||||
}
|
||||
|
||||
// Meter is an interface to the metrics portion of the OpenTelemetry SDK.
|
||||
type Meter interface {
|
||||
// DefineLabels returns a reference to a set of labels that
|
||||
// cannot be read by the application.
|
||||
DefineLabels(context.Context, ...core.KeyValue) LabelSet
|
||||
// Labels returns a reference to a set of labels that cannot
|
||||
// be read by the application.
|
||||
Labels(context.Context, ...core.KeyValue) LabelSet
|
||||
|
||||
// NewInt64Counter creates a new integral counter with a given
|
||||
// name and customized with passed options.
|
||||
NewInt64Counter(name string, cos ...CounterOptionApplier) Int64Counter
|
||||
// NewFloat64Counter creates a new floating point counter with
|
||||
// a given name and customized with passed options.
|
||||
NewFloat64Counter(name string, cos ...CounterOptionApplier) Float64Counter
|
||||
// NewInt64Gauge creates a new integral gauge with a given
|
||||
// name and customized with passed options.
|
||||
NewInt64Gauge(name string, gos ...GaugeOptionApplier) Int64Gauge
|
||||
// NewFloat64Gauge creates a new floating point gauge with a
|
||||
// given name and customized with passed options.
|
||||
NewFloat64Gauge(name string, gos ...GaugeOptionApplier) Float64Gauge
|
||||
// NewInt64Measure creates a new integral measure with a given
|
||||
// name and customized with passed options.
|
||||
NewInt64Measure(name string, mos ...MeasureOptionApplier) Int64Measure
|
||||
// NewFloat64Measure creates a new floating point measure with
|
||||
// a given name and customized with passed options.
|
||||
NewFloat64Measure(name string, mos ...MeasureOptionApplier) Float64Measure
|
||||
|
||||
// RecordBatch atomically records a batch of measurements.
|
||||
RecordBatch(context.Context, LabelSet, ...Measurement)
|
||||
|
||||
// NewHandle creates a Handle that contains the passed
|
||||
// key-value pairs. This should not be used directly - prefer
|
||||
// using GetHandle function of a metric.
|
||||
NewHandle(ExplicitReportingMetric, LabelSet) Handle
|
||||
// DeleteHandle destroys the Handle and does a cleanup of the
|
||||
// underlying resources.
|
||||
DeleteHandle(Handle)
|
||||
}
|
||||
|
||||
// DescriptorID is a unique identifier of a metric.
|
||||
type DescriptorID uint64
|
||||
|
||||
// ValueKind describes the data type of the measurement value the
|
||||
// metric generates.
|
||||
type ValueKind int8
|
||||
|
||||
const (
|
||||
// Int64ValueKind means that the metric generates values of
|
||||
// type int64.
|
||||
Int64ValueKind ValueKind = iota
|
||||
// Float64ValueKind means that the metric generates values of
|
||||
// type float64.
|
||||
Float64ValueKind
|
||||
)
|
||||
|
||||
// Descriptor represents a named metric with recommended
|
||||
// local-aggregation keys.
|
||||
type Descriptor struct {
|
||||
name string
|
||||
kind Kind
|
||||
keys []core.Key
|
||||
id DescriptorID
|
||||
description string
|
||||
unit unit.Unit
|
||||
valueKind ValueKind
|
||||
alternate bool
|
||||
}
|
||||
|
||||
// Name is a required field describing this metric descriptor, should
|
||||
// have length > 0.
|
||||
func (d *Descriptor) Name() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
// Kind is the metric kind of this descriptor.
|
||||
func (d *Descriptor) Kind() Kind {
|
||||
return d.kind
|
||||
}
|
||||
|
||||
// Keys are recommended keys determined in the handles obtained for
|
||||
// this metric.
|
||||
func (d *Descriptor) Keys() []core.Key {
|
||||
return d.keys
|
||||
}
|
||||
|
||||
// ID is uniquely assigned to support per-SDK registration.
|
||||
func (d *Descriptor) ID() DescriptorID {
|
||||
return d.id
|
||||
}
|
||||
|
||||
// Description is an optional field describing this metric descriptor.
|
||||
func (d *Descriptor) Description() string {
|
||||
return d.description
|
||||
}
|
||||
|
||||
// Unit is an optional field describing this metric descriptor.
|
||||
func (d *Descriptor) Unit() unit.Unit {
|
||||
return d.unit
|
||||
}
|
||||
|
||||
// ValueKind describes the type of values the metric produces.
|
||||
func (d *Descriptor) ValueKind() ValueKind {
|
||||
return d.valueKind
|
||||
}
|
||||
|
||||
// Alternate defines the property of metric value dependent on a
|
||||
// metric type.
|
||||
//
|
||||
// - for Counter, true implies that the metric is an up-down Counter
|
||||
//
|
||||
// - for Gauge, true implies that the metric is a
|
||||
// non-descending Gauge
|
||||
//
|
||||
// - for Measure, true implies that the metric supports positive and
|
||||
// negative values
|
||||
func (d *Descriptor) Alternate() bool {
|
||||
return d.alternate
|
||||
}
|
||||
|
||||
// Measurement is used for reporting a batch of metric values.
|
||||
type Measurement struct {
|
||||
Descriptor *Descriptor
|
||||
Value MeasurementValue
|
||||
}
|
||||
|
||||
// Option supports specifying the various metric options.
|
||||
type Option func(*Descriptor)
|
||||
type Option func(*Options)
|
||||
|
||||
// OptionApplier is an interface for applying metric options that are
|
||||
// valid for all the kinds of metrics.
|
||||
@ -185,37 +162,87 @@ type OptionApplier interface {
|
||||
CounterOptionApplier
|
||||
GaugeOptionApplier
|
||||
MeasureOptionApplier
|
||||
// ApplyOption is used to make some changes in the Descriptor.
|
||||
ApplyOption(*Descriptor)
|
||||
// ApplyOption is used to make some general changes in the
|
||||
// Options.
|
||||
ApplyOption(*Options)
|
||||
}
|
||||
|
||||
// CounterGaugeOptionApplier is an interface for applying metric
|
||||
// options that are valid for counter or gauge metrics.
|
||||
type CounterGaugeOptionApplier interface {
|
||||
CounterOptionApplier
|
||||
GaugeOptionApplier
|
||||
}
|
||||
|
||||
type optionWrapper struct {
|
||||
F Option
|
||||
}
|
||||
|
||||
var _ OptionApplier = optionWrapper{}
|
||||
|
||||
func (o optionWrapper) ApplyCounterOption(d *Descriptor) {
|
||||
o.ApplyOption(d)
|
||||
type counterOptionWrapper struct {
|
||||
F Option
|
||||
}
|
||||
|
||||
func (o optionWrapper) ApplyGaugeOption(d *Descriptor) {
|
||||
o.ApplyOption(d)
|
||||
type gaugeOptionWrapper struct {
|
||||
F Option
|
||||
}
|
||||
|
||||
func (o optionWrapper) ApplyMeasureOption(d *Descriptor) {
|
||||
o.ApplyOption(d)
|
||||
type measureOptionWrapper struct {
|
||||
F Option
|
||||
}
|
||||
|
||||
func (o optionWrapper) ApplyOption(d *Descriptor) {
|
||||
o.F(d)
|
||||
type counterGaugeOptionWrapper struct {
|
||||
FC Option
|
||||
FG Option
|
||||
}
|
||||
|
||||
var (
|
||||
_ OptionApplier = optionWrapper{}
|
||||
_ CounterOptionApplier = counterOptionWrapper{}
|
||||
_ GaugeOptionApplier = gaugeOptionWrapper{}
|
||||
_ MeasureOptionApplier = measureOptionWrapper{}
|
||||
)
|
||||
|
||||
func (o optionWrapper) ApplyCounterOption(opts *Options) {
|
||||
o.ApplyOption(opts)
|
||||
}
|
||||
|
||||
func (o optionWrapper) ApplyGaugeOption(opts *Options) {
|
||||
o.ApplyOption(opts)
|
||||
}
|
||||
|
||||
func (o optionWrapper) ApplyMeasureOption(opts *Options) {
|
||||
o.ApplyOption(opts)
|
||||
}
|
||||
|
||||
func (o optionWrapper) ApplyOption(opts *Options) {
|
||||
o.F(opts)
|
||||
}
|
||||
|
||||
func (o counterOptionWrapper) ApplyCounterOption(opts *Options) {
|
||||
o.F(opts)
|
||||
}
|
||||
|
||||
func (o gaugeOptionWrapper) ApplyGaugeOption(opts *Options) {
|
||||
o.F(opts)
|
||||
}
|
||||
|
||||
func (o measureOptionWrapper) ApplyMeasureOption(opts *Options) {
|
||||
o.F(opts)
|
||||
}
|
||||
|
||||
func (o counterGaugeOptionWrapper) ApplyCounterOption(opts *Options) {
|
||||
o.FC(opts)
|
||||
}
|
||||
|
||||
func (o counterGaugeOptionWrapper) ApplyGaugeOption(opts *Options) {
|
||||
o.FG(opts)
|
||||
}
|
||||
|
||||
// WithDescription applies provided description.
|
||||
func WithDescription(desc string) OptionApplier {
|
||||
return optionWrapper{
|
||||
F: func(d *Descriptor) {
|
||||
d.description = desc
|
||||
F: func(opts *Options) {
|
||||
opts.Description = desc
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -223,56 +250,41 @@ func WithDescription(desc string) OptionApplier {
|
||||
// WithUnit applies provided unit.
|
||||
func WithUnit(unit unit.Unit) OptionApplier {
|
||||
return optionWrapper{
|
||||
F: func(d *Descriptor) {
|
||||
d.unit = unit
|
||||
F: func(opts *Options) {
|
||||
opts.Unit = unit
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// WithKeys applies required label keys. Multiple `WithKeys` options
|
||||
// accumulate.
|
||||
// WithKeys applies recommended label keys. Multiple `WithKeys`
|
||||
// options accumulate.
|
||||
func WithKeys(keys ...core.Key) OptionApplier {
|
||||
return optionWrapper{
|
||||
F: func(d *Descriptor) {
|
||||
d.keys = append(d.keys, keys...)
|
||||
F: func(opts *Options) {
|
||||
opts.Keys = append(opts.Keys, keys...)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// WithNonMonotonic sets whether a counter is permitted to go up AND
|
||||
// down.
|
||||
func WithNonMonotonic(nm bool) CounterOptionApplier {
|
||||
return counterOptionWrapper{
|
||||
F: func(d *Descriptor) {
|
||||
d.alternate = nm
|
||||
// WithMonotonic sets whether a counter or a gauge is not permitted to
|
||||
// go down.
|
||||
func WithMonotonic(monotonic bool) CounterGaugeOptionApplier {
|
||||
return counterGaugeOptionWrapper{
|
||||
FC: func(opts *Options) {
|
||||
opts.Alternate = !monotonic
|
||||
},
|
||||
FG: func(opts *Options) {
|
||||
opts.Alternate = monotonic
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// WithMonotonic sets whether a gauge is not permitted to go down.
|
||||
func WithMonotonic(m bool) GaugeOptionApplier {
|
||||
return gaugeOptionWrapper{
|
||||
F: func(d *Descriptor) {
|
||||
d.alternate = m
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// WithSigned sets whether a measure is permitted to be negative.
|
||||
func WithSigned(s bool) MeasureOptionApplier {
|
||||
// WithAbsolute sets whether a measure is not permitted to be
|
||||
// negative.
|
||||
func WithAbsolute(absolute bool) MeasureOptionApplier {
|
||||
return measureOptionWrapper{
|
||||
F: func(d *Descriptor) {
|
||||
d.alternate = s
|
||||
F: func(opts *Options) {
|
||||
opts.Alternate = !absolute
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Defined returns true when the descriptor has been registered.
|
||||
func (d Descriptor) Defined() bool {
|
||||
return len(d.name) != 0
|
||||
}
|
||||
|
||||
// RecordBatch reports to the global Meter.
|
||||
func RecordBatch(ctx context.Context, labels LabelSet, batch ...Measurement) {
|
||||
GlobalMeter().RecordBatch(ctx, labels, batch...)
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ import (
|
||||
"go.opentelemetry.io/api/core"
|
||||
"go.opentelemetry.io/api/key"
|
||||
"go.opentelemetry.io/api/unit"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestCounterOptions(t *testing.T) {
|
||||
@ -103,7 +105,7 @@ func TestCounterOptions(t *testing.T) {
|
||||
{
|
||||
name: "nonmonotonic",
|
||||
opts: []CounterOptionApplier{
|
||||
WithNonMonotonic(true),
|
||||
WithMonotonic(false),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "",
|
||||
@ -113,8 +115,8 @@ func TestCounterOptions(t *testing.T) {
|
||||
{
|
||||
name: "nonmonotonic, but not really",
|
||||
opts: []CounterOptionApplier{
|
||||
WithNonMonotonic(true),
|
||||
WithNonMonotonic(false),
|
||||
WithMonotonic(false),
|
||||
WithMonotonic(true),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "",
|
||||
@ -122,24 +124,16 @@ func TestCounterOptions(t *testing.T) {
|
||||
alt: false,
|
||||
},
|
||||
}
|
||||
checkCounterDescriptor := func(tt testcase, vk ValueKind, d *Descriptor) {
|
||||
e := descriptor{
|
||||
name: tt.name,
|
||||
keys: tt.keys,
|
||||
desc: tt.desc,
|
||||
unit: tt.unit,
|
||||
alt: tt.alt,
|
||||
kind: CounterKind,
|
||||
vk: vk,
|
||||
}
|
||||
checkDescriptor(t, e, d)
|
||||
}
|
||||
for idx, tt := range testcases {
|
||||
t.Logf("Testing counter case %s (%d)", tt.name, idx)
|
||||
f := NewFloat64Counter(tt.name, tt.opts...)
|
||||
checkCounterDescriptor(tt, Float64ValueKind, f.Descriptor())
|
||||
i := NewInt64Counter(tt.name, tt.opts...)
|
||||
checkCounterDescriptor(tt, Int64ValueKind, i.Descriptor())
|
||||
opts := &Options{}
|
||||
ApplyCounterOptions(opts, tt.opts...)
|
||||
checkOptions(t, opts, &Options{
|
||||
Description: tt.desc,
|
||||
Unit: tt.unit,
|
||||
Keys: tt.keys,
|
||||
Alternate: tt.alt,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,24 +235,16 @@ func TestGaugeOptions(t *testing.T) {
|
||||
alt: false,
|
||||
},
|
||||
}
|
||||
checkGaugeDescriptor := func(tt testcase, vk ValueKind, d *Descriptor) {
|
||||
e := descriptor{
|
||||
name: tt.name,
|
||||
keys: tt.keys,
|
||||
desc: tt.desc,
|
||||
unit: tt.unit,
|
||||
alt: tt.alt,
|
||||
kind: GaugeKind,
|
||||
vk: vk,
|
||||
}
|
||||
checkDescriptor(t, e, d)
|
||||
}
|
||||
for idx, tt := range testcases {
|
||||
t.Logf("Testing gauge case %s (%d)", tt.name, idx)
|
||||
f := NewFloat64Gauge(tt.name, tt.opts...)
|
||||
checkGaugeDescriptor(tt, Float64ValueKind, f.Descriptor())
|
||||
i := NewInt64Gauge(tt.name, tt.opts...)
|
||||
checkGaugeDescriptor(tt, Int64ValueKind, i.Descriptor())
|
||||
opts := &Options{}
|
||||
ApplyGaugeOptions(opts, tt.opts...)
|
||||
checkOptions(t, opts, &Options{
|
||||
Description: tt.desc,
|
||||
Unit: tt.unit,
|
||||
Keys: tt.keys,
|
||||
Alternate: tt.alt,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,9 +325,9 @@ func TestMeasureOptions(t *testing.T) {
|
||||
alt: false,
|
||||
},
|
||||
{
|
||||
name: "signed",
|
||||
name: "not absolute",
|
||||
opts: []MeasureOptionApplier{
|
||||
WithSigned(true),
|
||||
WithAbsolute(false),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "",
|
||||
@ -349,10 +335,10 @@ func TestMeasureOptions(t *testing.T) {
|
||||
alt: true,
|
||||
},
|
||||
{
|
||||
name: "signed, but not really",
|
||||
name: "not absolute, but not really",
|
||||
opts: []MeasureOptionApplier{
|
||||
WithSigned(true),
|
||||
WithSigned(false),
|
||||
WithAbsolute(false),
|
||||
WithAbsolute(true),
|
||||
},
|
||||
keys: nil,
|
||||
desc: "",
|
||||
@ -360,156 +346,112 @@ func TestMeasureOptions(t *testing.T) {
|
||||
alt: false,
|
||||
},
|
||||
}
|
||||
checkMeasureDescriptor := func(tt testcase, vk ValueKind, d *Descriptor) {
|
||||
e := descriptor{
|
||||
name: tt.name,
|
||||
keys: tt.keys,
|
||||
desc: tt.desc,
|
||||
unit: tt.unit,
|
||||
alt: tt.alt,
|
||||
kind: MeasureKind,
|
||||
vk: vk,
|
||||
}
|
||||
checkDescriptor(t, e, d)
|
||||
}
|
||||
for idx, tt := range testcases {
|
||||
t.Logf("Testing measure case %s (%d)", tt.name, idx)
|
||||
f := NewFloat64Measure(tt.name, tt.opts...)
|
||||
checkMeasureDescriptor(tt, Float64ValueKind, f.Descriptor())
|
||||
i := NewInt64Measure(tt.name, tt.opts...)
|
||||
checkMeasureDescriptor(tt, Int64ValueKind, i.Descriptor())
|
||||
opts := &Options{}
|
||||
ApplyMeasureOptions(opts, tt.opts...)
|
||||
checkOptions(t, opts, &Options{
|
||||
Description: tt.desc,
|
||||
Unit: tt.unit,
|
||||
Keys: tt.keys,
|
||||
Alternate: tt.alt,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type descriptor struct {
|
||||
name string
|
||||
keys []core.Key
|
||||
desc string
|
||||
unit unit.Unit
|
||||
alt bool
|
||||
kind Kind
|
||||
vk ValueKind
|
||||
}
|
||||
|
||||
func checkDescriptor(t *testing.T, e descriptor, d *Descriptor) {
|
||||
if e.name != d.Name() {
|
||||
t.Errorf("Expected name %q, got %q", e.name, d.Name())
|
||||
}
|
||||
if len(e.keys) != len(d.Keys()) {
|
||||
t.Errorf("Expected %d key(s), got %d", len(e.keys), len(d.Keys()))
|
||||
}
|
||||
minLen := len(e.keys)
|
||||
if minLen > len(d.Keys()) {
|
||||
minLen = len(d.Keys())
|
||||
}
|
||||
for i := 0; i < minLen; i++ {
|
||||
if e.keys[i] != d.Keys()[i] {
|
||||
t.Errorf("Expected key %q, got %q", e.keys[i], d.Keys()[i])
|
||||
}
|
||||
}
|
||||
if e.desc != d.Description() {
|
||||
t.Errorf("Expected description %q, got %q", e.desc, d.Description())
|
||||
}
|
||||
if e.unit != d.Unit() {
|
||||
t.Errorf("Expected unit %q, got %q", e.unit, d.Unit())
|
||||
}
|
||||
if e.alt != d.Alternate() {
|
||||
t.Errorf("Expected alternate %v, got %v", e.alt, d.Alternate())
|
||||
}
|
||||
if e.vk != d.ValueKind() {
|
||||
t.Errorf("Expected value kind %q, got %q", e.vk, d.ValueKind())
|
||||
}
|
||||
if e.kind != d.Kind() {
|
||||
t.Errorf("Expected kind %q, got %q", e.kind, d.Kind())
|
||||
func checkOptions(t *testing.T, got *Options, expected *Options) {
|
||||
if diff := cmp.Diff(got, expected); diff != "" {
|
||||
t.Errorf("Compare options: -got +want %s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCounter(t *testing.T) {
|
||||
{
|
||||
c := NewFloat64Counter("ajwaj")
|
||||
meter := newMockMeter()
|
||||
c := meter.NewFloat64Counter("ajwaj")
|
||||
ctx := context.Background()
|
||||
labels := meter.DefineLabels(ctx)
|
||||
labels := meter.Labels(ctx)
|
||||
c.Add(ctx, 42, labels)
|
||||
handle := c.GetHandle(labels)
|
||||
handle := c.AcquireHandle(labels)
|
||||
handle.Add(ctx, 42)
|
||||
meter.RecordBatch(ctx, labels, c.Measurement(42))
|
||||
t.Log("Testing float counter")
|
||||
checkBatches(t, ctx, labels, meter, c.Descriptor())
|
||||
checkBatches(t, ctx, labels, meter, Float64ValueKind, c.instrument)
|
||||
}
|
||||
{
|
||||
c := NewInt64Counter("ajwaj")
|
||||
meter := newMockMeter()
|
||||
c := meter.NewInt64Counter("ajwaj")
|
||||
ctx := context.Background()
|
||||
labels := meter.DefineLabels(ctx)
|
||||
labels := meter.Labels(ctx)
|
||||
c.Add(ctx, 42, labels)
|
||||
handle := c.GetHandle(labels)
|
||||
handle := c.AcquireHandle(labels)
|
||||
handle.Add(ctx, 42)
|
||||
meter.RecordBatch(ctx, labels, c.Measurement(42))
|
||||
t.Log("Testing int counter")
|
||||
checkBatches(t, ctx, labels, meter, c.Descriptor())
|
||||
checkBatches(t, ctx, labels, meter, Int64ValueKind, c.instrument)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGauge(t *testing.T) {
|
||||
{
|
||||
g := NewFloat64Gauge("ajwaj")
|
||||
meter := newMockMeter()
|
||||
g := meter.NewFloat64Gauge("ajwaj")
|
||||
ctx := context.Background()
|
||||
labels := meter.DefineLabels(ctx)
|
||||
labels := meter.Labels(ctx)
|
||||
g.Set(ctx, 42, labels)
|
||||
handle := g.GetHandle(labels)
|
||||
handle := g.AcquireHandle(labels)
|
||||
handle.Set(ctx, 42)
|
||||
meter.RecordBatch(ctx, labels, g.Measurement(42))
|
||||
t.Log("Testing float gauge")
|
||||
checkBatches(t, ctx, labels, meter, g.Descriptor())
|
||||
checkBatches(t, ctx, labels, meter, Float64ValueKind, g.instrument)
|
||||
}
|
||||
{
|
||||
g := NewInt64Gauge("ajwaj")
|
||||
meter := newMockMeter()
|
||||
g := meter.NewInt64Gauge("ajwaj")
|
||||
ctx := context.Background()
|
||||
labels := meter.DefineLabels(ctx)
|
||||
labels := meter.Labels(ctx)
|
||||
g.Set(ctx, 42, labels)
|
||||
handle := g.GetHandle(labels)
|
||||
handle := g.AcquireHandle(labels)
|
||||
handle.Set(ctx, 42)
|
||||
meter.RecordBatch(ctx, labels, g.Measurement(42))
|
||||
t.Log("Testing int gauge")
|
||||
checkBatches(t, ctx, labels, meter, g.Descriptor())
|
||||
checkBatches(t, ctx, labels, meter, Int64ValueKind, g.instrument)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMeasure(t *testing.T) {
|
||||
{
|
||||
m := NewFloat64Measure("ajwaj")
|
||||
meter := newMockMeter()
|
||||
m := meter.NewFloat64Measure("ajwaj")
|
||||
ctx := context.Background()
|
||||
labels := meter.DefineLabels(ctx)
|
||||
labels := meter.Labels(ctx)
|
||||
m.Record(ctx, 42, labels)
|
||||
handle := m.GetHandle(labels)
|
||||
handle := m.AcquireHandle(labels)
|
||||
handle.Record(ctx, 42)
|
||||
meter.RecordBatch(ctx, labels, m.Measurement(42))
|
||||
t.Log("Testing float measure")
|
||||
checkBatches(t, ctx, labels, meter, m.Descriptor())
|
||||
checkBatches(t, ctx, labels, meter, Float64ValueKind, m.instrument)
|
||||
}
|
||||
{
|
||||
m := NewInt64Measure("ajwaj")
|
||||
meter := newMockMeter()
|
||||
m := meter.NewInt64Measure("ajwaj")
|
||||
ctx := context.Background()
|
||||
labels := meter.DefineLabels(ctx)
|
||||
labels := meter.Labels(ctx)
|
||||
m.Record(ctx, 42, labels)
|
||||
handle := m.GetHandle(labels)
|
||||
handle := m.AcquireHandle(labels)
|
||||
handle.Record(ctx, 42)
|
||||
meter.RecordBatch(ctx, labels, m.Measurement(42))
|
||||
t.Log("Testing int measure")
|
||||
checkBatches(t, ctx, labels, meter, m.Descriptor())
|
||||
checkBatches(t, ctx, labels, meter, Int64ValueKind, m.instrument)
|
||||
}
|
||||
}
|
||||
|
||||
func checkBatches(t *testing.T, ctx context.Context, labels LabelSet, meter *mockMeter, descriptor *Descriptor) {
|
||||
func checkBatches(t *testing.T, ctx context.Context, labels LabelSet, meter *mockMeter, kind ValueKind, instrument Instrument) {
|
||||
t.Helper()
|
||||
if len(meter.measurementBatches) != 3 {
|
||||
t.Errorf("Expected 3 recorded measurement batches, got %d", len(meter.measurementBatches))
|
||||
}
|
||||
ourInstrument := instrument.(*mockInstrument)
|
||||
ourLabelSet := labels.(*mockLabelSet)
|
||||
minLen := 3
|
||||
if minLen > len(meter.measurementBatches) {
|
||||
@ -538,15 +480,15 @@ func checkBatches(t *testing.T, ctx context.Context, labels LabelSet, meter *moc
|
||||
}
|
||||
for j := 0; j < minMLen; j++ {
|
||||
measurement := got.measurements[j]
|
||||
if measurement.Descriptor != descriptor {
|
||||
d := func(d *Descriptor) string {
|
||||
return fmt.Sprintf("(ptr: %p, descriptor %#v)", d, d)
|
||||
if measurement.instrument != ourInstrument {
|
||||
d := func(i *mockInstrument) string {
|
||||
return fmt.Sprintf("(ptr: %p, instrument %#v)", i, i)
|
||||
}
|
||||
t.Errorf("Wrong recorded descriptor in measurement %d in batch %d, expected %s, got %s", j, i, d(descriptor), d(measurement.Descriptor))
|
||||
t.Errorf("Wrong recorded instrument in measurement %d in batch %d, expected %s, got %s", j, i, d(ourInstrument), d(measurement.instrument))
|
||||
}
|
||||
ft := fortyTwo(t, descriptor.ValueKind())
|
||||
if measurement.Value.RawCompare(ft.AsRaw(), descriptor.ValueKind()) != 0 {
|
||||
t.Errorf("Wrong recorded value in measurement %d in batch %d, expected %s, got %s", j, i, ft.Emit(descriptor.ValueKind()), measurement.Value.Emit(descriptor.ValueKind()))
|
||||
ft := fortyTwo(t, kind)
|
||||
if measurement.value.RawCompare(ft.AsRaw(), kind) != 0 {
|
||||
t.Errorf("Wrong recorded value in measurement %d in batch %d, expected %s, got %s", j, i, ft.Emit(kind), measurement.value.Emit(kind))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,63 +16,55 @@ package metric
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var (
|
||||
descriptorID uint64
|
||||
)
|
||||
|
||||
type commonMetric struct {
|
||||
d *Descriptor
|
||||
instrument Instrument
|
||||
}
|
||||
|
||||
var _ ExplicitReportingMetric = commonMetric{}
|
||||
|
||||
func (m commonMetric) Descriptor() *Descriptor {
|
||||
return m.d
|
||||
type commonHandle struct {
|
||||
handle Handle
|
||||
}
|
||||
|
||||
func (m commonMetric) SupportHandle() hiddenType {
|
||||
return hiddenType{}
|
||||
}
|
||||
|
||||
func (m commonMetric) getHandle(labels LabelSet) Handle {
|
||||
return labels.Meter().NewHandle(m, labels)
|
||||
func (m commonMetric) acquireCommonHandle(labels LabelSet) commonHandle {
|
||||
return newCommonHandle(m.instrument.AcquireHandle(labels))
|
||||
}
|
||||
|
||||
func (m commonMetric) float64Measurement(value float64) Measurement {
|
||||
return Measurement{
|
||||
Descriptor: m.d,
|
||||
Value: NewFloat64MeasurementValue(value),
|
||||
}
|
||||
return newMeasurement(m.instrument, NewFloat64MeasurementValue(value))
|
||||
}
|
||||
|
||||
func (m commonMetric) int64Measurement(value int64) Measurement {
|
||||
return Measurement{
|
||||
Descriptor: m.d,
|
||||
Value: NewInt64MeasurementValue(value),
|
||||
}
|
||||
return newMeasurement(m.instrument, NewInt64MeasurementValue(value))
|
||||
}
|
||||
|
||||
func (m commonMetric) recordOne(ctx context.Context, value MeasurementValue, labels LabelSet) {
|
||||
labels.Meter().RecordBatch(ctx, labels, Measurement{
|
||||
Descriptor: m.d,
|
||||
Value: value,
|
||||
})
|
||||
m.instrument.RecordOne(ctx, value, labels)
|
||||
}
|
||||
|
||||
func registerCommonMetric(name string, kind Kind, valueKind ValueKind) commonMetric {
|
||||
func (h commonHandle) recordOne(ctx context.Context, value MeasurementValue) {
|
||||
h.handle.RecordOne(ctx, value)
|
||||
}
|
||||
|
||||
func (h commonHandle) Release() {
|
||||
h.handle.Release()
|
||||
}
|
||||
|
||||
func newCommonMetric(instrument Instrument) commonMetric {
|
||||
return commonMetric{
|
||||
d: registerDescriptor(name, kind, valueKind),
|
||||
instrument: instrument,
|
||||
}
|
||||
}
|
||||
|
||||
func registerDescriptor(name string, kind Kind, valueKind ValueKind) *Descriptor {
|
||||
return &Descriptor{
|
||||
name: name,
|
||||
kind: kind,
|
||||
valueKind: valueKind,
|
||||
id: DescriptorID(atomic.AddUint64(&descriptorID, 1)),
|
||||
func newCommonHandle(handle Handle) commonHandle {
|
||||
return commonHandle{
|
||||
handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
func newMeasurement(instrument Instrument, value MeasurementValue) Measurement {
|
||||
return Measurement{
|
||||
instrument: instrument,
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
|
@ -29,78 +29,40 @@ type Int64Counter struct {
|
||||
}
|
||||
|
||||
// Float64CounterHandle is a handle for Float64Counter.
|
||||
//
|
||||
// It inherits the Release function from commonHandle.
|
||||
type Float64CounterHandle struct {
|
||||
Handle
|
||||
commonHandle
|
||||
}
|
||||
|
||||
// Int64CounterHandle is a handle for Int64Counter.
|
||||
//
|
||||
// It inherits the Release function from commonHandle.
|
||||
type Int64CounterHandle struct {
|
||||
Handle
|
||||
commonHandle
|
||||
}
|
||||
|
||||
// CounterOptionApplier is an interface for applying metric options
|
||||
// that are valid only for counter metrics.
|
||||
type CounterOptionApplier interface {
|
||||
// ApplyCounterOption is used to make some counter-specific
|
||||
// changes in the Descriptor.
|
||||
ApplyCounterOption(*Descriptor)
|
||||
}
|
||||
|
||||
type counterOptionWrapper struct {
|
||||
F Option
|
||||
}
|
||||
|
||||
var (
|
||||
_ CounterOptionApplier = counterOptionWrapper{}
|
||||
_ ExplicitReportingMetric = Float64Counter{}
|
||||
_ ExplicitReportingMetric = Int64Counter{}
|
||||
)
|
||||
|
||||
func (o counterOptionWrapper) ApplyCounterOption(d *Descriptor) {
|
||||
o.F(d)
|
||||
}
|
||||
|
||||
func newCounter(name string, valueKind ValueKind, mos ...CounterOptionApplier) commonMetric {
|
||||
m := registerCommonMetric(name, CounterKind, valueKind)
|
||||
for _, opt := range mos {
|
||||
opt.ApplyCounterOption(m.Descriptor())
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// NewFloat64Counter creates a new counter for float64.
|
||||
func NewFloat64Counter(name string, mos ...CounterOptionApplier) (c Float64Counter) {
|
||||
c.commonMetric = newCounter(name, Float64ValueKind, mos...)
|
||||
return
|
||||
}
|
||||
|
||||
// NewInt64Counter creates a new counter for int64.
|
||||
func NewInt64Counter(name string, mos ...CounterOptionApplier) (c Int64Counter) {
|
||||
c.commonMetric = newCounter(name, Int64ValueKind, mos...)
|
||||
return
|
||||
}
|
||||
|
||||
// GetHandle creates a handle for this counter. The labels should
|
||||
// AcquireHandle creates a handle for this counter. The labels should
|
||||
// contain the keys and values for each key specified in the counter
|
||||
// with the WithKeys option.
|
||||
//
|
||||
// If the labels do not contain a value for the key specified in the
|
||||
// counter with the WithKeys option, then the missing value will be
|
||||
// treated as unspecified.
|
||||
func (c *Float64Counter) GetHandle(labels LabelSet) (h Float64CounterHandle) {
|
||||
h.Handle = c.getHandle(labels)
|
||||
func (c *Float64Counter) AcquireHandle(labels LabelSet) (h Float64CounterHandle) {
|
||||
h.commonHandle = c.acquireCommonHandle(labels)
|
||||
return
|
||||
}
|
||||
|
||||
// GetHandle creates a handle for this counter. The labels should
|
||||
// AcquireHandle creates a handle for this counter. The labels should
|
||||
// contain the keys and values for each key specified in the counter
|
||||
// with the WithKeys option.
|
||||
//
|
||||
// If the labels do not contain a value for the key specified in the
|
||||
// counter with the WithKeys option, then the missing value will be
|
||||
// treated as unspecified.
|
||||
func (c *Int64Counter) GetHandle(labels LabelSet) (h Int64CounterHandle) {
|
||||
h.Handle = c.getHandle(labels)
|
||||
func (c *Int64Counter) AcquireHandle(labels LabelSet) (h Int64CounterHandle) {
|
||||
h.commonHandle = c.acquireCommonHandle(labels)
|
||||
return
|
||||
}
|
||||
|
||||
@ -140,10 +102,10 @@ func (c *Int64Counter) Add(ctx context.Context, value int64, labels LabelSet) {
|
||||
|
||||
// Add adds the value to the counter's sum.
|
||||
func (h *Float64CounterHandle) Add(ctx context.Context, value float64) {
|
||||
h.RecordOne(ctx, NewFloat64MeasurementValue(value))
|
||||
h.recordOne(ctx, NewFloat64MeasurementValue(value))
|
||||
}
|
||||
|
||||
// Add adds the value to the counter's sum.
|
||||
func (h *Int64CounterHandle) Add(ctx context.Context, value int64) {
|
||||
h.RecordOne(ctx, NewInt64MeasurementValue(value))
|
||||
h.recordOne(ctx, NewInt64MeasurementValue(value))
|
||||
}
|
||||
|
@ -36,9 +36,10 @@
|
||||
// example could be bank account balance or bytes downloaded. Counters
|
||||
// can be created with either NewFloat64Counter or
|
||||
// NewInt64Counter. Counters expect non-negative values by default to
|
||||
// be reported. This can be changed with the WithNonMonotonic option
|
||||
// passed to the New*Counter function - this allows reporting negative
|
||||
// values. To report the new value, use an Add function.
|
||||
// be reported. This can be changed with the WithMonotonic option
|
||||
// (passing false as a parameter) passed to the Meter.New*Counter
|
||||
// function - this allows reporting negative values. To report the new
|
||||
// value, use an Add function.
|
||||
//
|
||||
// Gauges are instruments that are reporting a current state of a
|
||||
// value. An example could be voltage or temperature. Gauges can be
|
||||
@ -55,13 +56,14 @@
|
||||
// time or lines of code in the project over time. Measures can be
|
||||
// created with either NewFloat64Measure or NewInt64Measure. Measures
|
||||
// by default take only non-negative values. This can be changed with
|
||||
// the WithSigned option passed to the New*Measure function - this
|
||||
// allows reporting negative values too. To report a new value, use
|
||||
// the Record function.
|
||||
// the WithAbsolute option (passing false as a parameter) passed to
|
||||
// the New*Measure function - this allows reporting negative values
|
||||
// too. To report a new value, use the Record function.
|
||||
//
|
||||
// All the basic kinds of instruments also support creating handles
|
||||
// for a potentially more efficient reporting. The handles have the
|
||||
// same function names as the instruments (so counter handle has Add,
|
||||
// gauge handle has Set and measure handle has Record). Handles can be
|
||||
// created with the GetHandle function of the respective instrument.
|
||||
// created with the AcquireHandle function of the respective
|
||||
// instrument. When done with the handle, call Release on it.
|
||||
package metric // import "go.opentelemetry.io/api/metric"
|
||||
|
@ -29,78 +29,40 @@ type Int64Gauge struct {
|
||||
}
|
||||
|
||||
// Float64GaugeHandle is a handle for Float64Gauge.
|
||||
//
|
||||
// It inherits the Release function from commonHandle.
|
||||
type Float64GaugeHandle struct {
|
||||
Handle
|
||||
commonHandle
|
||||
}
|
||||
|
||||
// Int64GaugeHandle is a handle for Int64Gauge.
|
||||
//
|
||||
// It inherits the Release function from commonHandle.
|
||||
type Int64GaugeHandle struct {
|
||||
Handle
|
||||
commonHandle
|
||||
}
|
||||
|
||||
// GaugeOptionApplier is an interface for applying metric options that
|
||||
// are valid only for gauge metrics.
|
||||
type GaugeOptionApplier interface {
|
||||
// ApplyGaugeOption is used to make some gauge-specific
|
||||
// changes in the Descriptor.
|
||||
ApplyGaugeOption(*Descriptor)
|
||||
}
|
||||
|
||||
type gaugeOptionWrapper struct {
|
||||
F Option
|
||||
}
|
||||
|
||||
var (
|
||||
_ GaugeOptionApplier = gaugeOptionWrapper{}
|
||||
_ ExplicitReportingMetric = Float64Gauge{}
|
||||
_ ExplicitReportingMetric = Int64Gauge{}
|
||||
)
|
||||
|
||||
func (o gaugeOptionWrapper) ApplyGaugeOption(d *Descriptor) {
|
||||
o.F(d)
|
||||
}
|
||||
|
||||
func newGauge(name string, valueKind ValueKind, mos ...GaugeOptionApplier) commonMetric {
|
||||
m := registerCommonMetric(name, GaugeKind, valueKind)
|
||||
for _, opt := range mos {
|
||||
opt.ApplyGaugeOption(m.Descriptor())
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// NewFloat64Gauge creates a new gauge for float64.
|
||||
func NewFloat64Gauge(name string, mos ...GaugeOptionApplier) (g Float64Gauge) {
|
||||
g.commonMetric = newGauge(name, Float64ValueKind, mos...)
|
||||
return
|
||||
}
|
||||
|
||||
// NewInt64Gauge creates a new gauge for int64.
|
||||
func NewInt64Gauge(name string, mos ...GaugeOptionApplier) (g Int64Gauge) {
|
||||
g.commonMetric = newGauge(name, Int64ValueKind, mos...)
|
||||
return
|
||||
}
|
||||
|
||||
// GetHandle creates a handle for this gauge. The labels should
|
||||
// AcquireHandle creates a handle for this gauge. The labels should
|
||||
// contain the keys and values for each key specified in the gauge
|
||||
// with the WithKeys option.
|
||||
//
|
||||
// If the labels do not contain a value for the key specified in the
|
||||
// gauge with the WithKeys option, then the missing value will be
|
||||
// treated as unspecified.
|
||||
func (g *Float64Gauge) GetHandle(labels LabelSet) (h Float64GaugeHandle) {
|
||||
h.Handle = g.getHandle(labels)
|
||||
func (g *Float64Gauge) AcquireHandle(labels LabelSet) (h Float64GaugeHandle) {
|
||||
h.commonHandle = g.acquireCommonHandle(labels)
|
||||
return
|
||||
}
|
||||
|
||||
// GetHandle creates a handle for this gauge. The labels should
|
||||
// AcquireHandle creates a handle for this gauge. The labels should
|
||||
// contain the keys and values for each key specified in the gauge
|
||||
// with the WithKeys option.
|
||||
//
|
||||
// If the labels do not contain a value for the key specified in the
|
||||
// gauge with the WithKeys option, then the missing value will be
|
||||
// treated as unspecified.
|
||||
func (g *Int64Gauge) GetHandle(labels LabelSet) (h Int64GaugeHandle) {
|
||||
h.Handle = g.getHandle(labels)
|
||||
func (g *Int64Gauge) AcquireHandle(labels LabelSet) (h Int64GaugeHandle) {
|
||||
h.commonHandle = g.acquireCommonHandle(labels)
|
||||
return
|
||||
}
|
||||
|
||||
@ -140,10 +102,10 @@ func (g *Int64Gauge) Set(ctx context.Context, value int64, labels LabelSet) {
|
||||
|
||||
// Set assigns the passed value to the value of the gauge.
|
||||
func (h *Float64GaugeHandle) Set(ctx context.Context, value float64) {
|
||||
h.RecordOne(ctx, NewFloat64MeasurementValue(value))
|
||||
h.recordOne(ctx, NewFloat64MeasurementValue(value))
|
||||
}
|
||||
|
||||
// Set assigns the passed value to the value of the gauge.
|
||||
func (h *Int64GaugeHandle) Set(ctx context.Context, value int64) {
|
||||
h.RecordOne(ctx, NewInt64MeasurementValue(value))
|
||||
h.recordOne(ctx, NewInt64MeasurementValue(value))
|
||||
}
|
||||
|
@ -14,7 +14,9 @@
|
||||
|
||||
package metric
|
||||
|
||||
import "sync/atomic"
|
||||
import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var global atomic.Value
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
// Code generated by "stringer -type=Kind,ValueKind"; DO NOT EDIT.
|
||||
|
||||
package metric
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[Invalid-0]
|
||||
_ = x[CounterKind-1]
|
||||
_ = x[GaugeKind-2]
|
||||
_ = x[MeasureKind-3]
|
||||
}
|
||||
|
||||
const _Kind_name = "InvalidCounterKindGaugeKindMeasureKind"
|
||||
|
||||
var _Kind_index = [...]uint8{0, 7, 18, 27, 38}
|
||||
|
||||
func (i Kind) String() string {
|
||||
if i < 0 || i >= Kind(len(_Kind_index)-1) {
|
||||
return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
|
||||
}
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[Int64ValueKind-0]
|
||||
_ = x[Float64ValueKind-1]
|
||||
}
|
||||
|
||||
const _ValueKind_name = "Int64ValueKindFloat64ValueKind"
|
||||
|
||||
var _ValueKind_index = [...]uint8{0, 14, 30}
|
||||
|
||||
func (i ValueKind) String() string {
|
||||
if i < 0 || i >= ValueKind(len(_ValueKind_index)-1) {
|
||||
return "ValueKind(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _ValueKind_name[_ValueKind_index[i]:_ValueKind_index[i+1]]
|
||||
}
|
@ -29,78 +29,40 @@ type Int64Measure struct {
|
||||
}
|
||||
|
||||
// Float64MeasureHandle is a handle for Float64Measure.
|
||||
//
|
||||
// It inherits the Release function from commonHandle.
|
||||
type Float64MeasureHandle struct {
|
||||
Handle
|
||||
commonHandle
|
||||
}
|
||||
|
||||
// Int64MeasureHandle is a handle for Int64Measure.
|
||||
//
|
||||
// It inherits the Release function from commonHandle.
|
||||
type Int64MeasureHandle struct {
|
||||
Handle
|
||||
commonHandle
|
||||
}
|
||||
|
||||
// MeasureOptionApplier is an interface for applying metric options
|
||||
// that are valid only for measure metrics.
|
||||
type MeasureOptionApplier interface {
|
||||
// ApplyMeasureOption is used to make some measure-specific
|
||||
// changes in the Descriptor.
|
||||
ApplyMeasureOption(*Descriptor)
|
||||
}
|
||||
|
||||
type measureOptionWrapper struct {
|
||||
F Option
|
||||
}
|
||||
|
||||
var (
|
||||
_ MeasureOptionApplier = measureOptionWrapper{}
|
||||
_ ExplicitReportingMetric = Float64Measure{}
|
||||
_ ExplicitReportingMetric = Int64Measure{}
|
||||
)
|
||||
|
||||
func (o measureOptionWrapper) ApplyMeasureOption(d *Descriptor) {
|
||||
o.F(d)
|
||||
}
|
||||
|
||||
func newMeasure(name string, valueKind ValueKind, mos ...MeasureOptionApplier) commonMetric {
|
||||
m := registerCommonMetric(name, MeasureKind, valueKind)
|
||||
for _, opt := range mos {
|
||||
opt.ApplyMeasureOption(m.Descriptor())
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// NewFloat64Measure creates a new measure for float64.
|
||||
func NewFloat64Measure(name string, mos ...MeasureOptionApplier) (c Float64Measure) {
|
||||
c.commonMetric = newMeasure(name, Float64ValueKind, mos...)
|
||||
return
|
||||
}
|
||||
|
||||
// NewInt64Measure creates a new measure for int64.
|
||||
func NewInt64Measure(name string, mos ...MeasureOptionApplier) (c Int64Measure) {
|
||||
c.commonMetric = newMeasure(name, Int64ValueKind, mos...)
|
||||
return
|
||||
}
|
||||
|
||||
// GetHandle creates a handle for this measure. The labels should
|
||||
// AcquireHandle creates a handle for this measure. The labels should
|
||||
// contain the keys and values for each key specified in the measure
|
||||
// with the WithKeys option.
|
||||
//
|
||||
// If the labels do not contain a value for the key specified in the
|
||||
// measure with the WithKeys option, then the missing value will be
|
||||
// treated as unspecified.
|
||||
func (c *Float64Measure) GetHandle(labels LabelSet) (h Float64MeasureHandle) {
|
||||
h.Handle = c.getHandle(labels)
|
||||
func (c *Float64Measure) AcquireHandle(labels LabelSet) (h Float64MeasureHandle) {
|
||||
h.commonHandle = c.acquireCommonHandle(labels)
|
||||
return
|
||||
}
|
||||
|
||||
// GetHandle creates a handle for this measure. The labels should
|
||||
// AcquireHandle creates a handle for this measure. The labels should
|
||||
// contain the keys and values for each key specified in the measure
|
||||
// with the WithKeys option.
|
||||
//
|
||||
// If the labels do not contain a value for the key specified in the
|
||||
// measure with the WithKeys option, then the missing value will be
|
||||
// treated as unspecified.
|
||||
func (c *Int64Measure) GetHandle(labels LabelSet) (h Int64MeasureHandle) {
|
||||
h.Handle = c.getHandle(labels)
|
||||
func (c *Int64Measure) AcquireHandle(labels LabelSet) (h Int64MeasureHandle) {
|
||||
h.commonHandle = c.acquireCommonHandle(labels)
|
||||
return
|
||||
}
|
||||
|
||||
@ -140,10 +102,10 @@ func (c *Int64Measure) Record(ctx context.Context, value int64, labels LabelSet)
|
||||
|
||||
// Record adds a new value to the list of measure's records.
|
||||
func (h *Float64MeasureHandle) Record(ctx context.Context, value float64) {
|
||||
h.RecordOne(ctx, NewFloat64MeasurementValue(value))
|
||||
h.recordOne(ctx, NewFloat64MeasurementValue(value))
|
||||
}
|
||||
|
||||
// Record adds a new value to the list of measure's records.
|
||||
func (h *Int64MeasureHandle) Record(ctx context.Context, value int64) {
|
||||
h.RecordOne(ctx, NewInt64MeasurementValue(value))
|
||||
h.recordOne(ctx, NewInt64MeasurementValue(value))
|
||||
}
|
||||
|
@ -22,10 +22,17 @@ import (
|
||||
|
||||
type (
|
||||
mockHandle struct {
|
||||
descriptor *Descriptor
|
||||
instrument *mockInstrument
|
||||
labelSet *mockLabelSet
|
||||
}
|
||||
|
||||
mockInstrument struct {
|
||||
name string
|
||||
kind mockKind
|
||||
valueKind ValueKind
|
||||
opts Options
|
||||
}
|
||||
|
||||
mockLabelSet struct {
|
||||
meter *mockMeter
|
||||
labels map[core.Key]core.Value
|
||||
@ -34,24 +41,56 @@ type (
|
||||
batch struct {
|
||||
ctx context.Context
|
||||
labelSet *mockLabelSet
|
||||
measurements []Measurement
|
||||
measurements []mockMeasurement
|
||||
}
|
||||
|
||||
mockMeter struct {
|
||||
measurementBatches []batch
|
||||
}
|
||||
|
||||
mockKind int8
|
||||
|
||||
mockMeasurement struct {
|
||||
instrument *mockInstrument
|
||||
value MeasurementValue
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
_ Handle = &mockHandle{}
|
||||
_ LabelSet = &mockLabelSet{}
|
||||
_ Meter = &mockMeter{}
|
||||
_ Instrument = &mockInstrument{}
|
||||
_ Handle = &mockHandle{}
|
||||
_ LabelSet = &mockLabelSet{}
|
||||
_ Meter = &mockMeter{}
|
||||
)
|
||||
|
||||
const (
|
||||
mockKindCounter mockKind = iota
|
||||
mockKindGauge
|
||||
mockKindMeasure
|
||||
)
|
||||
|
||||
func (i *mockInstrument) AcquireHandle(labels LabelSet) Handle {
|
||||
return &mockHandle{
|
||||
instrument: i,
|
||||
labelSet: labels.(*mockLabelSet),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *mockInstrument) RecordOne(ctx context.Context, value MeasurementValue, labels LabelSet) {
|
||||
doRecordBatch(labels.(*mockLabelSet), ctx, i, value)
|
||||
}
|
||||
|
||||
func (h *mockHandle) RecordOne(ctx context.Context, value MeasurementValue) {
|
||||
h.labelSet.meter.RecordBatch(ctx, h.labelSet, Measurement{
|
||||
Descriptor: h.descriptor,
|
||||
Value: value,
|
||||
doRecordBatch(h.labelSet, ctx, h.instrument, value)
|
||||
}
|
||||
|
||||
func (h *mockHandle) Release() {
|
||||
}
|
||||
|
||||
func doRecordBatch(labelSet *mockLabelSet, ctx context.Context, instrument *mockInstrument, value MeasurementValue) {
|
||||
labelSet.meter.recordMockBatch(ctx, labelSet, mockMeasurement{
|
||||
instrument: instrument,
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
|
||||
@ -63,7 +102,7 @@ func newMockMeter() *mockMeter {
|
||||
return &mockMeter{}
|
||||
}
|
||||
|
||||
func (m *mockMeter) DefineLabels(ctx context.Context, labels ...core.KeyValue) LabelSet {
|
||||
func (m *mockMeter) Labels(ctx context.Context, labels ...core.KeyValue) LabelSet {
|
||||
ul := make(map[core.Key]core.Value)
|
||||
for _, kv := range labels {
|
||||
ul[kv.Key] = kv.Value
|
||||
@ -74,24 +113,86 @@ func (m *mockMeter) DefineLabels(ctx context.Context, labels ...core.KeyValue) L
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockMeter) RecordBatch(ctx context.Context, labels LabelSet, measurements ...Measurement) {
|
||||
ourLabelSet := labels.(*mockLabelSet)
|
||||
m.measurementBatches = append(m.measurementBatches, batch{
|
||||
ctx: ctx,
|
||||
labelSet: ourLabelSet,
|
||||
measurements: measurements,
|
||||
})
|
||||
func (m *mockMeter) NewInt64Counter(name string, cos ...CounterOptionApplier) Int64Counter {
|
||||
instrument := m.newCounterInstrument(name, Int64ValueKind, cos...)
|
||||
return WrapInt64CounterInstrument(instrument)
|
||||
}
|
||||
|
||||
func (m *mockMeter) NewHandle(erm ExplicitReportingMetric, labels LabelSet) Handle {
|
||||
descriptor := erm.Descriptor()
|
||||
ourLabels := labels.(*mockLabelSet)
|
||||
func (m *mockMeter) NewFloat64Counter(name string, cos ...CounterOptionApplier) Float64Counter {
|
||||
instrument := m.newCounterInstrument(name, Float64ValueKind, cos...)
|
||||
return WrapFloat64CounterInstrument(instrument)
|
||||
}
|
||||
|
||||
return &mockHandle{
|
||||
descriptor: descriptor,
|
||||
labelSet: ourLabels,
|
||||
func (m *mockMeter) newCounterInstrument(name string, valueKind ValueKind, cos ...CounterOptionApplier) *mockInstrument {
|
||||
opts := Options{}
|
||||
ApplyCounterOptions(&opts, cos...)
|
||||
return &mockInstrument{
|
||||
name: name,
|
||||
kind: mockKindCounter,
|
||||
valueKind: valueKind,
|
||||
opts: opts,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockMeter) DeleteHandle(Handle) {
|
||||
func (m *mockMeter) NewInt64Gauge(name string, gos ...GaugeOptionApplier) Int64Gauge {
|
||||
instrument := m.newGaugeInstrument(name, Int64ValueKind, gos...)
|
||||
return WrapInt64GaugeInstrument(instrument)
|
||||
}
|
||||
|
||||
func (m *mockMeter) NewFloat64Gauge(name string, gos ...GaugeOptionApplier) Float64Gauge {
|
||||
instrument := m.newGaugeInstrument(name, Float64ValueKind, gos...)
|
||||
return WrapFloat64GaugeInstrument(instrument)
|
||||
}
|
||||
|
||||
func (m *mockMeter) newGaugeInstrument(name string, valueKind ValueKind, gos ...GaugeOptionApplier) *mockInstrument {
|
||||
opts := Options{}
|
||||
ApplyGaugeOptions(&opts, gos...)
|
||||
return &mockInstrument{
|
||||
name: name,
|
||||
kind: mockKindGauge,
|
||||
valueKind: valueKind,
|
||||
opts: opts,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockMeter) NewInt64Measure(name string, mos ...MeasureOptionApplier) Int64Measure {
|
||||
instrument := m.newMeasureInstrument(name, Int64ValueKind, mos...)
|
||||
return WrapInt64MeasureInstrument(instrument)
|
||||
}
|
||||
|
||||
func (m *mockMeter) NewFloat64Measure(name string, mos ...MeasureOptionApplier) Float64Measure {
|
||||
instrument := m.newMeasureInstrument(name, Float64ValueKind, mos...)
|
||||
return WrapFloat64MeasureInstrument(instrument)
|
||||
}
|
||||
|
||||
func (m *mockMeter) newMeasureInstrument(name string, valueKind ValueKind, mos ...MeasureOptionApplier) *mockInstrument {
|
||||
opts := Options{}
|
||||
ApplyMeasureOptions(&opts, mos...)
|
||||
return &mockInstrument{
|
||||
name: name,
|
||||
kind: mockKindMeasure,
|
||||
valueKind: valueKind,
|
||||
opts: opts,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockMeter) RecordBatch(ctx context.Context, labels LabelSet, measurements ...Measurement) {
|
||||
ourLabelSet := labels.(*mockLabelSet)
|
||||
mm := make([]mockMeasurement, len(measurements))
|
||||
for i := 0; i < len(measurements); i++ {
|
||||
m := measurements[i]
|
||||
mm[i] = mockMeasurement{
|
||||
instrument: m.Instrument().(*mockInstrument),
|
||||
value: m.Value(),
|
||||
}
|
||||
}
|
||||
m.recordMockBatch(ctx, ourLabelSet, mm...)
|
||||
}
|
||||
|
||||
func (m *mockMeter) recordMockBatch(ctx context.Context, labelSet *mockLabelSet, measurements ...mockMeasurement) {
|
||||
m.measurementBatches = append(m.measurementBatches, batch{
|
||||
ctx: ctx,
|
||||
labelSet: labelSet,
|
||||
measurements: measurements,
|
||||
})
|
||||
}
|
||||
|
@ -9,27 +9,56 @@ import (
|
||||
type noopMeter struct{}
|
||||
type noopHandle struct{}
|
||||
type noopLabelSet struct{}
|
||||
type noopInstrument struct{}
|
||||
|
||||
var _ Meter = noopMeter{}
|
||||
var _ Instrument = noopInstrument{}
|
||||
var _ Handle = noopHandle{}
|
||||
var _ LabelSet = noopLabelSet{}
|
||||
|
||||
func (noopHandle) RecordOne(context.Context, MeasurementValue) {
|
||||
}
|
||||
|
||||
func (noopHandle) Release() {
|
||||
}
|
||||
|
||||
func (noopInstrument) AcquireHandle(LabelSet) Handle {
|
||||
return noopHandle{}
|
||||
}
|
||||
|
||||
func (noopInstrument) RecordOne(context.Context, MeasurementValue, LabelSet) {
|
||||
}
|
||||
|
||||
func (noopLabelSet) Meter() Meter {
|
||||
return noopMeter{}
|
||||
}
|
||||
|
||||
func (noopMeter) DefineLabels(context.Context, ...core.KeyValue) LabelSet {
|
||||
func (noopMeter) Labels(context.Context, ...core.KeyValue) LabelSet {
|
||||
return noopLabelSet{}
|
||||
}
|
||||
|
||||
func (noopMeter) NewHandle(ExplicitReportingMetric, LabelSet) Handle {
|
||||
return noopHandle{}
|
||||
func (noopMeter) NewInt64Counter(name string, cos ...CounterOptionApplier) Int64Counter {
|
||||
return WrapInt64CounterInstrument(noopInstrument{})
|
||||
}
|
||||
|
||||
func (noopMeter) DeleteHandle(Handle) {
|
||||
func (noopMeter) NewFloat64Counter(name string, cos ...CounterOptionApplier) Float64Counter {
|
||||
return WrapFloat64CounterInstrument(noopInstrument{})
|
||||
}
|
||||
|
||||
func (noopMeter) NewInt64Gauge(name string, gos ...GaugeOptionApplier) Int64Gauge {
|
||||
return WrapInt64GaugeInstrument(noopInstrument{})
|
||||
}
|
||||
|
||||
func (noopMeter) NewFloat64Gauge(name string, gos ...GaugeOptionApplier) Float64Gauge {
|
||||
return WrapFloat64GaugeInstrument(noopInstrument{})
|
||||
}
|
||||
|
||||
func (noopMeter) NewInt64Measure(name string, mos ...MeasureOptionApplier) Int64Measure {
|
||||
return WrapInt64MeasureInstrument(noopInstrument{})
|
||||
}
|
||||
|
||||
func (noopMeter) NewFloat64Measure(name string, mos ...MeasureOptionApplier) Float64Measure {
|
||||
return WrapFloat64MeasureInstrument(noopInstrument{})
|
||||
}
|
||||
|
||||
func (noopMeter) RecordBatch(context.Context, LabelSet, ...Measurement) {
|
||||
|
87
api/metric/sdkhelpers.go
Normal file
87
api/metric/sdkhelpers.go
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright 2019, OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package metric
|
||||
|
||||
// WrapInt64CounterInstrument wraps the instrument in the type-safe
|
||||
// wrapper as an integral counter.
|
||||
//
|
||||
// It is mostly intended for SDKs.
|
||||
func WrapInt64CounterInstrument(instrument Instrument) Int64Counter {
|
||||
return Int64Counter{commonMetric: newCommonMetric(instrument)}
|
||||
}
|
||||
|
||||
// WrapFloat64CounterInstrument wraps the instrument in the type-safe
|
||||
// wrapper as an floating point counter.
|
||||
//
|
||||
// It is mostly intended for SDKs.
|
||||
func WrapFloat64CounterInstrument(instrument Instrument) Float64Counter {
|
||||
return Float64Counter{commonMetric: newCommonMetric(instrument)}
|
||||
}
|
||||
|
||||
// WrapInt64GaugeInstrument wraps the instrument in the type-safe
|
||||
// wrapper as an integral gauge.
|
||||
//
|
||||
// It is mostly intended for SDKs.
|
||||
func WrapInt64GaugeInstrument(instrument Instrument) Int64Gauge {
|
||||
return Int64Gauge{commonMetric: newCommonMetric(instrument)}
|
||||
}
|
||||
|
||||
// WrapFloat64GaugeInstrument wraps the instrument in the type-safe
|
||||
// wrapper as an floating point gauge.
|
||||
//
|
||||
// It is mostly intended for SDKs.
|
||||
func WrapFloat64GaugeInstrument(instrument Instrument) Float64Gauge {
|
||||
return Float64Gauge{commonMetric: newCommonMetric(instrument)}
|
||||
}
|
||||
|
||||
// WrapInt64MeasureInstrument wraps the instrument in the type-safe
|
||||
// wrapper as an integral measure.
|
||||
//
|
||||
// It is mostly intended for SDKs.
|
||||
func WrapInt64MeasureInstrument(instrument Instrument) Int64Measure {
|
||||
return Int64Measure{commonMetric: newCommonMetric(instrument)}
|
||||
}
|
||||
|
||||
// WrapFloat64MeasureInstrument wraps the instrument in the type-safe
|
||||
// wrapper as an floating point measure.
|
||||
//
|
||||
// It is mostly intended for SDKs.
|
||||
func WrapFloat64MeasureInstrument(instrument Instrument) Float64Measure {
|
||||
return Float64Measure{commonMetric: newCommonMetric(instrument)}
|
||||
}
|
||||
|
||||
// ApplyCounterOptions is a helper that applies all the counter
|
||||
// options to passed opts.
|
||||
func ApplyCounterOptions(opts *Options, cos ...CounterOptionApplier) {
|
||||
for _, o := range cos {
|
||||
o.ApplyCounterOption(opts)
|
||||
}
|
||||
}
|
||||
|
||||
// ApplyGaugeOptions is a helper that applies all the gauge options to
|
||||
// passed opts.
|
||||
func ApplyGaugeOptions(opts *Options, gos ...GaugeOptionApplier) {
|
||||
for _, o := range gos {
|
||||
o.ApplyGaugeOption(opts)
|
||||
}
|
||||
}
|
||||
|
||||
// ApplyMeasureOptions is a helper that applies all the measure
|
||||
// options to passed opts.
|
||||
func ApplyMeasureOptions(opts *Options, mos ...MeasureOptionApplier) {
|
||||
for _, o := range mos {
|
||||
o.ApplyMeasureOption(opts)
|
||||
}
|
||||
}
|
@ -19,10 +19,25 @@ import (
|
||||
"math"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=ValueKind
|
||||
|
||||
// ValueKind describes the data type of the measurement value the
|
||||
// metric generates.
|
||||
type ValueKind int8
|
||||
|
||||
const (
|
||||
// Int64ValueKind means that the metric generates values of
|
||||
// type int64.
|
||||
Int64ValueKind ValueKind = iota
|
||||
// Float64ValueKind means that the metric generates values of
|
||||
// type float64.
|
||||
Float64ValueKind
|
||||
)
|
||||
|
||||
// MeasurementValue represents either an integral or a floating point
|
||||
// value of a measurement. It needs to be accompanied with a
|
||||
// descriptor of a metric that generated this value to decide what
|
||||
// type of value it represents.
|
||||
// value of a measurement. It needs to be accompanied with a value
|
||||
// kind or some source that provides a value kind describing this
|
||||
// measurement value.
|
||||
type MeasurementValue uint64
|
||||
|
||||
// NewInt64MeasurementValue creates an integral MeasurementValue.
|
||||
@ -41,15 +56,17 @@ func newFromRaw(raw uint64) MeasurementValue {
|
||||
}
|
||||
|
||||
// AsInt64 assumes that the measurement value contains an int64 and
|
||||
// returns it as such. Make sure that metric that generated this value
|
||||
// has indeed Int64ValueKind in its descriptor.
|
||||
// returns it as such. Make sure that the accompanying source of value
|
||||
// kind indeed tells you its a 64 bit integral measurement value,
|
||||
// otherwise the returned int64 will be wrong.
|
||||
func (v MeasurementValue) AsInt64() int64 {
|
||||
return rawToInt64(v.AsRaw())
|
||||
}
|
||||
|
||||
// AsFloat64 assumes that the measurement value contains a float64 and
|
||||
// returns it as such. Make sure that metric that generated this value
|
||||
// has indeed Int64ValueKind in its descriptor.
|
||||
// returns it as such. Make sure that the accompanying source of value
|
||||
// kind indeed tells you its a 64 bit floating point measurement
|
||||
// value, otherwise the returned float64 will be wrong.
|
||||
func (v MeasurementValue) AsFloat64() float64 {
|
||||
return rawToFloat64(v.AsRaw())
|
||||
}
|
||||
|
24
api/metric/valuekind_string.go
Normal file
24
api/metric/valuekind_string.go
Normal file
@ -0,0 +1,24 @@
|
||||
// Code generated by "stringer -type=ValueKind"; DO NOT EDIT.
|
||||
|
||||
package metric
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[Int64ValueKind-0]
|
||||
_ = x[Float64ValueKind-1]
|
||||
}
|
||||
|
||||
const _ValueKind_name = "Int64ValueKindFloat64ValueKind"
|
||||
|
||||
var _ValueKind_index = [...]uint8{0, 14, 30}
|
||||
|
||||
func (i ValueKind) String() string {
|
||||
if i < 0 || i >= ValueKind(len(_ValueKind_index)-1) {
|
||||
return "ValueKind(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _ValueKind_name[_ValueKind_index[i]:_ValueKind_index[i+1]]
|
||||
}
|
@ -32,16 +32,16 @@ var (
|
||||
barKey = key.New("ex.com/bar")
|
||||
lemonsKey = key.New("ex.com/lemons")
|
||||
anotherKey = key.New("ex.com/another")
|
||||
)
|
||||
|
||||
oneMetric = metric.NewFloat64Gauge("ex.com/one",
|
||||
func main() {
|
||||
oneMetric := meter.NewFloat64Gauge("ex.com.one",
|
||||
metric.WithKeys(fooKey, barKey, lemonsKey),
|
||||
metric.WithDescription("A gauge set to 1.0"),
|
||||
)
|
||||
|
||||
measureTwo = metric.NewFloat64Measure("ex.com/two")
|
||||
)
|
||||
measureTwo := meter.NewFloat64Measure("ex.com.two")
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
ctx = distributedcontext.NewContext(ctx,
|
||||
@ -49,11 +49,13 @@ func main() {
|
||||
distributedcontext.Insert(barKey.String("bar1")),
|
||||
)
|
||||
|
||||
commonLabels := meter.DefineLabels(ctx, lemonsKey.Int(10))
|
||||
commonLabels := meter.Labels(ctx, lemonsKey.Int(10))
|
||||
|
||||
gauge := oneMetric.GetHandle(commonLabels)
|
||||
gauge := oneMetric.AcquireHandle(commonLabels)
|
||||
defer gauge.Release()
|
||||
|
||||
measure := measureTwo.GetHandle(commonLabels)
|
||||
measure := measureTwo.AcquireHandle(commonLabels)
|
||||
defer measure.Release()
|
||||
|
||||
err := tracer.WithSpan(ctx, "operation", func(ctx context.Context) error {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user