1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-01-26 03:52:03 +02:00

255 lines
7.7 KiB
Go
Raw Normal View History

// Copyright The OpenTelemetry Authors
2019-06-14 13:09:41 -07:00
//
// 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.
//go:generate stringer -type=Kind
package metric
import (
"context"
"go.opentelemetry.io/otel/api/core"
"go.opentelemetry.io/otel/api/unit"
Add support for Resources in the SDK (#552) * Add support for Resources in the SDK Add `Config` types for the push `Controller` and the `SDK`. Included with this are helper functions to configure the `ErrorHandler` and `Resource`. Add a `Resource` to the Meter `Descriptor`. The choice to add the `Resource` here (instead of say a `Record` or the `Instrument` itself) was motivated by the definition of the `Descriptor` as the way to uniquely describe a metric instrument. Update the push `Controller` and default `SDK` to pass down their configured `Resource` from instantiation to the metric instruments. * Update New SDK constructor documentation * Change NewDescriptor constructor to take opts Add DescriptorConfig and DescriptorOption to configure the metric Descriptor with the description, unit, keys, and resource. Update all function calls to NewDescriptor to use new function signature. * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> * Update and add copyright notices * Update push controller creator func Pass the configured ErrorHandler for the controller to the SDK. * Update Resource integration with the SDK Add back the Resource field to the Descriptor that was moved in the last merge with master. Add a resource.Provider interface. Have the default SDK implement the new resource.Provider interface and integrate the new interface into the newSync/newAsync workflows. Now, if the SDK has a Resource defined it will be passed to all Descriptors created for the instruments it creates. * Remove nil check for metric SDK config * Fix and add test for API Options Add an `Equal` method to the Resource so it can be compared with github.com/google/go-cmp/cmp. Add additional test of the API Option unit tests to ensure WithResource correctly sets a new resource. * Move the resource.Provider interface to the API package Move the interface to where it is used. Fix spelling. * Remove errant line * Remove nil checks for the push controller config * Fix check SDK implements Resourcer * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-20 08:58:32 -07:00
"go.opentelemetry.io/otel/sdk/resource"
)
// Provider supports named Meter instances.
type Provider interface {
2019-11-27 01:54:05 +08:00
// Meter gets a named Meter interface. If the name is an
// empty string, the provider uses a default name.
2019-11-27 01:54:05 +08:00
Meter(name string) Meter
}
// Config contains some options for metrics of any kind.
type Config 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
Add support for Resources in the SDK (#552) * Add support for Resources in the SDK Add `Config` types for the push `Controller` and the `SDK`. Included with this are helper functions to configure the `ErrorHandler` and `Resource`. Add a `Resource` to the Meter `Descriptor`. The choice to add the `Resource` here (instead of say a `Record` or the `Instrument` itself) was motivated by the definition of the `Descriptor` as the way to uniquely describe a metric instrument. Update the push `Controller` and default `SDK` to pass down their configured `Resource` from instantiation to the metric instruments. * Update New SDK constructor documentation * Change NewDescriptor constructor to take opts Add DescriptorConfig and DescriptorOption to configure the metric Descriptor with the description, unit, keys, and resource. Update all function calls to NewDescriptor to use new function signature. * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> * Update and add copyright notices * Update push controller creator func Pass the configured ErrorHandler for the controller to the SDK. * Update Resource integration with the SDK Add back the Resource field to the Descriptor that was moved in the last merge with master. Add a resource.Provider interface. Have the default SDK implement the new resource.Provider interface and integrate the new interface into the newSync/newAsync workflows. Now, if the SDK has a Resource defined it will be passed to all Descriptors created for the instruments it creates. * Remove nil check for metric SDK config * Fix and add test for API Options Add an `Equal` method to the Resource so it can be compared with github.com/google/go-cmp/cmp. Add additional test of the API Option unit tests to ensure WithResource correctly sets a new resource. * Move the resource.Provider interface to the API package Move the interface to where it is used. Fix spelling. * Remove errant line * Remove nil checks for the push controller config * Fix check SDK implements Resourcer * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-20 08:58:32 -07:00
// Resource describes the entity for which measurements are made.
Resource resource.Resource
// LibraryName is the name given to the Meter that created
// this instrument. See `Provider`.
LibraryName string
}
// Option is an interface for applying metric options.
type Option interface {
// Apply is used to set the Option value of a Config.
Apply(*Config)
Add observer metric (#474) * wip: observers * wip: float observers * fix copy pasta * wip: rework observers in sdk * small fix in global meter * wip: aggregators and selectors * wip: monotonicity option for observers * some refactor * wip: docs needs more package docs (especially for api/metric and sdk/metric) * fix ci * Fix copy-pasta in docs Co-Authored-By: Mauricio Vásquez <mauricio@kinvolk.io> * recycle unused recorders in observers if a recorder for a labelset is unused for a second collection cycle in a row, drop it * unregister * thread-safe set callback * Fix docs * Revert "wip: aggregators and selectors" This reverts commit 37b7d05aed5dc90f6d5593325b6eb77494e21736. * update selector * tests * Rework number equality Compare concrete numbers, so we can get actual numbers in the error message when they are not equal, not some uint64 representation. This also uses InDelta for comparing floats. * Ensure that Observers are registered in the same order * Run observers in fixed order So the tests can be reproducible - iterating a map made the order of measurements random. * Ensure the proper alignment of the delegates This wasn't checked at all. After adding the checks, the test-386 failed. * Small tweaks to the global meter test * Ensure proper alignment of the callback pointer test-386 was complaining about it * update docs * update a TODO * address review issues * drop SetCallback Co-authored-by: Mauricio Vásquez <mauricio@kinvolk.io> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-05 12:15:30 -08:00
}
// Measurement is used for reporting a batch of metric
// values. Instances of this type should be created by instruments
// (e.g., Int64Counter.Measurement()).
type Measurement struct {
// number needs to be aligned for 64-bit atomic operations.
number core.Number
instrument SyncImpl
}
// SyncImpl returns the instrument that created this measurement.
// This returns an implementation-level object for use by the SDK,
// users should not refer to this.
func (m Measurement) SyncImpl() SyncImpl {
return m.instrument
}
// Number returns a number recorded in this measurement.
func (m Measurement) Number() core.Number {
return m.number
}
// Kind describes the kind of instrument.
type Kind int8
const (
// MeasureKind indicates a Measure instrument.
MeasureKind Kind = iota
// ObserverKind indicates an Observer instrument.
ObserverKind
// CounterKind indicates a Counter instrument.
CounterKind
)
// Descriptor contains all the settings that describe an instrument,
// including its name, metric kind, number kind, and the configurable
// options.
type Descriptor struct {
name string
kind Kind
numberKind core.NumberKind
config Config
}
// NewDescriptor returns a Descriptor with the given contents.
func NewDescriptor(name string, mkind Kind, nkind core.NumberKind, opts ...Option) Descriptor {
return Descriptor{
name: name,
kind: mkind,
numberKind: nkind,
config: Configure(opts),
}
}
// Name returns the metric instrument's name.
func (d Descriptor) Name() string {
return d.name
}
// MetricKind returns the specific kind of instrument.
func (d Descriptor) MetricKind() Kind {
return d.kind
}
// Keys returns the recommended keys included in the metric
// definition. These keys may be used by a Batcher as a default set
// of grouping keys for the metric instrument.
func (d Descriptor) Keys() []core.Key {
return d.config.Keys
}
// Description provides a human-readable description of the metric
// instrument.
func (d Descriptor) Description() string {
return d.config.Description
}
// Unit describes the units of the metric instrument. Unitless
// metrics return the empty string.
func (d Descriptor) Unit() unit.Unit {
return d.config.Unit
}
// NumberKind returns whether this instrument is declared over int64,
// float64, or uint64 values.
func (d Descriptor) NumberKind() core.NumberKind {
return d.numberKind
}
Add support for Resources in the SDK (#552) * Add support for Resources in the SDK Add `Config` types for the push `Controller` and the `SDK`. Included with this are helper functions to configure the `ErrorHandler` and `Resource`. Add a `Resource` to the Meter `Descriptor`. The choice to add the `Resource` here (instead of say a `Record` or the `Instrument` itself) was motivated by the definition of the `Descriptor` as the way to uniquely describe a metric instrument. Update the push `Controller` and default `SDK` to pass down their configured `Resource` from instantiation to the metric instruments. * Update New SDK constructor documentation * Change NewDescriptor constructor to take opts Add DescriptorConfig and DescriptorOption to configure the metric Descriptor with the description, unit, keys, and resource. Update all function calls to NewDescriptor to use new function signature. * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> * Update and add copyright notices * Update push controller creator func Pass the configured ErrorHandler for the controller to the SDK. * Update Resource integration with the SDK Add back the Resource field to the Descriptor that was moved in the last merge with master. Add a resource.Provider interface. Have the default SDK implement the new resource.Provider interface and integrate the new interface into the newSync/newAsync workflows. Now, if the SDK has a Resource defined it will be passed to all Descriptors created for the instruments it creates. * Remove nil check for metric SDK config * Fix and add test for API Options Add an `Equal` method to the Resource so it can be compared with github.com/google/go-cmp/cmp. Add additional test of the API Option unit tests to ensure WithResource correctly sets a new resource. * Move the resource.Provider interface to the API package Move the interface to where it is used. Fix spelling. * Remove errant line * Remove nil checks for the push controller config * Fix check SDK implements Resourcer * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-20 08:58:32 -07:00
// Resource returns the Resource describing the entity for which the metric
// instrument measures.
func (d Descriptor) Resource() resource.Resource {
return d.config.Resource
}
// LibraryName returns the metric instrument's library name, typically
// given via a call to Provider.Meter().
func (d Descriptor) LibraryName() string {
return d.config.LibraryName
}
// Meter is an interface to the metrics portion of the OpenTelemetry SDK.
type Meter interface {
// RecordBatch atomically records a batch of measurements.
RecordBatch(context.Context, []core.KeyValue, ...Measurement)
// All instrument constructors may return an error for
// conditions such as:
// `name` is an empty string
// `name` was previously registered as a different kind of instrument
// for a given named `Meter`.
// NewInt64Counter creates a new integral counter with a given
// name and customized with passed options.
NewInt64Counter(name string, opts ...Option) (Int64Counter, error)
// NewFloat64Counter creates a new floating point counter with
// a given name and customized with passed options.
NewFloat64Counter(name string, opts ...Option) (Float64Counter, error)
// NewInt64Measure creates a new integral measure with a given
// name and customized with passed options.
NewInt64Measure(name string, opts ...Option) (Int64Measure, error)
// NewFloat64Measure creates a new floating point measure with
// a given name and customized with passed options.
NewFloat64Measure(name string, opts ...Option) (Float64Measure, error)
Add observer metric (#474) * wip: observers * wip: float observers * fix copy pasta * wip: rework observers in sdk * small fix in global meter * wip: aggregators and selectors * wip: monotonicity option for observers * some refactor * wip: docs needs more package docs (especially for api/metric and sdk/metric) * fix ci * Fix copy-pasta in docs Co-Authored-By: Mauricio Vásquez <mauricio@kinvolk.io> * recycle unused recorders in observers if a recorder for a labelset is unused for a second collection cycle in a row, drop it * unregister * thread-safe set callback * Fix docs * Revert "wip: aggregators and selectors" This reverts commit 37b7d05aed5dc90f6d5593325b6eb77494e21736. * update selector * tests * Rework number equality Compare concrete numbers, so we can get actual numbers in the error message when they are not equal, not some uint64 representation. This also uses InDelta for comparing floats. * Ensure that Observers are registered in the same order * Run observers in fixed order So the tests can be reproducible - iterating a map made the order of measurements random. * Ensure the proper alignment of the delegates This wasn't checked at all. After adding the checks, the test-386 failed. * Small tweaks to the global meter test * Ensure proper alignment of the callback pointer test-386 was complaining about it * update docs * update a TODO * address review issues * drop SetCallback Co-authored-by: Mauricio Vásquez <mauricio@kinvolk.io> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-05 12:15:30 -08:00
// RegisterInt64Observer creates a new integral observer with a
// given name, running a given callback, and customized with passed
// options. Callback can be nil.
RegisterInt64Observer(name string, callback Int64ObserverCallback, opts ...Option) (Int64Observer, error)
Add observer metric (#474) * wip: observers * wip: float observers * fix copy pasta * wip: rework observers in sdk * small fix in global meter * wip: aggregators and selectors * wip: monotonicity option for observers * some refactor * wip: docs needs more package docs (especially for api/metric and sdk/metric) * fix ci * Fix copy-pasta in docs Co-Authored-By: Mauricio Vásquez <mauricio@kinvolk.io> * recycle unused recorders in observers if a recorder for a labelset is unused for a second collection cycle in a row, drop it * unregister * thread-safe set callback * Fix docs * Revert "wip: aggregators and selectors" This reverts commit 37b7d05aed5dc90f6d5593325b6eb77494e21736. * update selector * tests * Rework number equality Compare concrete numbers, so we can get actual numbers in the error message when they are not equal, not some uint64 representation. This also uses InDelta for comparing floats. * Ensure that Observers are registered in the same order * Run observers in fixed order So the tests can be reproducible - iterating a map made the order of measurements random. * Ensure the proper alignment of the delegates This wasn't checked at all. After adding the checks, the test-386 failed. * Small tweaks to the global meter test * Ensure proper alignment of the callback pointer test-386 was complaining about it * update docs * update a TODO * address review issues * drop SetCallback Co-authored-by: Mauricio Vásquez <mauricio@kinvolk.io> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-05 12:15:30 -08:00
// RegisterFloat64Observer creates a new floating point observer
// with a given name, running a given callback, and customized with
// passed options. Callback can be nil.
RegisterFloat64Observer(name string, callback Float64ObserverCallback, opts ...Option) (Float64Observer, error)
}
// WithDescription applies provided description.
func WithDescription(desc string) Option {
return descriptionOption(desc)
}
type descriptionOption string
func (d descriptionOption) Apply(config *Config) {
config.Description = string(d)
}
// WithUnit applies provided unit.
func WithUnit(unit unit.Unit) Option {
return unitOption(unit)
Add observer metric (#474) * wip: observers * wip: float observers * fix copy pasta * wip: rework observers in sdk * small fix in global meter * wip: aggregators and selectors * wip: monotonicity option for observers * some refactor * wip: docs needs more package docs (especially for api/metric and sdk/metric) * fix ci * Fix copy-pasta in docs Co-Authored-By: Mauricio Vásquez <mauricio@kinvolk.io> * recycle unused recorders in observers if a recorder for a labelset is unused for a second collection cycle in a row, drop it * unregister * thread-safe set callback * Fix docs * Revert "wip: aggregators and selectors" This reverts commit 37b7d05aed5dc90f6d5593325b6eb77494e21736. * update selector * tests * Rework number equality Compare concrete numbers, so we can get actual numbers in the error message when they are not equal, not some uint64 representation. This also uses InDelta for comparing floats. * Ensure that Observers are registered in the same order * Run observers in fixed order So the tests can be reproducible - iterating a map made the order of measurements random. * Ensure the proper alignment of the delegates This wasn't checked at all. After adding the checks, the test-386 failed. * Small tweaks to the global meter test * Ensure proper alignment of the callback pointer test-386 was complaining about it * update docs * update a TODO * address review issues * drop SetCallback Co-authored-by: Mauricio Vásquez <mauricio@kinvolk.io> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-05 12:15:30 -08:00
}
type unitOption unit.Unit
Add observer metric (#474) * wip: observers * wip: float observers * fix copy pasta * wip: rework observers in sdk * small fix in global meter * wip: aggregators and selectors * wip: monotonicity option for observers * some refactor * wip: docs needs more package docs (especially for api/metric and sdk/metric) * fix ci * Fix copy-pasta in docs Co-Authored-By: Mauricio Vásquez <mauricio@kinvolk.io> * recycle unused recorders in observers if a recorder for a labelset is unused for a second collection cycle in a row, drop it * unregister * thread-safe set callback * Fix docs * Revert "wip: aggregators and selectors" This reverts commit 37b7d05aed5dc90f6d5593325b6eb77494e21736. * update selector * tests * Rework number equality Compare concrete numbers, so we can get actual numbers in the error message when they are not equal, not some uint64 representation. This also uses InDelta for comparing floats. * Ensure that Observers are registered in the same order * Run observers in fixed order So the tests can be reproducible - iterating a map made the order of measurements random. * Ensure the proper alignment of the delegates This wasn't checked at all. After adding the checks, the test-386 failed. * Small tweaks to the global meter test * Ensure proper alignment of the callback pointer test-386 was complaining about it * update docs * update a TODO * address review issues * drop SetCallback Co-authored-by: Mauricio Vásquez <mauricio@kinvolk.io> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-05 12:15:30 -08:00
func (u unitOption) Apply(config *Config) {
config.Unit = unit.Unit(u)
}
// WithKeys applies recommended label keys. Multiple `WithKeys`
// options accumulate.
func WithKeys(keys ...core.Key) Option {
return keysOption(keys)
}
type keysOption []core.Key
func (k keysOption) Apply(config *Config) {
config.Keys = append(config.Keys, k...)
}
Add support for Resources in the SDK (#552) * Add support for Resources in the SDK Add `Config` types for the push `Controller` and the `SDK`. Included with this are helper functions to configure the `ErrorHandler` and `Resource`. Add a `Resource` to the Meter `Descriptor`. The choice to add the `Resource` here (instead of say a `Record` or the `Instrument` itself) was motivated by the definition of the `Descriptor` as the way to uniquely describe a metric instrument. Update the push `Controller` and default `SDK` to pass down their configured `Resource` from instantiation to the metric instruments. * Update New SDK constructor documentation * Change NewDescriptor constructor to take opts Add DescriptorConfig and DescriptorOption to configure the metric Descriptor with the description, unit, keys, and resource. Update all function calls to NewDescriptor to use new function signature. * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> * Update and add copyright notices * Update push controller creator func Pass the configured ErrorHandler for the controller to the SDK. * Update Resource integration with the SDK Add back the Resource field to the Descriptor that was moved in the last merge with master. Add a resource.Provider interface. Have the default SDK implement the new resource.Provider interface and integrate the new interface into the newSync/newAsync workflows. Now, if the SDK has a Resource defined it will be passed to all Descriptors created for the instruments it creates. * Remove nil check for metric SDK config * Fix and add test for API Options Add an `Equal` method to the Resource so it can be compared with github.com/google/go-cmp/cmp. Add additional test of the API Option unit tests to ensure WithResource correctly sets a new resource. * Move the resource.Provider interface to the API package Move the interface to where it is used. Fix spelling. * Remove errant line * Remove nil checks for the push controller config * Fix check SDK implements Resourcer * Apply suggestions from code review Co-Authored-By: Rahul Patel <rghetia@yahoo.com> Co-authored-by: Rahul Patel <rghetia@yahoo.com>
2020-03-20 08:58:32 -07:00
// WithResource applies provided Resource.
//
// This will override any existing Resource.
func WithResource(r resource.Resource) Option {
return resourceOption(r)
}
type resourceOption resource.Resource
func (r resourceOption) Apply(config *Config) {
config.Resource = resource.Resource(r)
}
// WithLibraryName applies provided library name. This is meant for
// use in `Provider` implementations that have not used
// `WrapMeterImpl`. Implementations built using `WrapMeterImpl` have
// instrument descriptors taken care of through this package.
//
// This option will have no effect when supplied by the user.
// Provider implementations are expected to append this option after
// the user-supplied options when building instrument descriptors.
func WithLibraryName(name string) Option {
return libraryNameOption(name)
}
type libraryNameOption string
func (r libraryNameOption) Apply(config *Config) {
config.LibraryName = string(r)
}