You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-11-29 23:07:45 +02:00
Allow configuring the exemplar filter on the metrics SDK (#5850)
Part of https://github.com/open-telemetry/opentelemetry-go/issues/5249 ### Spec https://opentelemetry.io/docs/specs/otel/metrics/sdk/#exemplarfilter > The ExemplarFilter configuration MUST allow users to select between one of the built-in ExemplarFilters. While ExemplarFilter determines which measurements are eligible for becoming an Exemplar, the ExemplarReservoir makes the final decision if a measurement becomes an exemplar and is stored. > The ExemplarFilter SHOULD be a configuration parameter of a MeterProvider for an SDK. The default value SHOULD be TraceBased. The filter configuration SHOULD follow the [environment variable specification](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exemplar). > An OpenTelemetry SDK MUST support the following filters: > * [AlwaysOn](https://opentelemetry.io/docs/specs/otel/metrics/sdk/#alwayson) > * [AlwaysOff](https://opentelemetry.io/docs/specs/otel/metrics/sdk/#alwaysoff) > * [TraceBased](https://opentelemetry.io/docs/specs/otel/metrics/sdk/#tracebased) ### Changes * adds exemplar.AlwaysOffFilter, which is one of the required filters from the SDK: https://opentelemetry.io/docs/specs/otel/metrics/sdk/#alwaysoff * adds `metric.WithExemplarFilter` as an option for the metrics SDK. * moves handling of `OTEL_METRICS_EXEMPLAR_FILTER` to the same location as config handling to make code easier to navigate. dropReservoir can actually be removed, but I plan to do that in a follow-up refactor, since it will be a large diff. --------- Co-authored-by: Damien Mathieu <42@dmathieu.com> Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com> Co-authored-by: Chester Cheung <cheung.zhy.csu@gmail.com>
This commit is contained in:
@@ -23,6 +23,7 @@ import (
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
"go.opentelemetry.io/otel/sdk/metric/exemplar"
|
||||
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
||||
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
@@ -39,7 +40,7 @@ func testSumAggregateOutput(dest *metricdata.Aggregation) int {
|
||||
}
|
||||
|
||||
func TestNewPipeline(t *testing.T) {
|
||||
pipe := newPipeline(nil, nil, nil)
|
||||
pipe := newPipeline(nil, nil, nil, exemplar.AlwaysOffFilter)
|
||||
|
||||
output := metricdata.ResourceMetrics{}
|
||||
err := pipe.produce(context.Background(), &output)
|
||||
@@ -65,7 +66,7 @@ func TestNewPipeline(t *testing.T) {
|
||||
|
||||
func TestPipelineUsesResource(t *testing.T) {
|
||||
res := resource.NewWithAttributes("noSchema", attribute.String("test", "resource"))
|
||||
pipe := newPipeline(res, nil, nil)
|
||||
pipe := newPipeline(res, nil, nil, exemplar.AlwaysOffFilter)
|
||||
|
||||
output := metricdata.ResourceMetrics{}
|
||||
err := pipe.produce(context.Background(), &output)
|
||||
@@ -74,7 +75,7 @@ func TestPipelineUsesResource(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPipelineConcurrentSafe(t *testing.T) {
|
||||
pipe := newPipeline(nil, nil, nil)
|
||||
pipe := newPipeline(nil, nil, nil, exemplar.AlwaysOffFilter)
|
||||
ctx := context.Background()
|
||||
var output metricdata.ResourceMetrics
|
||||
|
||||
@@ -124,13 +125,13 @@ func testDefaultViewImplicit[N int64 | float64]() func(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "NoView",
|
||||
pipe: newPipeline(nil, reader, nil),
|
||||
pipe: newPipeline(nil, reader, nil, exemplar.AlwaysOffFilter),
|
||||
},
|
||||
{
|
||||
name: "NoMatchingView",
|
||||
pipe: newPipeline(nil, reader, []View{
|
||||
NewView(Instrument{Name: "foo"}, Stream{Name: "bar"}),
|
||||
}),
|
||||
}, exemplar.AlwaysOffFilter),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -215,7 +216,7 @@ func TestLogConflictName(t *testing.T) {
|
||||
return instID{Name: tc.existing}
|
||||
})
|
||||
|
||||
i := newInserter[int64](newPipeline(nil, nil, nil), &vc)
|
||||
i := newInserter[int64](newPipeline(nil, nil, nil, exemplar.AlwaysOffFilter), &vc)
|
||||
i.logConflict(instID{Name: tc.name})
|
||||
|
||||
if tc.conflict {
|
||||
@@ -257,7 +258,7 @@ func TestLogConflictSuggestView(t *testing.T) {
|
||||
var vc cache[string, instID]
|
||||
name := strings.ToLower(orig.Name)
|
||||
_ = vc.Lookup(name, func() instID { return orig })
|
||||
i := newInserter[int64](newPipeline(nil, nil, nil), &vc)
|
||||
i := newInserter[int64](newPipeline(nil, nil, nil, exemplar.AlwaysOffFilter), &vc)
|
||||
|
||||
viewSuggestion := func(inst instID, stream string) string {
|
||||
return `"NewView(Instrument{` +
|
||||
@@ -362,7 +363,7 @@ func TestInserterCachedAggregatorNameConflict(t *testing.T) {
|
||||
}
|
||||
|
||||
var vc cache[string, instID]
|
||||
pipe := newPipeline(nil, NewManualReader(), nil)
|
||||
pipe := newPipeline(nil, NewManualReader(), nil, exemplar.AlwaysOffFilter)
|
||||
i := newInserter[int64](pipe, &vc)
|
||||
|
||||
readerAggregation := i.readerDefaultAggregation(kind)
|
||||
|
||||
Reference in New Issue
Block a user