mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-01-26 03:52:03 +02:00
Add options to measurement methods (#3971)
* Add options to measurement methods * Update noop * Update global impl * Update SDK impl * Fix metric API example * Update prometheus exporter tests * Update examples * WithAttributes and WithAttributeSet * Add changes to changelog * Accept slice instead of variadic to new conf funcs * Clarify WithAttributes performance in docs * Address feedback about WithAttributes comment * Add changelog entry for WithAttribute{s,Set} * Remove number scope from measure opts * Update changelog * Remove left-over test cases --------- Co-authored-by: Robert Pająk <pellared@hotmail.com>
This commit is contained in:
parent
d1959c9239
commit
f8fcfda872
24
CHANGELOG.md
24
CHANGELOG.md
@ -13,6 +13,18 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
- The `go.opentelemetry.io/otel/metric/embedded` package. (#3916)
|
||||
- The `Version` function to `go.opentelemetry.io/otel/sdk` to return the SDK version. (#3949)
|
||||
- Add a `WithNamespace` option to `go.opentelemetry.io/otel/exporters/prometheus` to allow users to prefix metrics with a namespace. (#3970)
|
||||
- The following configuration types were added to `go.opentelemetry.io/otel/metric/instrument` to be used in the configuration of measurement methods. (#3971)
|
||||
- The `AddConfig` used to hold configuration for addition measurements
|
||||
- `NewAddConfig` used to create a new `AddConfig`
|
||||
- `AddOption` used to configure an `AddConfig`
|
||||
- The `RecordConfig` used to hold configuration for recorded measurements
|
||||
- `NewRecordConfig` used to create a new `RecordConfig`
|
||||
- `RecordOption` used to configure a `RecordConfig`
|
||||
- The `ObserveConfig` used to hold configuration for observed measurements
|
||||
- `NewObserveConfig` used to create a new `ObserveConfig`
|
||||
- `ObserveOption` used to configure an `ObserveConfig`
|
||||
- `WithAttributeSet` and `WithAttributes` are added to `go.opentelemetry.io/otel/metric/instrument`.
|
||||
They return an option used during a measurement that defines the attribute Set associated with the measurement. (#3971)
|
||||
- The `Version` function to `go.opentelemetry.io/otel/exporters/otlp/otlpmetric` to return the OTLP metrics client version. (#3956)
|
||||
- The `Version` function to `go.opentelemetry.io/otel/exporters/otlp/otlptrace` to return the OTLP trace client version. (#3956)
|
||||
|
||||
@ -24,6 +36,18 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
- Move No-Op implementation from `go.opentelemetry.io/otel/metric` into its own package `go.opentelemetry.io/otel/metric/noop`. (#3941)
|
||||
- `metric.NewNoopMeterProvider` is replaced with `noop.NewMeterProvider`
|
||||
- Wrap `UploadMetrics` error in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/` to improve error message when encountering generic grpc errors. (#3974)
|
||||
- The measurement methods for all instruments in `go.opentelemetry.io/otel/metric/instrument` accept an option instead of the variadic `"go.opentelemetry.io/otel/attribute".KeyValue`. (#3971)
|
||||
- The `Int64Counter.Add` method now accepts `...AddOption`
|
||||
- The `Float64Counter.Add` method now accepts `...AddOption`
|
||||
- The `Int64UpDownCounter.Add` method now accepts `...AddOption`
|
||||
- The `Float64UpDownCounter.Add` method now accepts `...AddOption`
|
||||
- The `Int64Histogram.Record` method now accepts `...RecordOption`
|
||||
- The `Float64Histogram.Record` method now accepts `...RecordOption`
|
||||
- The `Int64Observer.Observe` method now accepts `...ObserveOption`
|
||||
- The `Float64Observer.Observe` method now accepts `...ObserveOption`
|
||||
- The `Observer` methods in `go.opentelemetry.io/otel/metric` accept an option instead of the variadic `"go.opentelemetry.io/otel/attribute".KeyValue`. (#3971)
|
||||
- The `Observer.ObserveInt64` method now accepts `...ObserveOption`
|
||||
- The `Observer.ObserveFloat64` method now accepts `...ObserveOption`
|
||||
- Move global metric back to `go.opentelemetry.io/otel/metric/global` from `go.opentelemetry.io/otel`. (#3986)
|
||||
|
||||
### Fixed
|
||||
|
@ -50,17 +50,17 @@ func main() {
|
||||
// Start the prometheus HTTP server and pass the exporter Collector to it
|
||||
go serveMetrics()
|
||||
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
}
|
||||
)
|
||||
|
||||
// This is the equivalent of prometheus.NewCounterVec
|
||||
counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
counter.Add(ctx, 5, attrs...)
|
||||
counter.Add(ctx, 5, opt)
|
||||
|
||||
gauge, err := meter.Float64ObservableGauge("bar", instrument.WithDescription("a fun little gauge"))
|
||||
if err != nil {
|
||||
@ -68,7 +68,7 @@ func main() {
|
||||
}
|
||||
_, err = meter.RegisterCallback(func(_ context.Context, o api.Observer) error {
|
||||
n := -10. + rng.Float64()*(90.) // [-10, 100)
|
||||
o.ObserveFloat64(gauge, n, attrs...)
|
||||
o.ObserveFloat64(gauge, n, opt)
|
||||
return nil
|
||||
}, gauge)
|
||||
if err != nil {
|
||||
@ -80,10 +80,10 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
histogram.Record(ctx, 23, attrs...)
|
||||
histogram.Record(ctx, 7, attrs...)
|
||||
histogram.Record(ctx, 101, attrs...)
|
||||
histogram.Record(ctx, 105, attrs...)
|
||||
histogram.Record(ctx, 23, opt)
|
||||
histogram.Record(ctx, 7, opt)
|
||||
histogram.Record(ctx, 101, opt)
|
||||
histogram.Record(ctx, 105, opt)
|
||||
|
||||
ctx, _ = signal.NotifyContext(ctx, os.Interrupt)
|
||||
<-ctx.Done()
|
||||
|
@ -64,25 +64,25 @@ func main() {
|
||||
// Start the prometheus HTTP server and pass the exporter Collector to it
|
||||
go serveMetrics()
|
||||
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
}
|
||||
)
|
||||
|
||||
counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
counter.Add(ctx, 5, attrs...)
|
||||
counter.Add(ctx, 5, opt)
|
||||
|
||||
histogram, err := meter.Float64Histogram("custom_histogram", instrument.WithDescription("a histogram with custom buckets and rename"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
histogram.Record(ctx, 136, attrs...)
|
||||
histogram.Record(ctx, 64, attrs...)
|
||||
histogram.Record(ctx, 701, attrs...)
|
||||
histogram.Record(ctx, 830, attrs...)
|
||||
histogram.Record(ctx, 136, opt)
|
||||
histogram.Record(ctx, 64, opt)
|
||||
histogram.Record(ctx, 701, opt)
|
||||
histogram.Record(ctx, 830, opt)
|
||||
|
||||
ctx, _ = signal.NotifyContext(ctx, os.Interrupt)
|
||||
<-ctx.Done()
|
||||
|
@ -46,67 +46,67 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
name: "counter",
|
||||
expectedFile: "testdata/counter.txt",
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
attribute.Key("E").Bool(true),
|
||||
attribute.Key("F").Int(42),
|
||||
}
|
||||
)
|
||||
counter, err := meter.Float64Counter(
|
||||
"foo",
|
||||
instrument.WithDescription("a simple counter"),
|
||||
instrument.WithUnit("ms"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
counter.Add(ctx, 5, attrs...)
|
||||
counter.Add(ctx, 10.3, attrs...)
|
||||
counter.Add(ctx, 9, attrs...)
|
||||
counter.Add(ctx, 5, opt)
|
||||
counter.Add(ctx, 10.3, opt)
|
||||
counter.Add(ctx, 9, opt)
|
||||
|
||||
attrs2 := []attribute.KeyValue{
|
||||
attrs2 := attribute.NewSet(
|
||||
attribute.Key("A").String("D"),
|
||||
attribute.Key("C").String("B"),
|
||||
attribute.Key("E").Bool(true),
|
||||
attribute.Key("F").Int(42),
|
||||
}
|
||||
counter.Add(ctx, 5, attrs2...)
|
||||
)
|
||||
counter.Add(ctx, 5, instrument.WithAttributeSet(attrs2))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gauge",
|
||||
expectedFile: "testdata/gauge.txt",
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
}
|
||||
)
|
||||
gauge, err := meter.Float64UpDownCounter(
|
||||
"bar",
|
||||
instrument.WithDescription("a fun little gauge"),
|
||||
instrument.WithUnit("1"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
gauge.Add(ctx, 1.0, attrs...)
|
||||
gauge.Add(ctx, -.25, attrs...)
|
||||
gauge.Add(ctx, 1.0, opt)
|
||||
gauge.Add(ctx, -.25, opt)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "histogram",
|
||||
expectedFile: "testdata/histogram.txt",
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
}
|
||||
)
|
||||
histogram, err := meter.Float64Histogram(
|
||||
"histogram_baz",
|
||||
instrument.WithDescription("a very nice histogram"),
|
||||
instrument.WithUnit("By"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
histogram.Record(ctx, 23, attrs...)
|
||||
histogram.Record(ctx, 7, attrs...)
|
||||
histogram.Record(ctx, 101, attrs...)
|
||||
histogram.Record(ctx, 105, attrs...)
|
||||
histogram.Record(ctx, 23, opt)
|
||||
histogram.Record(ctx, 7, opt)
|
||||
histogram.Record(ctx, 101, opt)
|
||||
histogram.Record(ctx, 105, opt)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -114,7 +114,7 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
expectedFile: "testdata/sanitized_labels.txt",
|
||||
options: []Option{WithoutUnits()},
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
// exact match, value should be overwritten
|
||||
attribute.Key("A.B").String("X"),
|
||||
attribute.Key("A.B").String("Q"),
|
||||
@ -122,7 +122,7 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
// unintended match due to sanitization, values should be concatenated
|
||||
attribute.Key("C.D").String("Y"),
|
||||
attribute.Key("C/D").String("Z"),
|
||||
}
|
||||
)
|
||||
counter, err := meter.Float64Counter(
|
||||
"foo",
|
||||
instrument.WithDescription("a sanitary counter"),
|
||||
@ -130,37 +130,37 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
counter.Add(ctx, 5, attrs...)
|
||||
counter.Add(ctx, 10.3, attrs...)
|
||||
counter.Add(ctx, 9, attrs...)
|
||||
counter.Add(ctx, 5, opt)
|
||||
counter.Add(ctx, 10.3, opt)
|
||||
counter.Add(ctx, 9, opt)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid instruments are renamed",
|
||||
expectedFile: "testdata/sanitized_names.txt",
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
}
|
||||
)
|
||||
// Valid.
|
||||
gauge, err := meter.Float64UpDownCounter("bar", instrument.WithDescription("a fun little gauge"))
|
||||
require.NoError(t, err)
|
||||
gauge.Add(ctx, 100, attrs...)
|
||||
gauge.Add(ctx, -25, attrs...)
|
||||
gauge.Add(ctx, 100, opt)
|
||||
gauge.Add(ctx, -25, opt)
|
||||
|
||||
// Invalid, will be renamed.
|
||||
gauge, err = meter.Float64UpDownCounter("invalid.gauge.name", instrument.WithDescription("a gauge with an invalid name"))
|
||||
require.NoError(t, err)
|
||||
gauge.Add(ctx, 100, attrs...)
|
||||
gauge.Add(ctx, 100, opt)
|
||||
|
||||
counter, err := meter.Float64Counter("0invalid.counter.name", instrument.WithDescription("a counter with an invalid name"))
|
||||
require.NoError(t, err)
|
||||
counter.Add(ctx, 100, attrs...)
|
||||
counter.Add(ctx, 100, opt)
|
||||
|
||||
histogram, err := meter.Float64Histogram("invalid.hist.name", instrument.WithDescription("a histogram with an invalid name"))
|
||||
require.NoError(t, err)
|
||||
histogram.Record(ctx, 23, attrs...)
|
||||
histogram.Record(ctx, 23, opt)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -168,17 +168,17 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
emptyResource: true,
|
||||
expectedFile: "testdata/empty_resource.txt",
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
attribute.Key("E").Bool(true),
|
||||
attribute.Key("F").Int(42),
|
||||
}
|
||||
)
|
||||
counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter"))
|
||||
require.NoError(t, err)
|
||||
counter.Add(ctx, 5, attrs...)
|
||||
counter.Add(ctx, 10.3, attrs...)
|
||||
counter.Add(ctx, 9, attrs...)
|
||||
counter.Add(ctx, 5, opt)
|
||||
counter.Add(ctx, 10.3, opt)
|
||||
counter.Add(ctx, 9, opt)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -189,17 +189,17 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
},
|
||||
expectedFile: "testdata/custom_resource.txt",
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
attribute.Key("E").Bool(true),
|
||||
attribute.Key("F").Int(42),
|
||||
}
|
||||
)
|
||||
counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter"))
|
||||
require.NoError(t, err)
|
||||
counter.Add(ctx, 5, attrs...)
|
||||
counter.Add(ctx, 10.3, attrs...)
|
||||
counter.Add(ctx, 9, attrs...)
|
||||
counter.Add(ctx, 5, opt)
|
||||
counter.Add(ctx, 10.3, opt)
|
||||
counter.Add(ctx, 9, opt)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -207,17 +207,17 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
options: []Option{WithoutTargetInfo()},
|
||||
expectedFile: "testdata/without_target_info.txt",
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
attribute.Key("E").Bool(true),
|
||||
attribute.Key("F").Int(42),
|
||||
}
|
||||
)
|
||||
counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter"))
|
||||
require.NoError(t, err)
|
||||
counter.Add(ctx, 5, attrs...)
|
||||
counter.Add(ctx, 10.3, attrs...)
|
||||
counter.Add(ctx, 9, attrs...)
|
||||
counter.Add(ctx, 5, opt)
|
||||
counter.Add(ctx, 10.3, opt)
|
||||
counter.Add(ctx, 9, opt)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -225,18 +225,18 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
options: []Option{WithoutScopeInfo()},
|
||||
expectedFile: "testdata/without_scope_info.txt",
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
}
|
||||
)
|
||||
gauge, err := meter.Int64UpDownCounter(
|
||||
"bar",
|
||||
instrument.WithDescription("a fun little gauge"),
|
||||
instrument.WithUnit("1"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
gauge.Add(ctx, 2, attrs...)
|
||||
gauge.Add(ctx, -1, attrs...)
|
||||
gauge.Add(ctx, 2, opt)
|
||||
gauge.Add(ctx, -1, opt)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -244,18 +244,18 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
options: []Option{WithoutScopeInfo(), WithoutTargetInfo()},
|
||||
expectedFile: "testdata/without_scope_and_target_info.txt",
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
}
|
||||
)
|
||||
counter, err := meter.Int64Counter(
|
||||
"bar",
|
||||
instrument.WithDescription("a fun little counter"),
|
||||
instrument.WithUnit("By"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
counter.Add(ctx, 2, attrs...)
|
||||
counter.Add(ctx, 1, attrs...)
|
||||
counter.Add(ctx, 2, opt)
|
||||
counter.Add(ctx, 1, opt)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -265,17 +265,17 @@ func TestPrometheusExporter(t *testing.T) {
|
||||
WithNamespace("test"),
|
||||
},
|
||||
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||
attrs := []attribute.KeyValue{
|
||||
opt := instrument.WithAttributes(
|
||||
attribute.Key("A").String("B"),
|
||||
attribute.Key("C").String("D"),
|
||||
attribute.Key("E").Bool(true),
|
||||
attribute.Key("F").Int(42),
|
||||
}
|
||||
)
|
||||
counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter"))
|
||||
require.NoError(t, err)
|
||||
counter.Add(ctx, 5, attrs...)
|
||||
counter.Add(ctx, 10.3, attrs...)
|
||||
counter.Add(ctx, 9, attrs...)
|
||||
counter.Add(ctx, 5, opt)
|
||||
counter.Add(ctx, 10.3, opt)
|
||||
counter.Add(ctx, 9, opt)
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -388,7 +388,7 @@ func TestMultiScopes(t *testing.T) {
|
||||
instrument.WithUnit("ms"),
|
||||
instrument.WithDescription("meter foo counter"))
|
||||
assert.NoError(t, err)
|
||||
fooCounter.Add(ctx, 100, attribute.String("type", "foo"))
|
||||
fooCounter.Add(ctx, 100, instrument.WithAttributes(attribute.String("type", "foo")))
|
||||
|
||||
barCounter, err := provider.Meter("meterbar", otelmetric.WithInstrumentationVersion("v0.1.0")).
|
||||
Int64Counter(
|
||||
@ -396,7 +396,7 @@ func TestMultiScopes(t *testing.T) {
|
||||
instrument.WithUnit("ms"),
|
||||
instrument.WithDescription("meter bar counter"))
|
||||
assert.NoError(t, err)
|
||||
barCounter.Add(ctx, 200, attribute.String("type", "bar"))
|
||||
barCounter.Add(ctx, 200, instrument.WithAttributes(attribute.String("type", "bar")))
|
||||
|
||||
file, err := os.Open("testdata/multi_scopes.txt")
|
||||
require.NoError(t, err)
|
||||
@ -407,6 +407,12 @@ func TestMultiScopes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDuplicateMetrics(t *testing.T) {
|
||||
ab := attribute.NewSet(attribute.String("A", "B"))
|
||||
withAB := instrument.WithAttributeSet(ab)
|
||||
typeBar := attribute.NewSet(attribute.String("type", "bar"))
|
||||
withTypeBar := instrument.WithAttributeSet(typeBar)
|
||||
typeFoo := attribute.NewSet(attribute.String("type", "foo"))
|
||||
withTypeFoo := instrument.WithAttributeSet(typeFoo)
|
||||
testCases := []struct {
|
||||
name string
|
||||
customResouceAttrs []attribute.KeyValue
|
||||
@ -421,13 +427,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter counter foo"))
|
||||
assert.NoError(t, err)
|
||||
fooA.Add(ctx, 100, attribute.String("A", "B"))
|
||||
fooA.Add(ctx, 100, withAB)
|
||||
|
||||
fooB, err := meterB.Int64Counter("foo",
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter counter foo"))
|
||||
assert.NoError(t, err)
|
||||
fooB.Add(ctx, 100, attribute.String("A", "B"))
|
||||
fooB.Add(ctx, 100, withAB)
|
||||
},
|
||||
possibleExpectedFiles: []string{"testdata/no_conflict_two_counters.txt"},
|
||||
},
|
||||
@ -438,13 +444,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter gauge foo"))
|
||||
assert.NoError(t, err)
|
||||
fooA.Add(ctx, 100, attribute.String("A", "B"))
|
||||
fooA.Add(ctx, 100, withAB)
|
||||
|
||||
fooB, err := meterB.Int64UpDownCounter("foo",
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter gauge foo"))
|
||||
assert.NoError(t, err)
|
||||
fooB.Add(ctx, 100, attribute.String("A", "B"))
|
||||
fooB.Add(ctx, 100, withAB)
|
||||
},
|
||||
possibleExpectedFiles: []string{"testdata/no_conflict_two_updowncounters.txt"},
|
||||
},
|
||||
@ -455,13 +461,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter histogram foo"))
|
||||
assert.NoError(t, err)
|
||||
fooA.Record(ctx, 100, attribute.String("A", "B"))
|
||||
fooA.Record(ctx, 100, withAB)
|
||||
|
||||
fooB, err := meterB.Int64Histogram("foo",
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter histogram foo"))
|
||||
assert.NoError(t, err)
|
||||
fooB.Record(ctx, 100, attribute.String("A", "B"))
|
||||
fooB.Record(ctx, 100, withAB)
|
||||
},
|
||||
possibleExpectedFiles: []string{"testdata/no_conflict_two_histograms.txt"},
|
||||
},
|
||||
@ -472,13 +478,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter a bar"))
|
||||
assert.NoError(t, err)
|
||||
barA.Add(ctx, 100, attribute.String("type", "bar"))
|
||||
barA.Add(ctx, 100, withTypeBar)
|
||||
|
||||
barB, err := meterB.Int64Counter("bar",
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter b bar"))
|
||||
assert.NoError(t, err)
|
||||
barB.Add(ctx, 100, attribute.String("type", "bar"))
|
||||
barB.Add(ctx, 100, withTypeBar)
|
||||
},
|
||||
possibleExpectedFiles: []string{
|
||||
"testdata/conflict_help_two_counters_1.txt",
|
||||
@ -492,13 +498,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter a bar"))
|
||||
assert.NoError(t, err)
|
||||
barA.Add(ctx, 100, attribute.String("type", "bar"))
|
||||
barA.Add(ctx, 100, withTypeBar)
|
||||
|
||||
barB, err := meterB.Int64UpDownCounter("bar",
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter b bar"))
|
||||
assert.NoError(t, err)
|
||||
barB.Add(ctx, 100, attribute.String("type", "bar"))
|
||||
barB.Add(ctx, 100, withTypeBar)
|
||||
},
|
||||
possibleExpectedFiles: []string{
|
||||
"testdata/conflict_help_two_updowncounters_1.txt",
|
||||
@ -512,13 +518,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter a bar"))
|
||||
assert.NoError(t, err)
|
||||
barA.Record(ctx, 100, attribute.String("A", "B"))
|
||||
barA.Record(ctx, 100, withAB)
|
||||
|
||||
barB, err := meterB.Int64Histogram("bar",
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter b bar"))
|
||||
assert.NoError(t, err)
|
||||
barB.Record(ctx, 100, attribute.String("A", "B"))
|
||||
barB.Record(ctx, 100, withAB)
|
||||
},
|
||||
possibleExpectedFiles: []string{
|
||||
"testdata/conflict_help_two_histograms_1.txt",
|
||||
@ -532,13 +538,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter bar"))
|
||||
assert.NoError(t, err)
|
||||
bazA.Add(ctx, 100, attribute.String("type", "bar"))
|
||||
bazA.Add(ctx, 100, withTypeBar)
|
||||
|
||||
bazB, err := meterB.Int64Counter("bar",
|
||||
instrument.WithUnit("ms"),
|
||||
instrument.WithDescription("meter bar"))
|
||||
assert.NoError(t, err)
|
||||
bazB.Add(ctx, 100, attribute.String("type", "bar"))
|
||||
bazB.Add(ctx, 100, withTypeBar)
|
||||
},
|
||||
options: []Option{WithoutUnits()},
|
||||
possibleExpectedFiles: []string{"testdata/conflict_unit_two_counters.txt"},
|
||||
@ -550,13 +556,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter gauge bar"))
|
||||
assert.NoError(t, err)
|
||||
barA.Add(ctx, 100, attribute.String("type", "bar"))
|
||||
barA.Add(ctx, 100, withTypeBar)
|
||||
|
||||
barB, err := meterB.Int64UpDownCounter("bar",
|
||||
instrument.WithUnit("ms"),
|
||||
instrument.WithDescription("meter gauge bar"))
|
||||
assert.NoError(t, err)
|
||||
barB.Add(ctx, 100, attribute.String("type", "bar"))
|
||||
barB.Add(ctx, 100, withTypeBar)
|
||||
},
|
||||
options: []Option{WithoutUnits()},
|
||||
possibleExpectedFiles: []string{"testdata/conflict_unit_two_updowncounters.txt"},
|
||||
@ -568,13 +574,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter histogram bar"))
|
||||
assert.NoError(t, err)
|
||||
barA.Record(ctx, 100, attribute.String("A", "B"))
|
||||
barA.Record(ctx, 100, withAB)
|
||||
|
||||
barB, err := meterB.Int64Histogram("bar",
|
||||
instrument.WithUnit("ms"),
|
||||
instrument.WithDescription("meter histogram bar"))
|
||||
assert.NoError(t, err)
|
||||
barB.Record(ctx, 100, attribute.String("A", "B"))
|
||||
barB.Record(ctx, 100, withAB)
|
||||
},
|
||||
options: []Option{WithoutUnits()},
|
||||
possibleExpectedFiles: []string{"testdata/conflict_unit_two_histograms.txt"},
|
||||
@ -586,13 +592,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter foo"))
|
||||
assert.NoError(t, err)
|
||||
counter.Add(ctx, 100, attribute.String("type", "foo"))
|
||||
counter.Add(ctx, 100, withTypeFoo)
|
||||
|
||||
gauge, err := meterA.Int64UpDownCounter("foo_total",
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter foo"))
|
||||
assert.NoError(t, err)
|
||||
gauge.Add(ctx, 200, attribute.String("type", "foo"))
|
||||
gauge.Add(ctx, 200, withTypeFoo)
|
||||
},
|
||||
options: []Option{WithoutUnits()},
|
||||
possibleExpectedFiles: []string{
|
||||
@ -607,13 +613,13 @@ func TestDuplicateMetrics(t *testing.T) {
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter gauge foo"))
|
||||
assert.NoError(t, err)
|
||||
fooA.Add(ctx, 100, attribute.String("A", "B"))
|
||||
fooA.Add(ctx, 100, withAB)
|
||||
|
||||
fooHistogramA, err := meterA.Int64Histogram("foo",
|
||||
instrument.WithUnit("By"),
|
||||
instrument.WithDescription("meter histogram foo"))
|
||||
assert.NoError(t, err)
|
||||
fooHistogramA.Record(ctx, 100, attribute.String("A", "B"))
|
||||
fooHistogramA.Record(ctx, 100, withAB)
|
||||
},
|
||||
possibleExpectedFiles: []string{
|
||||
"testdata/conflict_type_histogram_and_updowncounter_1.txt",
|
||||
|
@ -63,7 +63,7 @@ func ExampleMeter_asynchronous_single() {
|
||||
//
|
||||
// For demonstration purpose, a static value is used here.
|
||||
usage := 75000
|
||||
obsrv.Observe(int64(usage), attribute.Int("disk.id", 3))
|
||||
obsrv.Observe(int64(usage), instrument.WithAttributes(attribute.Int("disk.id", 3)))
|
||||
return nil
|
||||
}),
|
||||
)
|
||||
|
@ -17,7 +17,6 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
)
|
||||
|
||||
@ -207,8 +206,8 @@ type Float64ObservableGaugeOption interface {
|
||||
type Float64Observer interface {
|
||||
embedded.Float64Observer
|
||||
|
||||
// Observe records the float64 value with attributes.
|
||||
Observe(value float64, attributes ...attribute.KeyValue)
|
||||
// Observe records the float64 value.
|
||||
Observe(value float64, opts ...ObserveOption)
|
||||
}
|
||||
|
||||
// Float64Callback is a function registered with a Meter that makes
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
)
|
||||
|
||||
@ -89,6 +88,6 @@ type float64Observer struct {
|
||||
got float64
|
||||
}
|
||||
|
||||
func (o *float64Observer) Observe(v float64, _ ...attribute.KeyValue) {
|
||||
func (o *float64Observer) Observe(v float64, _ ...ObserveOption) {
|
||||
o.got = v
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
)
|
||||
|
||||
@ -206,8 +205,8 @@ type Int64ObservableGaugeOption interface {
|
||||
type Int64Observer interface {
|
||||
embedded.Int64Observer
|
||||
|
||||
// Observe records the int64 value with attributes.
|
||||
Observe(value int64, attributes ...attribute.KeyValue)
|
||||
// Observe records the int64 value.
|
||||
Observe(value int64, opts ...ObserveOption)
|
||||
}
|
||||
|
||||
// Int64Callback is a function registered with a Meter that makes observations
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
)
|
||||
|
||||
@ -89,6 +88,6 @@ type int64Observer struct {
|
||||
got int64
|
||||
}
|
||||
|
||||
func (o *int64Observer) Observe(v int64, _ ...attribute.KeyValue) {
|
||||
func (o *int64Observer) Observe(v int64, _ ...ObserveOption) {
|
||||
o.got = v
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
package instrument // import "go.opentelemetry.io/otel/metric/instrument"
|
||||
|
||||
import "go.opentelemetry.io/otel/attribute"
|
||||
|
||||
// Observable is used as a grouping mechanism for all instruments that are
|
||||
// updated within a Callback.
|
||||
type Observable interface {
|
||||
@ -166,3 +168,165 @@ func (o unitOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64Ob
|
||||
|
||||
// WithUnit sets the instrument unit.
|
||||
func WithUnit(u string) Option { return unitOpt(u) }
|
||||
|
||||
// AddOption applies options to an addition measurement. See
|
||||
// [MeasurementOption] for other options that can be used as a AddOption.
|
||||
type AddOption interface {
|
||||
applyAdd(AddConfig) AddConfig
|
||||
}
|
||||
|
||||
// AddConfig contains options for an addition measurement.
|
||||
type AddConfig struct {
|
||||
attrs attribute.Set
|
||||
}
|
||||
|
||||
// NewAddConfig returns a new [AddConfig] with all opts applied.
|
||||
func NewAddConfig(opts []AddOption) AddConfig {
|
||||
config := AddConfig{attrs: *attribute.EmptySet()}
|
||||
for _, o := range opts {
|
||||
config = o.applyAdd(config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// Attributes returns the configured attribute set.
|
||||
func (c AddConfig) Attributes() attribute.Set {
|
||||
return c.attrs
|
||||
}
|
||||
|
||||
// RecordOption applies options to an addition measurement. See
|
||||
// [MeasurementOption] for other options that can be used as a RecordOption.
|
||||
type RecordOption interface {
|
||||
applyRecord(RecordConfig) RecordConfig
|
||||
}
|
||||
|
||||
// RecordConfig contains options for a recorded measurement.
|
||||
type RecordConfig struct {
|
||||
attrs attribute.Set
|
||||
}
|
||||
|
||||
// NewRecordConfig returns a new [RecordConfig] with all opts applied.
|
||||
func NewRecordConfig(opts []RecordOption) RecordConfig {
|
||||
config := RecordConfig{attrs: *attribute.EmptySet()}
|
||||
for _, o := range opts {
|
||||
config = o.applyRecord(config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// Attributes returns the configured attribute set.
|
||||
func (c RecordConfig) Attributes() attribute.Set {
|
||||
return c.attrs
|
||||
}
|
||||
|
||||
// ObserveOption applies options to an addition measurement. See
|
||||
// [MeasurementOption] for other options that can be used as a ObserveOption.
|
||||
type ObserveOption interface {
|
||||
applyObserve(ObserveConfig) ObserveConfig
|
||||
}
|
||||
|
||||
// ObserveConfig contains options for an observed measurement.
|
||||
type ObserveConfig struct {
|
||||
attrs attribute.Set
|
||||
}
|
||||
|
||||
// NewObserveConfig returns a new [ObserveConfig] with all opts applied.
|
||||
func NewObserveConfig(opts []ObserveOption) ObserveConfig {
|
||||
config := ObserveConfig{attrs: *attribute.EmptySet()}
|
||||
for _, o := range opts {
|
||||
config = o.applyObserve(config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// Attributes returns the configured attribute set.
|
||||
func (c ObserveConfig) Attributes() attribute.Set {
|
||||
return c.attrs
|
||||
}
|
||||
|
||||
// MeasurementOption applies options to all instrument measurement.
|
||||
type MeasurementOption interface {
|
||||
AddOption
|
||||
RecordOption
|
||||
ObserveOption
|
||||
}
|
||||
|
||||
type attrOpt struct {
|
||||
set attribute.Set
|
||||
}
|
||||
|
||||
// mergeSets returns the union of keys between a and b. Any duplicate keys will
|
||||
// use the value associated with b.
|
||||
func mergeSets(a, b attribute.Set) attribute.Set {
|
||||
// NewMergeIterator uses the first value for any duplicates.
|
||||
iter := attribute.NewMergeIterator(&b, &a)
|
||||
merged := make([]attribute.KeyValue, 0, a.Len()+b.Len())
|
||||
for iter.Next() {
|
||||
merged = append(merged, iter.Attribute())
|
||||
}
|
||||
return attribute.NewSet(merged...)
|
||||
}
|
||||
|
||||
func (o attrOpt) applyAdd(c AddConfig) AddConfig {
|
||||
switch {
|
||||
case o.set.Len() == 0:
|
||||
case c.attrs.Len() == 0:
|
||||
c.attrs = o.set
|
||||
default:
|
||||
c.attrs = mergeSets(c.attrs, o.set)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (o attrOpt) applyRecord(c RecordConfig) RecordConfig {
|
||||
switch {
|
||||
case o.set.Len() == 0:
|
||||
case c.attrs.Len() == 0:
|
||||
c.attrs = o.set
|
||||
default:
|
||||
c.attrs = mergeSets(c.attrs, o.set)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (o attrOpt) applyObserve(c ObserveConfig) ObserveConfig {
|
||||
switch {
|
||||
case o.set.Len() == 0:
|
||||
case c.attrs.Len() == 0:
|
||||
c.attrs = o.set
|
||||
default:
|
||||
c.attrs = mergeSets(c.attrs, o.set)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// WithAttributeSet sets the attribute Set associated with a measurement is
|
||||
// made with.
|
||||
//
|
||||
// If multiple WithAttributeSet or WithAttributes options are passed the
|
||||
// attributes will be merged together in the order they are passed. Attributes
|
||||
// with duplicate keys will use the last value passed.
|
||||
func WithAttributeSet(attributes attribute.Set) MeasurementOption {
|
||||
return attrOpt{set: attributes}
|
||||
}
|
||||
|
||||
// WithAttributes converts attributes into an attribute Set and sets the Set to
|
||||
// be associated with a measurement. This is shorthand for:
|
||||
//
|
||||
// cp := make([]attribute.KeyValue, len(attributes))
|
||||
// copy(cp, attributes)
|
||||
// WithAttributes(attribute.NewSet(cp...))
|
||||
//
|
||||
// [attribute.NewSet] may modify the passed attributes so this will make a copy
|
||||
// of attributes before creating a set in order to ensure this function is
|
||||
// concurrent safe. This makes this option function less optimized in
|
||||
// comparison to [WithAttributeSet]. Therefore, [WithAttributeSet] should be
|
||||
// preferred for performance sensitive code.
|
||||
//
|
||||
// See [WithAttributeSet] for information about how multiple WithAttributes are
|
||||
// merged.
|
||||
func WithAttributes(attributes ...attribute.KeyValue) MeasurementOption {
|
||||
cp := make([]attribute.KeyValue, len(attributes))
|
||||
copy(cp, attributes)
|
||||
return attrOpt{set: attribute.NewSet(cp...)}
|
||||
}
|
||||
|
152
metric/instrument/instrument_test.go
Normal file
152
metric/instrument/instrument_test.go
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright The 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 instrument // import "go.opentelemetry.io/otel/metric/instrument"
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
type attrConf interface {
|
||||
Attributes() attribute.Set
|
||||
}
|
||||
|
||||
func TestConfigAttrs(t *testing.T) {
|
||||
t.Run("AddConfig", testConfAttr(func(mo ...MeasurementOption) attrConf {
|
||||
opts := make([]AddOption, len(mo))
|
||||
for i := range mo {
|
||||
opts[i] = mo[i].(AddOption)
|
||||
}
|
||||
return NewAddConfig(opts)
|
||||
}))
|
||||
|
||||
t.Run("RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf {
|
||||
opts := make([]RecordOption, len(mo))
|
||||
for i := range mo {
|
||||
opts[i] = mo[i].(RecordOption)
|
||||
}
|
||||
return NewRecordConfig(opts)
|
||||
}))
|
||||
|
||||
t.Run("ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf {
|
||||
opts := make([]ObserveOption, len(mo))
|
||||
for i := range mo {
|
||||
opts[i] = mo[i].(ObserveOption)
|
||||
}
|
||||
return NewObserveConfig(opts)
|
||||
}))
|
||||
}
|
||||
|
||||
func testConfAttr(newConf func(...MeasurementOption) attrConf) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Run("ZeroConfigEmpty", func(t *testing.T) {
|
||||
c := newConf()
|
||||
assert.Equal(t, *attribute.EmptySet(), c.Attributes())
|
||||
})
|
||||
|
||||
t.Run("EmptySet", func(t *testing.T) {
|
||||
c := newConf(WithAttributeSet(*attribute.EmptySet()))
|
||||
assert.Equal(t, *attribute.EmptySet(), c.Attributes())
|
||||
})
|
||||
|
||||
aliceAttr := attribute.String("user", "Alice")
|
||||
alice := attribute.NewSet(aliceAttr)
|
||||
t.Run("SingleWithAttributeSet", func(t *testing.T) {
|
||||
c := newConf(WithAttributeSet(alice))
|
||||
assert.Equal(t, alice, c.Attributes())
|
||||
})
|
||||
|
||||
t.Run("SingleWithAttributes", func(t *testing.T) {
|
||||
c := newConf(WithAttributes(aliceAttr))
|
||||
assert.Equal(t, alice, c.Attributes())
|
||||
})
|
||||
|
||||
bobAttr := attribute.String("user", "Bob")
|
||||
bob := attribute.NewSet(bobAttr)
|
||||
t.Run("MultiWithAttributeSet", func(t *testing.T) {
|
||||
c := newConf(WithAttributeSet(alice), WithAttributeSet(bob))
|
||||
assert.Equal(t, bob, c.Attributes())
|
||||
})
|
||||
|
||||
t.Run("MergedWithAttributes", func(t *testing.T) {
|
||||
c := newConf(WithAttributes(aliceAttr, bobAttr))
|
||||
assert.Equal(t, bob, c.Attributes())
|
||||
})
|
||||
|
||||
t.Run("MultiWithAttributeSet", func(t *testing.T) {
|
||||
c := newConf(WithAttributes(aliceAttr), WithAttributes(bobAttr))
|
||||
assert.Equal(t, bob, c.Attributes())
|
||||
})
|
||||
|
||||
t.Run("MergedEmpty", func(t *testing.T) {
|
||||
c := newConf(WithAttributeSet(alice), WithAttributeSet(*attribute.EmptySet()))
|
||||
assert.Equal(t, alice, c.Attributes())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithAttributesRace(t *testing.T) {
|
||||
attrs := []attribute.KeyValue{
|
||||
attribute.String("user", "Alice"),
|
||||
attribute.Bool("admin", true),
|
||||
attribute.String("user", "Bob"),
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
opt := []AddOption{WithAttributes(attrs...)}
|
||||
_ = NewAddConfig(opt)
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
opt := []AddOption{WithAttributes(attrs...)}
|
||||
_ = NewAddConfig(opt)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
opt := []RecordOption{WithAttributes(attrs...)}
|
||||
_ = NewRecordConfig(opt)
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
opt := []RecordOption{WithAttributes(attrs...)}
|
||||
_ = NewRecordConfig(opt)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
opt := []ObserveOption{WithAttributes(attrs...)}
|
||||
_ = NewObserveConfig(opt)
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
opt := []ObserveOption{WithAttributes(attrs...)}
|
||||
_ = NewObserveConfig(opt)
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
@ -17,7 +17,6 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
)
|
||||
|
||||
@ -31,7 +30,7 @@ type Float64Counter interface {
|
||||
embedded.Float64Counter
|
||||
|
||||
// Add records a change to the counter.
|
||||
Add(ctx context.Context, incr float64, attrs ...attribute.KeyValue)
|
||||
Add(ctx context.Context, incr float64, opts ...AddOption)
|
||||
}
|
||||
|
||||
// Float64CounterConfig contains options for synchronous counter instruments that
|
||||
@ -78,7 +77,7 @@ type Float64UpDownCounter interface {
|
||||
embedded.Float64UpDownCounter
|
||||
|
||||
// Add records a change to the counter.
|
||||
Add(ctx context.Context, incr float64, attrs ...attribute.KeyValue)
|
||||
Add(ctx context.Context, incr float64, opts ...AddOption)
|
||||
}
|
||||
|
||||
// Float64UpDownCounterConfig contains options for synchronous counter
|
||||
@ -126,7 +125,7 @@ type Float64Histogram interface {
|
||||
embedded.Float64Histogram
|
||||
|
||||
// Record adds an additional value to the distribution.
|
||||
Record(ctx context.Context, incr float64, attrs ...attribute.KeyValue)
|
||||
Record(ctx context.Context, incr float64, opts ...RecordOption)
|
||||
}
|
||||
|
||||
// Float64HistogramConfig contains options for synchronous counter instruments
|
||||
|
@ -17,7 +17,6 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
)
|
||||
|
||||
@ -31,7 +30,7 @@ type Int64Counter interface {
|
||||
embedded.Int64Counter
|
||||
|
||||
// Add records a change to the counter.
|
||||
Add(ctx context.Context, incr int64, attrs ...attribute.KeyValue)
|
||||
Add(ctx context.Context, incr int64, opts ...AddOption)
|
||||
}
|
||||
|
||||
// Int64CounterConfig contains options for synchronous counter instruments that
|
||||
@ -78,7 +77,7 @@ type Int64UpDownCounter interface {
|
||||
embedded.Int64UpDownCounter
|
||||
|
||||
// Add records a change to the counter.
|
||||
Add(ctx context.Context, incr int64, attrs ...attribute.KeyValue)
|
||||
Add(ctx context.Context, incr int64, opts ...AddOption)
|
||||
}
|
||||
|
||||
// Int64UpDownCounterConfig contains options for synchronous counter
|
||||
@ -126,7 +125,7 @@ type Int64Histogram interface {
|
||||
embedded.Int64Histogram
|
||||
|
||||
// Record adds an additional value to the distribution.
|
||||
Record(ctx context.Context, incr int64, attrs ...attribute.KeyValue)
|
||||
Record(ctx context.Context, incr int64, opts ...RecordOption)
|
||||
}
|
||||
|
||||
// Int64HistogramConfig contains options for synchronous counter instruments
|
||||
|
@ -19,7 +19,6 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
"go.opentelemetry.io/otel/metric/instrument"
|
||||
@ -225,9 +224,9 @@ func (i *sfCounter) setDelegate(m metric.Meter) {
|
||||
i.delegate.Store(ctr)
|
||||
}
|
||||
|
||||
func (i *sfCounter) Add(ctx context.Context, incr float64, attrs ...attribute.KeyValue) {
|
||||
func (i *sfCounter) Add(ctx context.Context, incr float64, opts ...instrument.AddOption) {
|
||||
if ctr := i.delegate.Load(); ctr != nil {
|
||||
ctr.(instrument.Float64Counter).Add(ctx, incr, attrs...)
|
||||
ctr.(instrument.Float64Counter).Add(ctx, incr, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,9 +250,9 @@ func (i *sfUpDownCounter) setDelegate(m metric.Meter) {
|
||||
i.delegate.Store(ctr)
|
||||
}
|
||||
|
||||
func (i *sfUpDownCounter) Add(ctx context.Context, incr float64, attrs ...attribute.KeyValue) {
|
||||
func (i *sfUpDownCounter) Add(ctx context.Context, incr float64, opts ...instrument.AddOption) {
|
||||
if ctr := i.delegate.Load(); ctr != nil {
|
||||
ctr.(instrument.Float64UpDownCounter).Add(ctx, incr, attrs...)
|
||||
ctr.(instrument.Float64UpDownCounter).Add(ctx, incr, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,9 +276,9 @@ func (i *sfHistogram) setDelegate(m metric.Meter) {
|
||||
i.delegate.Store(ctr)
|
||||
}
|
||||
|
||||
func (i *sfHistogram) Record(ctx context.Context, x float64, attrs ...attribute.KeyValue) {
|
||||
func (i *sfHistogram) Record(ctx context.Context, x float64, opts ...instrument.RecordOption) {
|
||||
if ctr := i.delegate.Load(); ctr != nil {
|
||||
ctr.(instrument.Float64Histogram).Record(ctx, x, attrs...)
|
||||
ctr.(instrument.Float64Histogram).Record(ctx, x, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,9 +302,9 @@ func (i *siCounter) setDelegate(m metric.Meter) {
|
||||
i.delegate.Store(ctr)
|
||||
}
|
||||
|
||||
func (i *siCounter) Add(ctx context.Context, x int64, attrs ...attribute.KeyValue) {
|
||||
func (i *siCounter) Add(ctx context.Context, x int64, opts ...instrument.AddOption) {
|
||||
if ctr := i.delegate.Load(); ctr != nil {
|
||||
ctr.(instrument.Int64Counter).Add(ctx, x, attrs...)
|
||||
ctr.(instrument.Int64Counter).Add(ctx, x, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,9 +328,9 @@ func (i *siUpDownCounter) setDelegate(m metric.Meter) {
|
||||
i.delegate.Store(ctr)
|
||||
}
|
||||
|
||||
func (i *siUpDownCounter) Add(ctx context.Context, x int64, attrs ...attribute.KeyValue) {
|
||||
func (i *siUpDownCounter) Add(ctx context.Context, x int64, opts ...instrument.AddOption) {
|
||||
if ctr := i.delegate.Load(); ctr != nil {
|
||||
ctr.(instrument.Int64UpDownCounter).Add(ctx, x, attrs...)
|
||||
ctr.(instrument.Int64UpDownCounter).Add(ctx, x, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,8 +354,8 @@ func (i *siHistogram) setDelegate(m metric.Meter) {
|
||||
i.delegate.Store(ctr)
|
||||
}
|
||||
|
||||
func (i *siHistogram) Record(ctx context.Context, x int64, attrs ...attribute.KeyValue) {
|
||||
func (i *siHistogram) Record(ctx context.Context, x int64, opts ...instrument.RecordOption) {
|
||||
if ctr := i.delegate.Load(); ctr != nil {
|
||||
ctr.(instrument.Int64Histogram).Record(ctx, x, attrs...)
|
||||
ctr.(instrument.Int64Histogram).Record(ctx, x, opts...)
|
||||
}
|
||||
}
|
||||
|
@ -18,18 +18,17 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
"go.opentelemetry.io/otel/metric/instrument"
|
||||
"go.opentelemetry.io/otel/metric/noop"
|
||||
)
|
||||
|
||||
func testFloat64Race(interact func(context.Context, float64, ...attribute.KeyValue), setDelegate func(metric.Meter)) {
|
||||
func testFloat64Race(interact func(float64), setDelegate func(metric.Meter)) {
|
||||
finish := make(chan struct{})
|
||||
go func() {
|
||||
for {
|
||||
interact(context.Background(), 1)
|
||||
interact(1)
|
||||
select {
|
||||
case <-finish:
|
||||
return
|
||||
@ -42,11 +41,11 @@ func testFloat64Race(interact func(context.Context, float64, ...attribute.KeyVal
|
||||
close(finish)
|
||||
}
|
||||
|
||||
func testInt64Race(interact func(context.Context, int64, ...attribute.KeyValue), setDelegate func(metric.Meter)) {
|
||||
func testInt64Race(interact func(int64), setDelegate func(metric.Meter)) {
|
||||
finish := make(chan struct{})
|
||||
go func() {
|
||||
for {
|
||||
interact(context.Background(), 1)
|
||||
interact(1)
|
||||
select {
|
||||
case <-finish:
|
||||
return
|
||||
@ -64,19 +63,19 @@ func TestAsyncInstrumentSetDelegateRace(t *testing.T) {
|
||||
t.Run("Float64", func(t *testing.T) {
|
||||
t.Run("Counter", func(t *testing.T) {
|
||||
delegate := &afCounter{}
|
||||
f := func(context.Context, float64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
|
||||
f := func(float64) { _ = delegate.Unwrap() }
|
||||
testFloat64Race(f, delegate.setDelegate)
|
||||
})
|
||||
|
||||
t.Run("UpDownCounter", func(t *testing.T) {
|
||||
delegate := &afUpDownCounter{}
|
||||
f := func(context.Context, float64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
|
||||
f := func(float64) { _ = delegate.Unwrap() }
|
||||
testFloat64Race(f, delegate.setDelegate)
|
||||
})
|
||||
|
||||
t.Run("Gauge", func(t *testing.T) {
|
||||
delegate := &afGauge{}
|
||||
f := func(context.Context, float64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
|
||||
f := func(float64) { _ = delegate.Unwrap() }
|
||||
testFloat64Race(f, delegate.setDelegate)
|
||||
})
|
||||
})
|
||||
@ -86,19 +85,19 @@ func TestAsyncInstrumentSetDelegateRace(t *testing.T) {
|
||||
t.Run("Int64", func(t *testing.T) {
|
||||
t.Run("Counter", func(t *testing.T) {
|
||||
delegate := &aiCounter{}
|
||||
f := func(context.Context, int64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
|
||||
f := func(int64) { _ = delegate.Unwrap() }
|
||||
testInt64Race(f, delegate.setDelegate)
|
||||
})
|
||||
|
||||
t.Run("UpDownCounter", func(t *testing.T) {
|
||||
delegate := &aiUpDownCounter{}
|
||||
f := func(context.Context, int64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
|
||||
f := func(int64) { _ = delegate.Unwrap() }
|
||||
testInt64Race(f, delegate.setDelegate)
|
||||
})
|
||||
|
||||
t.Run("Gauge", func(t *testing.T) {
|
||||
delegate := &aiGauge{}
|
||||
f := func(context.Context, int64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
|
||||
f := func(int64) { _ = delegate.Unwrap() }
|
||||
testInt64Race(f, delegate.setDelegate)
|
||||
})
|
||||
})
|
||||
@ -109,17 +108,20 @@ func TestSyncInstrumentSetDelegateRace(t *testing.T) {
|
||||
t.Run("Float64", func(t *testing.T) {
|
||||
t.Run("Counter", func(t *testing.T) {
|
||||
delegate := &sfCounter{}
|
||||
testFloat64Race(delegate.Add, delegate.setDelegate)
|
||||
f := func(v float64) { delegate.Add(context.Background(), v) }
|
||||
testFloat64Race(f, delegate.setDelegate)
|
||||
})
|
||||
|
||||
t.Run("UpDownCounter", func(t *testing.T) {
|
||||
delegate := &sfUpDownCounter{}
|
||||
testFloat64Race(delegate.Add, delegate.setDelegate)
|
||||
f := func(v float64) { delegate.Add(context.Background(), v) }
|
||||
testFloat64Race(f, delegate.setDelegate)
|
||||
})
|
||||
|
||||
t.Run("Histogram", func(t *testing.T) {
|
||||
delegate := &sfHistogram{}
|
||||
testFloat64Race(delegate.Record, delegate.setDelegate)
|
||||
f := func(v float64) { delegate.Record(context.Background(), v) }
|
||||
testFloat64Race(f, delegate.setDelegate)
|
||||
})
|
||||
})
|
||||
|
||||
@ -128,17 +130,20 @@ func TestSyncInstrumentSetDelegateRace(t *testing.T) {
|
||||
t.Run("Int64", func(t *testing.T) {
|
||||
t.Run("Counter", func(t *testing.T) {
|
||||
delegate := &siCounter{}
|
||||
testInt64Race(delegate.Add, delegate.setDelegate)
|
||||
f := func(v int64) { delegate.Add(context.Background(), v) }
|
||||
testInt64Race(f, delegate.setDelegate)
|
||||
})
|
||||
|
||||
t.Run("UpDownCounter", func(t *testing.T) {
|
||||
delegate := &siUpDownCounter{}
|
||||
testInt64Race(delegate.Add, delegate.setDelegate)
|
||||
f := func(v int64) { delegate.Add(context.Background(), v) }
|
||||
testInt64Race(f, delegate.setDelegate)
|
||||
})
|
||||
|
||||
t.Run("Histogram", func(t *testing.T) {
|
||||
delegate := &siHistogram{}
|
||||
testInt64Race(delegate.Record, delegate.setDelegate)
|
||||
f := func(v int64) { delegate.Record(context.Background(), v) }
|
||||
testInt64Race(f, delegate.setDelegate)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -158,10 +163,10 @@ type testCountingFloatInstrument struct {
|
||||
func (i *testCountingFloatInstrument) observe() {
|
||||
i.count++
|
||||
}
|
||||
func (i *testCountingFloatInstrument) Add(context.Context, float64, ...attribute.KeyValue) {
|
||||
func (i *testCountingFloatInstrument) Add(context.Context, float64, ...instrument.AddOption) {
|
||||
i.count++
|
||||
}
|
||||
func (i *testCountingFloatInstrument) Record(context.Context, float64, ...attribute.KeyValue) {
|
||||
func (i *testCountingFloatInstrument) Record(context.Context, float64, ...instrument.RecordOption) {
|
||||
i.count++
|
||||
}
|
||||
|
||||
@ -180,9 +185,9 @@ type testCountingIntInstrument struct {
|
||||
func (i *testCountingIntInstrument) observe() {
|
||||
i.count++
|
||||
}
|
||||
func (i *testCountingIntInstrument) Add(context.Context, int64, ...attribute.KeyValue) {
|
||||
func (i *testCountingIntInstrument) Add(context.Context, int64, ...instrument.AddOption) {
|
||||
i.count++
|
||||
}
|
||||
func (i *testCountingIntInstrument) Record(context.Context, int64, ...attribute.KeyValue) {
|
||||
func (i *testCountingIntInstrument) Record(context.Context, int64, ...instrument.RecordOption) {
|
||||
i.count++
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ package global // import "go.opentelemetry.io/otel/metric/internal/global"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
"go.opentelemetry.io/otel/metric/instrument"
|
||||
@ -157,14 +156,14 @@ type observationRecorder struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (o observationRecorder) ObserveFloat64(i instrument.Float64Observable, value float64, attr ...attribute.KeyValue) {
|
||||
func (o observationRecorder) ObserveFloat64(i instrument.Float64Observable, value float64, _ ...instrument.ObserveOption) {
|
||||
iImpl, ok := i.(*testCountingFloatInstrument)
|
||||
if ok {
|
||||
iImpl.observe()
|
||||
}
|
||||
}
|
||||
|
||||
func (o observationRecorder) ObserveInt64(i instrument.Int64Observable, value int64, attr ...attribute.KeyValue) {
|
||||
func (o observationRecorder) ObserveInt64(i instrument.Int64Observable, value int64, _ ...instrument.ObserveOption) {
|
||||
iImpl, ok := i.(*testCountingIntInstrument)
|
||||
if ok {
|
||||
iImpl.observe()
|
||||
|
@ -17,7 +17,6 @@ package metric // import "go.opentelemetry.io/otel/metric"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
"go.opentelemetry.io/otel/metric/instrument"
|
||||
)
|
||||
@ -141,10 +140,10 @@ type Callback func(context.Context, Observer) error
|
||||
type Observer interface {
|
||||
embedded.Observer
|
||||
|
||||
// ObserveFloat64 records the float64 value with attributes for obsrv.
|
||||
ObserveFloat64(obsrv instrument.Float64Observable, value float64, attributes ...attribute.KeyValue)
|
||||
// ObserveInt64 records the int64 value with attributes for obsrv.
|
||||
ObserveInt64(obsrv instrument.Int64Observable, value int64, attributes ...attribute.KeyValue)
|
||||
// ObserveFloat64 records the float64 value for obsrv.
|
||||
ObserveFloat64(obsrv instrument.Float64Observable, value float64, opts ...instrument.ObserveOption)
|
||||
// ObserveInt64 records the int64 value for obsrv.
|
||||
ObserveInt64(obsrv instrument.Int64Observable, value int64, opts ...instrument.ObserveOption)
|
||||
}
|
||||
|
||||
// Registration is an token representing the unique registration of a callback
|
||||
|
@ -26,7 +26,6 @@ package noop // import "go.opentelemetry.io/otel/metric/noop"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
"go.opentelemetry.io/otel/metric/instrument"
|
||||
@ -153,11 +152,11 @@ func (Meter) RegisterCallback(metric.Callback, ...instrument.Observable) (metric
|
||||
type Observer struct{ embedded.Observer }
|
||||
|
||||
// ObserveFloat64 performs no operation.
|
||||
func (Observer) ObserveFloat64(instrument.Float64Observable, float64, ...attribute.KeyValue) {
|
||||
func (Observer) ObserveFloat64(instrument.Float64Observable, float64, ...instrument.ObserveOption) {
|
||||
}
|
||||
|
||||
// ObserveInt64 performs no operation.
|
||||
func (Observer) ObserveInt64(instrument.Int64Observable, int64, ...attribute.KeyValue) {
|
||||
func (Observer) ObserveInt64(instrument.Int64Observable, int64, ...instrument.ObserveOption) {
|
||||
}
|
||||
|
||||
// Registration is the registration of a Callback with a No-Op Meter.
|
||||
@ -173,42 +172,42 @@ func (Registration) Unregister() error { return nil }
|
||||
type Int64Counter struct{ embedded.Int64Counter }
|
||||
|
||||
// Add performs no operation.
|
||||
func (Int64Counter) Add(context.Context, int64, ...attribute.KeyValue) {}
|
||||
func (Int64Counter) Add(context.Context, int64, ...instrument.AddOption) {}
|
||||
|
||||
// Float64Counter is an OpenTelemetry Counter used to record float64
|
||||
// measurements. It produces no telemetry.
|
||||
type Float64Counter struct{ embedded.Float64Counter }
|
||||
|
||||
// Add performs no operation.
|
||||
func (Float64Counter) Add(context.Context, float64, ...attribute.KeyValue) {}
|
||||
func (Float64Counter) Add(context.Context, float64, ...instrument.AddOption) {}
|
||||
|
||||
// Int64UpDownCounter is an OpenTelemetry UpDownCounter used to record int64
|
||||
// measurements. It produces no telemetry.
|
||||
type Int64UpDownCounter struct{ embedded.Int64UpDownCounter }
|
||||
|
||||
// Add performs no operation.
|
||||
func (Int64UpDownCounter) Add(context.Context, int64, ...attribute.KeyValue) {}
|
||||
func (Int64UpDownCounter) Add(context.Context, int64, ...instrument.AddOption) {}
|
||||
|
||||
// Float64UpDownCounter is an OpenTelemetry UpDownCounter used to record
|
||||
// float64 measurements. It produces no telemetry.
|
||||
type Float64UpDownCounter struct{ embedded.Float64UpDownCounter }
|
||||
|
||||
// Add performs no operation.
|
||||
func (Float64UpDownCounter) Add(context.Context, float64, ...attribute.KeyValue) {}
|
||||
func (Float64UpDownCounter) Add(context.Context, float64, ...instrument.AddOption) {}
|
||||
|
||||
// Int64Histogram is an OpenTelemetry Histogram used to record int64
|
||||
// measurements. It produces no telemetry.
|
||||
type Int64Histogram struct{ embedded.Int64Histogram }
|
||||
|
||||
// Record performs no operation.
|
||||
func (Int64Histogram) Record(context.Context, int64, ...attribute.KeyValue) {}
|
||||
func (Int64Histogram) Record(context.Context, int64, ...instrument.RecordOption) {}
|
||||
|
||||
// Float64Histogram is an OpenTelemetry Histogram used to record float64
|
||||
// measurements. It produces no telemetry.
|
||||
type Float64Histogram struct{ embedded.Float64Histogram }
|
||||
|
||||
// Record performs no operation.
|
||||
func (Float64Histogram) Record(context.Context, float64, ...attribute.KeyValue) {}
|
||||
func (Float64Histogram) Record(context.Context, float64, ...instrument.RecordOption) {}
|
||||
|
||||
// Int64ObservableCounter is an OpenTelemetry ObservableCounter used to record
|
||||
// int64 measurements. It produces no telemetry.
|
||||
@ -256,11 +255,11 @@ type Float64ObservableUpDownCounter struct {
|
||||
type Int64Observer struct{ embedded.Int64Observer }
|
||||
|
||||
// Observe performs no operation.
|
||||
func (Int64Observer) Observe(int64, ...attribute.KeyValue) {}
|
||||
func (Int64Observer) Observe(int64, ...instrument.ObserveOption) {}
|
||||
|
||||
// Float64Observer is a recorder of float64 measurements that performs no
|
||||
// operation.
|
||||
type Float64Observer struct{ embedded.Float64Observer }
|
||||
|
||||
// Observe performs no operation.
|
||||
func (Float64Observer) Observe(float64, ...attribute.KeyValue) {}
|
||||
func (Float64Observer) Observe(float64, ...instrument.ObserveOption) {}
|
||||
|
@ -66,59 +66,65 @@ func benchSyncViews(views ...View) func(*testing.B) {
|
||||
iCtr, err := meter.Int64Counter("int64-counter")
|
||||
assert.NoError(b, err)
|
||||
b.Run("Int64Counter", benchMeasAttrs(func() measF {
|
||||
return func(attr []attribute.KeyValue) func() {
|
||||
return func() { iCtr.Add(ctx, 1, attr...) }
|
||||
return func(s attribute.Set) func() {
|
||||
o := []instrument.AddOption{instrument.WithAttributeSet(s)}
|
||||
return func() { iCtr.Add(ctx, 1, o...) }
|
||||
}
|
||||
}()))
|
||||
|
||||
fCtr, err := meter.Float64Counter("float64-counter")
|
||||
assert.NoError(b, err)
|
||||
b.Run("Float64Counter", benchMeasAttrs(func() measF {
|
||||
return func(attr []attribute.KeyValue) func() {
|
||||
return func() { fCtr.Add(ctx, 1, attr...) }
|
||||
return func(s attribute.Set) func() {
|
||||
o := []instrument.AddOption{instrument.WithAttributeSet(s)}
|
||||
return func() { fCtr.Add(ctx, 1, o...) }
|
||||
}
|
||||
}()))
|
||||
|
||||
iUDCtr, err := meter.Int64UpDownCounter("int64-up-down-counter")
|
||||
assert.NoError(b, err)
|
||||
b.Run("Int64UpDownCounter", benchMeasAttrs(func() measF {
|
||||
return func(attr []attribute.KeyValue) func() {
|
||||
return func() { iUDCtr.Add(ctx, 1, attr...) }
|
||||
return func(s attribute.Set) func() {
|
||||
o := []instrument.AddOption{instrument.WithAttributeSet(s)}
|
||||
return func() { iUDCtr.Add(ctx, 1, o...) }
|
||||
}
|
||||
}()))
|
||||
|
||||
fUDCtr, err := meter.Float64UpDownCounter("float64-up-down-counter")
|
||||
assert.NoError(b, err)
|
||||
b.Run("Float64UpDownCounter", benchMeasAttrs(func() measF {
|
||||
return func(attr []attribute.KeyValue) func() {
|
||||
return func() { fUDCtr.Add(ctx, 1, attr...) }
|
||||
return func(s attribute.Set) func() {
|
||||
o := []instrument.AddOption{instrument.WithAttributeSet(s)}
|
||||
return func() { fUDCtr.Add(ctx, 1, o...) }
|
||||
}
|
||||
}()))
|
||||
|
||||
iHist, err := meter.Int64Histogram("int64-histogram")
|
||||
assert.NoError(b, err)
|
||||
b.Run("Int64Histogram", benchMeasAttrs(func() measF {
|
||||
return func(attr []attribute.KeyValue) func() {
|
||||
return func() { iHist.Record(ctx, 1, attr...) }
|
||||
return func(s attribute.Set) func() {
|
||||
o := []instrument.RecordOption{instrument.WithAttributeSet(s)}
|
||||
return func() { iHist.Record(ctx, 1, o...) }
|
||||
}
|
||||
}()))
|
||||
|
||||
fHist, err := meter.Float64Histogram("float64-histogram")
|
||||
assert.NoError(b, err)
|
||||
b.Run("Float64Histogram", benchMeasAttrs(func() measF {
|
||||
return func(attr []attribute.KeyValue) func() {
|
||||
return func() { fHist.Record(ctx, 1, attr...) }
|
||||
return func(s attribute.Set) func() {
|
||||
o := []instrument.RecordOption{instrument.WithAttributeSet(s)}
|
||||
return func() { fHist.Record(ctx, 1, o...) }
|
||||
}
|
||||
}()))
|
||||
}
|
||||
}
|
||||
|
||||
type measF func(attr []attribute.KeyValue) func()
|
||||
type measF func(s attribute.Set) func()
|
||||
|
||||
func benchMeasAttrs(meas measF) func(*testing.B) {
|
||||
return func(b *testing.B) {
|
||||
b.Run("Attributes/0", func(b *testing.B) {
|
||||
f := meas(nil)
|
||||
f := meas(*attribute.EmptySet())
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
@ -126,8 +132,7 @@ func benchMeasAttrs(meas measF) func(*testing.B) {
|
||||
}
|
||||
})
|
||||
b.Run("Attributes/1", func(b *testing.B) {
|
||||
attrs := []attribute.KeyValue{attribute.Bool("K", true)}
|
||||
f := meas(attrs)
|
||||
f := meas(attribute.NewSet(attribute.Bool("K", true)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
@ -141,7 +146,7 @@ func benchMeasAttrs(meas measF) func(*testing.B) {
|
||||
for i := 2; i < n; i++ {
|
||||
attrs = append(attrs, attribute.Int(strconv.Itoa(i), i))
|
||||
}
|
||||
f := meas(attrs)
|
||||
f := meas(attribute.NewSet(attrs...))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
@ -165,163 +170,163 @@ func benchCollectViews(views ...View) func(*testing.B) {
|
||||
}
|
||||
ctx := context.Background()
|
||||
return func(b *testing.B) {
|
||||
b.Run("Int64Counter/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Int64Counter/1", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Int64Counter")
|
||||
i, err := m.Int64Counter("int64-counter")
|
||||
assert.NoError(b, err)
|
||||
i.Add(ctx, 1, attr...)
|
||||
i.Add(ctx, 1, instrument.WithAttributeSet(s))
|
||||
return r
|
||||
}))
|
||||
b.Run("Int64Counter/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Int64Counter/10", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Int64Counter")
|
||||
i, err := m.Int64Counter("int64-counter")
|
||||
assert.NoError(b, err)
|
||||
for n := 0; n < 10; n++ {
|
||||
i.Add(ctx, 1, attr...)
|
||||
i.Add(ctx, 1, instrument.WithAttributeSet(s))
|
||||
}
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Float64Counter/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Float64Counter/1", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Float64Counter")
|
||||
i, err := m.Float64Counter("float64-counter")
|
||||
assert.NoError(b, err)
|
||||
i.Add(ctx, 1, attr...)
|
||||
i.Add(ctx, 1, instrument.WithAttributeSet(s))
|
||||
return r
|
||||
}))
|
||||
b.Run("Float64Counter/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Float64Counter/10", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Float64Counter")
|
||||
i, err := m.Float64Counter("float64-counter")
|
||||
assert.NoError(b, err)
|
||||
for n := 0; n < 10; n++ {
|
||||
i.Add(ctx, 1, attr...)
|
||||
i.Add(ctx, 1, instrument.WithAttributeSet(s))
|
||||
}
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Int64UpDownCounter/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Int64UpDownCounter/1", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Int64UpDownCounter")
|
||||
i, err := m.Int64UpDownCounter("int64-up-down-counter")
|
||||
assert.NoError(b, err)
|
||||
i.Add(ctx, 1, attr...)
|
||||
i.Add(ctx, 1, instrument.WithAttributeSet(s))
|
||||
return r
|
||||
}))
|
||||
b.Run("Int64UpDownCounter/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Int64UpDownCounter/10", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Int64UpDownCounter")
|
||||
i, err := m.Int64UpDownCounter("int64-up-down-counter")
|
||||
assert.NoError(b, err)
|
||||
for n := 0; n < 10; n++ {
|
||||
i.Add(ctx, 1, attr...)
|
||||
i.Add(ctx, 1, instrument.WithAttributeSet(s))
|
||||
}
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Float64UpDownCounter/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Float64UpDownCounter/1", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Float64UpDownCounter")
|
||||
i, err := m.Float64UpDownCounter("float64-up-down-counter")
|
||||
assert.NoError(b, err)
|
||||
i.Add(ctx, 1, attr...)
|
||||
i.Add(ctx, 1, instrument.WithAttributeSet(s))
|
||||
return r
|
||||
}))
|
||||
b.Run("Float64UpDownCounter/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Float64UpDownCounter/10", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Float64UpDownCounter")
|
||||
i, err := m.Float64UpDownCounter("float64-up-down-counter")
|
||||
assert.NoError(b, err)
|
||||
for n := 0; n < 10; n++ {
|
||||
i.Add(ctx, 1, attr...)
|
||||
i.Add(ctx, 1, instrument.WithAttributeSet(s))
|
||||
}
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Int64Histogram/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Int64Histogram/1", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Int64Histogram")
|
||||
i, err := m.Int64Histogram("int64-histogram")
|
||||
assert.NoError(b, err)
|
||||
i.Record(ctx, 1, attr...)
|
||||
i.Record(ctx, 1, instrument.WithAttributeSet(s))
|
||||
return r
|
||||
}))
|
||||
b.Run("Int64Histogram/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Int64Histogram/10", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Int64Histogram")
|
||||
i, err := m.Int64Histogram("int64-histogram")
|
||||
assert.NoError(b, err)
|
||||
for n := 0; n < 10; n++ {
|
||||
i.Record(ctx, 1, attr...)
|
||||
i.Record(ctx, 1, instrument.WithAttributeSet(s))
|
||||
}
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Float64Histogram/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Float64Histogram/1", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Float64Histogram")
|
||||
i, err := m.Float64Histogram("float64-histogram")
|
||||
assert.NoError(b, err)
|
||||
i.Record(ctx, 1, attr...)
|
||||
i.Record(ctx, 1, instrument.WithAttributeSet(s))
|
||||
return r
|
||||
}))
|
||||
b.Run("Float64Histogram/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Float64Histogram/10", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Float64Histogram")
|
||||
i, err := m.Float64Histogram("float64-histogram")
|
||||
assert.NoError(b, err)
|
||||
for n := 0; n < 10; n++ {
|
||||
i.Record(ctx, 1, attr...)
|
||||
i.Record(ctx, 1, instrument.WithAttributeSet(s))
|
||||
}
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Int64ObservableCounter", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Int64ObservableCounter", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Int64ObservableCounter")
|
||||
_, err := m.Int64ObservableCounter(
|
||||
"int64-observable-counter",
|
||||
instrument.WithInt64Callback(int64Cback(attr)),
|
||||
instrument.WithInt64Callback(int64Cback(s)),
|
||||
)
|
||||
assert.NoError(b, err)
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Float64ObservableCounter", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Float64ObservableCounter", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Float64ObservableCounter")
|
||||
_, err := m.Float64ObservableCounter(
|
||||
"float64-observable-counter",
|
||||
instrument.WithFloat64Callback(float64Cback(attr)),
|
||||
instrument.WithFloat64Callback(float64Cback(s)),
|
||||
)
|
||||
assert.NoError(b, err)
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Int64ObservableUpDownCounter", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Int64ObservableUpDownCounter", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Int64ObservableUpDownCounter")
|
||||
_, err := m.Int64ObservableUpDownCounter(
|
||||
"int64-observable-up-down-counter",
|
||||
instrument.WithInt64Callback(int64Cback(attr)),
|
||||
instrument.WithInt64Callback(int64Cback(s)),
|
||||
)
|
||||
assert.NoError(b, err)
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Float64ObservableUpDownCounter", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Float64ObservableUpDownCounter", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Float64ObservableUpDownCounter")
|
||||
_, err := m.Float64ObservableUpDownCounter(
|
||||
"float64-observable-up-down-counter",
|
||||
instrument.WithFloat64Callback(float64Cback(attr)),
|
||||
instrument.WithFloat64Callback(float64Cback(s)),
|
||||
)
|
||||
assert.NoError(b, err)
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Int64ObservableGauge", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Int64ObservableGauge", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Int64ObservableGauge")
|
||||
_, err := m.Int64ObservableGauge(
|
||||
"int64-observable-gauge",
|
||||
instrument.WithInt64Callback(int64Cback(attr)),
|
||||
instrument.WithInt64Callback(int64Cback(s)),
|
||||
)
|
||||
assert.NoError(b, err)
|
||||
return r
|
||||
}))
|
||||
|
||||
b.Run("Float64ObservableGauge", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
|
||||
b.Run("Float64ObservableGauge", benchCollectAttrs(func(s attribute.Set) Reader {
|
||||
m, r := setup("benchCollectViews/Float64ObservableGauge")
|
||||
_, err := m.Float64ObservableGauge(
|
||||
"float64-observable-gauge",
|
||||
instrument.WithFloat64Callback(float64Cback(attr)),
|
||||
instrument.WithFloat64Callback(float64Cback(s)),
|
||||
)
|
||||
assert.NoError(b, err)
|
||||
return r
|
||||
@ -329,21 +334,23 @@ func benchCollectViews(views ...View) func(*testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func int64Cback(attr []attribute.KeyValue) instrument.Int64Callback {
|
||||
func int64Cback(s attribute.Set) instrument.Int64Callback {
|
||||
opt := []instrument.ObserveOption{instrument.WithAttributeSet(s)}
|
||||
return func(_ context.Context, o instrument.Int64Observer) error {
|
||||
o.Observe(1, attr...)
|
||||
o.Observe(1, opt...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func float64Cback(attr []attribute.KeyValue) instrument.Float64Callback {
|
||||
func float64Cback(s attribute.Set) instrument.Float64Callback {
|
||||
opt := []instrument.ObserveOption{instrument.WithAttributeSet(s)}
|
||||
return func(_ context.Context, o instrument.Float64Observer) error {
|
||||
o.Observe(1, attr...)
|
||||
o.Observe(1, opt...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func benchCollectAttrs(setup func([]attribute.KeyValue) Reader) func(*testing.B) {
|
||||
func benchCollectAttrs(setup func(attribute.Set) Reader) func(*testing.B) {
|
||||
ctx := context.Background()
|
||||
out := new(metricdata.ResourceMetrics)
|
||||
run := func(reader Reader) func(b *testing.B) {
|
||||
@ -355,14 +362,14 @@ func benchCollectAttrs(setup func([]attribute.KeyValue) Reader) func(*testing.B)
|
||||
}
|
||||
}
|
||||
return func(b *testing.B) {
|
||||
b.Run("Attributes/0", run(setup(nil)))
|
||||
b.Run("Attributes/0", run(setup(*attribute.EmptySet())))
|
||||
|
||||
attrs := []attribute.KeyValue{attribute.Bool("K", true)}
|
||||
b.Run("Attributes/1", run(setup(attrs)))
|
||||
b.Run("Attributes/1", run(setup(attribute.NewSet(attrs...))))
|
||||
|
||||
for i := 2; i < 10; i++ {
|
||||
attrs = append(attrs, attribute.Int(strconv.Itoa(i), i))
|
||||
}
|
||||
b.Run("Attributes/10", run(setup(attrs)))
|
||||
b.Run("Attributes/10", run(setup(attribute.NewSet(attrs...))))
|
||||
}
|
||||
}
|
||||
|
@ -170,40 +170,63 @@ type streamID struct {
|
||||
Number string
|
||||
}
|
||||
|
||||
type instrumentImpl[N int64 | float64] struct {
|
||||
aggregators []internal.Aggregator[N]
|
||||
type int64Inst struct {
|
||||
aggregators []internal.Aggregator[int64]
|
||||
|
||||
embedded.Float64Counter
|
||||
embedded.Float64UpDownCounter
|
||||
embedded.Float64Histogram
|
||||
embedded.Int64Counter
|
||||
embedded.Int64UpDownCounter
|
||||
embedded.Int64Histogram
|
||||
}
|
||||
|
||||
var _ instrument.Float64Counter = (*instrumentImpl[float64])(nil)
|
||||
var _ instrument.Float64UpDownCounter = (*instrumentImpl[float64])(nil)
|
||||
var _ instrument.Float64Histogram = (*instrumentImpl[float64])(nil)
|
||||
var _ instrument.Int64Counter = (*instrumentImpl[int64])(nil)
|
||||
var _ instrument.Int64UpDownCounter = (*instrumentImpl[int64])(nil)
|
||||
var _ instrument.Int64Histogram = (*instrumentImpl[int64])(nil)
|
||||
var _ instrument.Int64Counter = (*int64Inst)(nil)
|
||||
var _ instrument.Int64UpDownCounter = (*int64Inst)(nil)
|
||||
var _ instrument.Int64Histogram = (*int64Inst)(nil)
|
||||
|
||||
func (i *instrumentImpl[N]) Add(ctx context.Context, val N, attrs ...attribute.KeyValue) {
|
||||
i.aggregate(ctx, val, attrs)
|
||||
func (i *int64Inst) Add(ctx context.Context, val int64, opts ...instrument.AddOption) {
|
||||
c := instrument.NewAddConfig(opts)
|
||||
i.aggregate(ctx, val, c.Attributes())
|
||||
}
|
||||
|
||||
func (i *instrumentImpl[N]) Record(ctx context.Context, val N, attrs ...attribute.KeyValue) {
|
||||
i.aggregate(ctx, val, attrs)
|
||||
func (i *int64Inst) Record(ctx context.Context, val int64, opts ...instrument.RecordOption) {
|
||||
c := instrument.NewRecordConfig(opts)
|
||||
i.aggregate(ctx, val, c.Attributes())
|
||||
}
|
||||
|
||||
func (i *instrumentImpl[N]) aggregate(ctx context.Context, val N, attrs []attribute.KeyValue) {
|
||||
func (i *int64Inst) aggregate(ctx context.Context, val int64, s attribute.Set) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
for _, agg := range i.aggregators {
|
||||
agg.Aggregate(val, s)
|
||||
}
|
||||
}
|
||||
|
||||
type float64Inst struct {
|
||||
aggregators []internal.Aggregator[float64]
|
||||
|
||||
embedded.Float64Counter
|
||||
embedded.Float64UpDownCounter
|
||||
embedded.Float64Histogram
|
||||
}
|
||||
|
||||
var _ instrument.Float64Counter = (*float64Inst)(nil)
|
||||
var _ instrument.Float64UpDownCounter = (*float64Inst)(nil)
|
||||
var _ instrument.Float64Histogram = (*float64Inst)(nil)
|
||||
|
||||
func (i *float64Inst) Add(ctx context.Context, val float64, opts ...instrument.AddOption) {
|
||||
c := instrument.NewAddConfig(opts)
|
||||
i.aggregate(ctx, val, c.Attributes())
|
||||
}
|
||||
|
||||
func (i *float64Inst) Record(ctx context.Context, val float64, opts ...instrument.RecordOption) {
|
||||
c := instrument.NewRecordConfig(opts)
|
||||
i.aggregate(ctx, val, c.Attributes())
|
||||
}
|
||||
|
||||
func (i *float64Inst) aggregate(ctx context.Context, val float64, s attribute.Set) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
// Do not use single attribute.Sortable and attribute.NewSetWithSortable,
|
||||
// this method needs to be concurrent safe. Let the sync.Pool in the
|
||||
// attribute package handle allocations of the Sortable.
|
||||
s := attribute.NewSet(attrs...)
|
||||
for _, agg := range i.aggregators {
|
||||
agg.Aggregate(val, s)
|
||||
}
|
||||
@ -277,11 +300,7 @@ func newObservable[N int64 | float64](scope instrumentation.Scope, kind Instrume
|
||||
}
|
||||
|
||||
// observe records the val for the set of attrs.
|
||||
func (o *observable[N]) observe(val N, attrs []attribute.KeyValue) {
|
||||
// Do not use single attribute.Sortable and attribute.NewSetWithSortable,
|
||||
// this method needs to be concurrent safe. Let the sync.Pool in the
|
||||
// attribute package handle allocations of the Sortable.
|
||||
s := attribute.NewSet(attrs...)
|
||||
func (o *observable[N]) observe(val N, s attribute.Set) {
|
||||
for _, agg := range o.aggregators {
|
||||
agg.Aggregate(val, s)
|
||||
}
|
||||
|
@ -23,16 +23,16 @@ import (
|
||||
)
|
||||
|
||||
func BenchmarkInstrument(b *testing.B) {
|
||||
attr := func(id int) []attribute.KeyValue {
|
||||
return []attribute.KeyValue{
|
||||
attr := func(id int) attribute.Set {
|
||||
return attribute.NewSet(
|
||||
attribute.String("user", "Alice"),
|
||||
attribute.Bool("admin", true),
|
||||
attribute.Int("id", id),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
b.Run("instrumentImpl/aggregate", func(b *testing.B) {
|
||||
inst := instrumentImpl[int64]{aggregators: []internal.Aggregator[int64]{
|
||||
inst := int64Inst{aggregators: []internal.Aggregator[int64]{
|
||||
internal.NewLastValue[int64](),
|
||||
internal.NewCumulativeSum[int64](true),
|
||||
internal.NewDeltaSum[int64](true),
|
||||
|
@ -94,8 +94,8 @@ type inst struct {
|
||||
embedded.Int64Histogram
|
||||
}
|
||||
|
||||
func (inst) Add(context.Context, int64, ...attribute.KeyValue) {}
|
||||
func (inst) Record(context.Context, int64, ...attribute.KeyValue) {}
|
||||
func (inst) Add(context.Context, int64, ...instrument.AddOption) {}
|
||||
func (inst) Record(context.Context, int64, ...instrument.RecordOption) {}
|
||||
|
||||
func Example() {
|
||||
m := meter{}
|
||||
|
@ -19,7 +19,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/internal/global"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/embedded"
|
||||
@ -38,8 +37,8 @@ type meter struct {
|
||||
scope instrumentation.Scope
|
||||
pipes pipelines
|
||||
|
||||
int64IP *instProvider[int64]
|
||||
float64IP *instProvider[float64]
|
||||
int64IP *int64InstProvider
|
||||
float64IP *float64InstProvider
|
||||
}
|
||||
|
||||
func newMeter(s instrumentation.Scope, p pipelines) *meter {
|
||||
@ -50,8 +49,8 @@ func newMeter(s instrumentation.Scope, p pipelines) *meter {
|
||||
return &meter{
|
||||
scope: s,
|
||||
pipes: p,
|
||||
int64IP: newInstProvider[int64](s, p, &viewCache),
|
||||
float64IP: newInstProvider[float64](s, p, &viewCache),
|
||||
int64IP: newInt64InstProvider(s, p, &viewCache),
|
||||
float64IP: newFloat64InstProvider(s, p, &viewCache),
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,7 +296,7 @@ var (
|
||||
errUnregObserver = errors.New("observable instrument not registered for callback")
|
||||
)
|
||||
|
||||
func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, a ...attribute.KeyValue) {
|
||||
func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, opts ...instrument.ObserveOption) {
|
||||
var oImpl float64Observable
|
||||
switch conv := o.(type) {
|
||||
case float64Observable:
|
||||
@ -326,10 +325,11 @@ func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, a ..
|
||||
)
|
||||
return
|
||||
}
|
||||
oImpl.observe(v, a)
|
||||
c := instrument.NewObserveConfig(opts)
|
||||
oImpl.observe(v, c.Attributes())
|
||||
}
|
||||
|
||||
func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, a ...attribute.KeyValue) {
|
||||
func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, opts ...instrument.ObserveOption) {
|
||||
var oImpl int64Observable
|
||||
switch conv := o.(type) {
|
||||
case int64Observable:
|
||||
@ -358,7 +358,8 @@ func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, a ...attri
|
||||
)
|
||||
return
|
||||
}
|
||||
oImpl.observe(v, a)
|
||||
c := instrument.NewObserveConfig(opts)
|
||||
oImpl.observe(v, c.Attributes())
|
||||
}
|
||||
|
||||
type noopRegister struct{ embedded.Registration }
|
||||
@ -367,18 +368,18 @@ func (noopRegister) Unregister() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// instProvider provides all OpenTelemetry instruments.
|
||||
type instProvider[N int64 | float64] struct {
|
||||
// int64InstProvider provides int64 OpenTelemetry instruments.
|
||||
type int64InstProvider struct {
|
||||
scope instrumentation.Scope
|
||||
pipes pipelines
|
||||
resolve resolver[N]
|
||||
resolve resolver[int64]
|
||||
}
|
||||
|
||||
func newInstProvider[N int64 | float64](s instrumentation.Scope, p pipelines, c *cache[string, streamID]) *instProvider[N] {
|
||||
return &instProvider[N]{scope: s, pipes: p, resolve: newResolver[N](p, c)}
|
||||
func newInt64InstProvider(s instrumentation.Scope, p pipelines, c *cache[string, streamID]) *int64InstProvider {
|
||||
return &int64InstProvider{scope: s, pipes: p, resolve: newResolver[int64](p, c)}
|
||||
}
|
||||
|
||||
func (p *instProvider[N]) aggs(kind InstrumentKind, name, desc, u string) ([]internal.Aggregator[N], error) {
|
||||
func (p *int64InstProvider) aggs(kind InstrumentKind, name, desc, u string) ([]internal.Aggregator[int64], error) {
|
||||
inst := Instrument{
|
||||
Name: name,
|
||||
Description: desc,
|
||||
@ -390,12 +391,40 @@ func (p *instProvider[N]) aggs(kind InstrumentKind, name, desc, u string) ([]int
|
||||
}
|
||||
|
||||
// lookup returns the resolved instrumentImpl.
|
||||
func (p *instProvider[N]) lookup(kind InstrumentKind, name, desc, u string) (*instrumentImpl[N], error) {
|
||||
func (p *int64InstProvider) lookup(kind InstrumentKind, name, desc, u string) (*int64Inst, error) {
|
||||
aggs, err := p.aggs(kind, name, desc, u)
|
||||
return &instrumentImpl[N]{aggregators: aggs}, err
|
||||
return &int64Inst{aggregators: aggs}, err
|
||||
}
|
||||
|
||||
type int64ObservProvider struct{ *instProvider[int64] }
|
||||
// float64InstProvider provides float64 OpenTelemetry instruments.
|
||||
type float64InstProvider struct {
|
||||
scope instrumentation.Scope
|
||||
pipes pipelines
|
||||
resolve resolver[float64]
|
||||
}
|
||||
|
||||
func newFloat64InstProvider(s instrumentation.Scope, p pipelines, c *cache[string, streamID]) *float64InstProvider {
|
||||
return &float64InstProvider{scope: s, pipes: p, resolve: newResolver[float64](p, c)}
|
||||
}
|
||||
|
||||
func (p *float64InstProvider) aggs(kind InstrumentKind, name, desc, u string) ([]internal.Aggregator[float64], error) {
|
||||
inst := Instrument{
|
||||
Name: name,
|
||||
Description: desc,
|
||||
Unit: u,
|
||||
Kind: kind,
|
||||
Scope: p.scope,
|
||||
}
|
||||
return p.resolve.Aggregators(inst)
|
||||
}
|
||||
|
||||
// lookup returns the resolved instrumentImpl.
|
||||
func (p *float64InstProvider) lookup(kind InstrumentKind, name, desc, u string) (*float64Inst, error) {
|
||||
aggs, err := p.aggs(kind, name, desc, u)
|
||||
return &float64Inst{aggregators: aggs}, err
|
||||
}
|
||||
|
||||
type int64ObservProvider struct{ *int64InstProvider }
|
||||
|
||||
func (p int64ObservProvider) lookup(kind InstrumentKind, name, desc, u string) (int64Observable, error) {
|
||||
aggs, err := p.aggs(kind, name, desc, u)
|
||||
@ -423,11 +452,12 @@ type int64Observer struct {
|
||||
int64Observable
|
||||
}
|
||||
|
||||
func (o int64Observer) Observe(val int64, attrs ...attribute.KeyValue) {
|
||||
o.observe(val, attrs)
|
||||
func (o int64Observer) Observe(val int64, opts ...instrument.ObserveOption) {
|
||||
c := instrument.NewObserveConfig(opts)
|
||||
o.observe(val, c.Attributes())
|
||||
}
|
||||
|
||||
type float64ObservProvider struct{ *instProvider[float64] }
|
||||
type float64ObservProvider struct{ *float64InstProvider }
|
||||
|
||||
func (p float64ObservProvider) lookup(kind InstrumentKind, name, desc, u string) (float64Observable, error) {
|
||||
aggs, err := p.aggs(kind, name, desc, u)
|
||||
@ -455,6 +485,7 @@ type float64Observer struct {
|
||||
float64Observable
|
||||
}
|
||||
|
||||
func (o float64Observer) Observe(val float64, attrs ...attribute.KeyValue) {
|
||||
o.observe(val, attrs)
|
||||
func (o float64Observer) Observe(val float64, opts ...instrument.ObserveOption) {
|
||||
c := instrument.NewObserveConfig(opts)
|
||||
o.observe(val, c.Attributes())
|
||||
}
|
||||
|
@ -169,7 +169,8 @@ func TestCallbackUnregisterConcurrency(t *testing.T) {
|
||||
|
||||
// Instruments should produce correct ResourceMetrics.
|
||||
func TestMeterCreatesInstruments(t *testing.T) {
|
||||
attrs := []attribute.KeyValue{attribute.String("name", "alice")}
|
||||
attrs := attribute.NewSet(attribute.String("name", "alice"))
|
||||
opt := instrument.WithAttributeSet(attrs)
|
||||
testCases := []struct {
|
||||
name string
|
||||
fn func(*testing.T, metric.Meter)
|
||||
@ -179,7 +180,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
name: "ObservableInt64Count",
|
||||
fn: func(t *testing.T, m metric.Meter) {
|
||||
cback := func(_ context.Context, o instrument.Int64Observer) error {
|
||||
o.Observe(4, attrs...)
|
||||
o.Observe(4, opt)
|
||||
return nil
|
||||
}
|
||||
ctr, err := m.Int64ObservableCounter("aint", instrument.WithInt64Callback(cback))
|
||||
@ -196,7 +197,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
Temporality: metricdata.CumulativeTemporality,
|
||||
IsMonotonic: true,
|
||||
DataPoints: []metricdata.DataPoint[int64]{
|
||||
{Attributes: attribute.NewSet(attrs...), Value: 4},
|
||||
{Attributes: attrs, Value: 4},
|
||||
{Value: 3},
|
||||
},
|
||||
},
|
||||
@ -206,7 +207,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
name: "ObservableInt64UpDownCount",
|
||||
fn: func(t *testing.T, m metric.Meter) {
|
||||
cback := func(_ context.Context, o instrument.Int64Observer) error {
|
||||
o.Observe(4, attrs...)
|
||||
o.Observe(4, opt)
|
||||
return nil
|
||||
}
|
||||
ctr, err := m.Int64ObservableUpDownCounter("aint", instrument.WithInt64Callback(cback))
|
||||
@ -223,7 +224,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
Temporality: metricdata.CumulativeTemporality,
|
||||
IsMonotonic: false,
|
||||
DataPoints: []metricdata.DataPoint[int64]{
|
||||
{Attributes: attribute.NewSet(attrs...), Value: 4},
|
||||
{Attributes: attrs, Value: 4},
|
||||
{Value: 11},
|
||||
},
|
||||
},
|
||||
@ -233,7 +234,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
name: "ObservableInt64Gauge",
|
||||
fn: func(t *testing.T, m metric.Meter) {
|
||||
cback := func(_ context.Context, o instrument.Int64Observer) error {
|
||||
o.Observe(4, attrs...)
|
||||
o.Observe(4, opt)
|
||||
return nil
|
||||
}
|
||||
gauge, err := m.Int64ObservableGauge("agauge", instrument.WithInt64Callback(cback))
|
||||
@ -248,7 +249,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
Name: "agauge",
|
||||
Data: metricdata.Gauge[int64]{
|
||||
DataPoints: []metricdata.DataPoint[int64]{
|
||||
{Attributes: attribute.NewSet(attrs...), Value: 4},
|
||||
{Attributes: attrs, Value: 4},
|
||||
{Value: 11},
|
||||
},
|
||||
},
|
||||
@ -258,7 +259,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
name: "ObservableFloat64Count",
|
||||
fn: func(t *testing.T, m metric.Meter) {
|
||||
cback := func(_ context.Context, o instrument.Float64Observer) error {
|
||||
o.Observe(4, attrs...)
|
||||
o.Observe(4, opt)
|
||||
return nil
|
||||
}
|
||||
ctr, err := m.Float64ObservableCounter("afloat", instrument.WithFloat64Callback(cback))
|
||||
@ -275,7 +276,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
Temporality: metricdata.CumulativeTemporality,
|
||||
IsMonotonic: true,
|
||||
DataPoints: []metricdata.DataPoint[float64]{
|
||||
{Attributes: attribute.NewSet(attrs...), Value: 4},
|
||||
{Attributes: attrs, Value: 4},
|
||||
{Value: 3},
|
||||
},
|
||||
},
|
||||
@ -285,7 +286,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
name: "ObservableFloat64UpDownCount",
|
||||
fn: func(t *testing.T, m metric.Meter) {
|
||||
cback := func(_ context.Context, o instrument.Float64Observer) error {
|
||||
o.Observe(4, attrs...)
|
||||
o.Observe(4, opt)
|
||||
return nil
|
||||
}
|
||||
ctr, err := m.Float64ObservableUpDownCounter("afloat", instrument.WithFloat64Callback(cback))
|
||||
@ -302,7 +303,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
Temporality: metricdata.CumulativeTemporality,
|
||||
IsMonotonic: false,
|
||||
DataPoints: []metricdata.DataPoint[float64]{
|
||||
{Attributes: attribute.NewSet(attrs...), Value: 4},
|
||||
{Attributes: attrs, Value: 4},
|
||||
{Value: 11},
|
||||
},
|
||||
},
|
||||
@ -312,7 +313,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
name: "ObservableFloat64Gauge",
|
||||
fn: func(t *testing.T, m metric.Meter) {
|
||||
cback := func(_ context.Context, o instrument.Float64Observer) error {
|
||||
o.Observe(4, attrs...)
|
||||
o.Observe(4, opt)
|
||||
return nil
|
||||
}
|
||||
gauge, err := m.Float64ObservableGauge("agauge", instrument.WithFloat64Callback(cback))
|
||||
@ -327,7 +328,7 @@ func TestMeterCreatesInstruments(t *testing.T) {
|
||||
Name: "agauge",
|
||||
Data: metricdata.Gauge[float64]{
|
||||
DataPoints: []metricdata.DataPoint[float64]{
|
||||
{Attributes: attribute.NewSet(attrs...), Value: 4},
|
||||
{Attributes: attrs, Value: 4},
|
||||
{Value: 11},
|
||||
},
|
||||
},
|
||||
@ -885,6 +886,12 @@ func TestAttributeFilter(t *testing.T) {
|
||||
}
|
||||
|
||||
func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
fooBar := attribute.NewSet(attribute.String("foo", "bar"))
|
||||
withFooBar := instrument.WithAttributeSet(fooBar)
|
||||
v1 := attribute.NewSet(attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
withV1 := instrument.WithAttributeSet(v1)
|
||||
v2 := attribute.NewSet(attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
withV2 := instrument.WithAttributeSet(v2)
|
||||
testcases := []struct {
|
||||
name string
|
||||
register func(t *testing.T, mtr metric.Meter) error
|
||||
@ -898,9 +905,9 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
_, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error {
|
||||
o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
o.ObserveFloat64(ctr, 2.0, attribute.String("foo", "bar"))
|
||||
o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
o.ObserveFloat64(ctr, 1.0, withV1)
|
||||
o.ObserveFloat64(ctr, 2.0, withFooBar)
|
||||
o.ObserveFloat64(ctr, 1.0, withV2)
|
||||
return nil
|
||||
}, ctr)
|
||||
return err
|
||||
@ -909,10 +916,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
Name: "afcounter",
|
||||
Data: metricdata.Sum[float64]{
|
||||
DataPoints: []metricdata.DataPoint[float64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Value: 4.0,
|
||||
},
|
||||
{Attributes: fooBar, Value: 4.0},
|
||||
},
|
||||
Temporality: temporality,
|
||||
IsMonotonic: true,
|
||||
@ -927,9 +931,9 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
_, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error {
|
||||
o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
o.ObserveFloat64(ctr, 2.0, attribute.String("foo", "bar"))
|
||||
o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
o.ObserveFloat64(ctr, 1.0, withV1)
|
||||
o.ObserveFloat64(ctr, 2.0, withFooBar)
|
||||
o.ObserveFloat64(ctr, 1.0, withV2)
|
||||
return nil
|
||||
}, ctr)
|
||||
return err
|
||||
@ -956,8 +960,8 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
_, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error {
|
||||
o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
o.ObserveFloat64(ctr, 2.0, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
o.ObserveFloat64(ctr, 1.0, withV1)
|
||||
o.ObserveFloat64(ctr, 2.0, withV2)
|
||||
return nil
|
||||
}, ctr)
|
||||
return err
|
||||
@ -966,10 +970,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
Name: "afgauge",
|
||||
Data: metricdata.Gauge[float64]{
|
||||
DataPoints: []metricdata.DataPoint[float64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Value: 2.0,
|
||||
},
|
||||
{Attributes: fooBar, Value: 2.0},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -982,9 +983,9 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
_, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error {
|
||||
o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
o.ObserveInt64(ctr, 20, attribute.String("foo", "bar"))
|
||||
o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
o.ObserveInt64(ctr, 10, withV1)
|
||||
o.ObserveInt64(ctr, 20, withFooBar)
|
||||
o.ObserveInt64(ctr, 10, withV2)
|
||||
return nil
|
||||
}, ctr)
|
||||
return err
|
||||
@ -993,10 +994,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
Name: "aicounter",
|
||||
Data: metricdata.Sum[int64]{
|
||||
DataPoints: []metricdata.DataPoint[int64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Value: 40,
|
||||
},
|
||||
{Attributes: fooBar, Value: 40},
|
||||
},
|
||||
Temporality: temporality,
|
||||
IsMonotonic: true,
|
||||
@ -1011,9 +1009,9 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
_, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error {
|
||||
o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
o.ObserveInt64(ctr, 20, attribute.String("foo", "bar"))
|
||||
o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
o.ObserveInt64(ctr, 10, withV1)
|
||||
o.ObserveInt64(ctr, 20, withFooBar)
|
||||
o.ObserveInt64(ctr, 10, withV2)
|
||||
return nil
|
||||
}, ctr)
|
||||
return err
|
||||
@ -1022,10 +1020,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
Name: "aiupdowncounter",
|
||||
Data: metricdata.Sum[int64]{
|
||||
DataPoints: []metricdata.DataPoint[int64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Value: 40,
|
||||
},
|
||||
{Attributes: fooBar, Value: 40},
|
||||
},
|
||||
Temporality: temporality,
|
||||
IsMonotonic: false,
|
||||
@ -1040,8 +1035,8 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
_, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error {
|
||||
o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
o.ObserveInt64(ctr, 20, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
o.ObserveInt64(ctr, 10, withV1)
|
||||
o.ObserveInt64(ctr, 20, withV2)
|
||||
return nil
|
||||
}, ctr)
|
||||
return err
|
||||
@ -1050,10 +1045,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
Name: "aigauge",
|
||||
Data: metricdata.Gauge[int64]{
|
||||
DataPoints: []metricdata.DataPoint[int64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Value: 20,
|
||||
},
|
||||
{Attributes: fooBar, Value: 20},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -1066,18 +1058,15 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
|
||||
ctr.Add(context.Background(), 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
ctr.Add(context.Background(), 2.0, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
ctr.Add(context.Background(), 1.0, withV1)
|
||||
ctr.Add(context.Background(), 2.0, withV2)
|
||||
return nil
|
||||
},
|
||||
wantMetric: metricdata.Metrics{
|
||||
Name: "sfcounter",
|
||||
Data: metricdata.Sum[float64]{
|
||||
DataPoints: []metricdata.DataPoint[float64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Value: 3.0,
|
||||
},
|
||||
{Attributes: fooBar, Value: 3.0},
|
||||
},
|
||||
Temporality: temporality,
|
||||
IsMonotonic: true,
|
||||
@ -1092,18 +1081,15 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
|
||||
ctr.Add(context.Background(), 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
ctr.Add(context.Background(), 2.0, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
ctr.Add(context.Background(), 1.0, withV1)
|
||||
ctr.Add(context.Background(), 2.0, withV2)
|
||||
return nil
|
||||
},
|
||||
wantMetric: metricdata.Metrics{
|
||||
Name: "sfupdowncounter",
|
||||
Data: metricdata.Sum[float64]{
|
||||
DataPoints: []metricdata.DataPoint[float64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Value: 3.0,
|
||||
},
|
||||
{Attributes: fooBar, Value: 3.0},
|
||||
},
|
||||
Temporality: temporality,
|
||||
IsMonotonic: false,
|
||||
@ -1118,8 +1104,8 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
|
||||
ctr.Record(context.Background(), 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
ctr.Record(context.Background(), 2.0, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
ctr.Record(context.Background(), 1.0, withV1)
|
||||
ctr.Record(context.Background(), 2.0, withV2)
|
||||
return nil
|
||||
},
|
||||
wantMetric: metricdata.Metrics{
|
||||
@ -1127,7 +1113,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
Data: metricdata.Histogram[float64]{
|
||||
DataPoints: []metricdata.HistogramDataPoint[float64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Attributes: fooBar,
|
||||
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
|
||||
BucketCounts: []uint64{0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
Count: 2,
|
||||
@ -1148,18 +1134,15 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
|
||||
ctr.Add(context.Background(), 10, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
ctr.Add(context.Background(), 20, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
ctr.Add(context.Background(), 10, withV1)
|
||||
ctr.Add(context.Background(), 20, withV2)
|
||||
return nil
|
||||
},
|
||||
wantMetric: metricdata.Metrics{
|
||||
Name: "sicounter",
|
||||
Data: metricdata.Sum[int64]{
|
||||
DataPoints: []metricdata.DataPoint[int64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Value: 30,
|
||||
},
|
||||
{Attributes: fooBar, Value: 30},
|
||||
},
|
||||
Temporality: temporality,
|
||||
IsMonotonic: true,
|
||||
@ -1174,18 +1157,15 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
|
||||
ctr.Add(context.Background(), 10, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
ctr.Add(context.Background(), 20, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
ctr.Add(context.Background(), 10, withV1)
|
||||
ctr.Add(context.Background(), 20, withV2)
|
||||
return nil
|
||||
},
|
||||
wantMetric: metricdata.Metrics{
|
||||
Name: "siupdowncounter",
|
||||
Data: metricdata.Sum[int64]{
|
||||
DataPoints: []metricdata.DataPoint[int64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Value: 30,
|
||||
},
|
||||
{Attributes: fooBar, Value: 30},
|
||||
},
|
||||
Temporality: temporality,
|
||||
IsMonotonic: false,
|
||||
@ -1200,8 +1180,8 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
return err
|
||||
}
|
||||
|
||||
ctr.Record(context.Background(), 1, attribute.String("foo", "bar"), attribute.Int("version", 1))
|
||||
ctr.Record(context.Background(), 2, attribute.String("foo", "bar"), attribute.Int("version", 2))
|
||||
ctr.Record(context.Background(), 1, withV1)
|
||||
ctr.Record(context.Background(), 2, withV2)
|
||||
return nil
|
||||
},
|
||||
wantMetric: metricdata.Metrics{
|
||||
@ -1209,7 +1189,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
|
||||
Data: metricdata.Histogram[int64]{
|
||||
DataPoints: []metricdata.HistogramDataPoint[int64]{
|
||||
{
|
||||
Attributes: attribute.NewSet(attribute.String("foo", "bar")),
|
||||
Attributes: fooBar,
|
||||
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
|
||||
BucketCounts: []uint64{0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
Count: 2,
|
||||
@ -1296,7 +1276,7 @@ func TestObservableExample(t *testing.T) {
|
||||
_, err := meter.Int64ObservableCounter(instName, instrument.WithInt64Callback(
|
||||
func(_ context.Context, o instrument.Int64Observer) error {
|
||||
for attrSet, val := range observations {
|
||||
o.Observe(val, attrSet.ToSlice()...)
|
||||
o.Observe(val, instrument.WithAttributeSet(attrSet))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user