Skip to content

Commit

Permalink
enable exemplars by default
Browse files Browse the repository at this point in the history
  • Loading branch information
dashpole committed Sep 4, 2024
1 parent 1b8f785 commit fc1f3ba
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 93 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Changed

- Enable exemplars by default in `go.opentelemetry.io/otel/sdk/metric`. Exemplars can be disabled by setting `OTEL_METRICS_EXEMPLAR_FILTER=always_off` (#5778)

### Fixed

- Fix memory leak in the global `MeterProvider` when identical instruments are repeatedly created. (#5754)
Expand Down
2 changes: 1 addition & 1 deletion sdk/internal/x/x_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/require"
)

func TestExemplars(t *testing.T) {
func TestResource(t *testing.T) {
const key = "OTEL_GO_X_RESOURCE"
require.Equal(t, key, Resource.Key())

Expand Down
4 changes: 0 additions & 4 deletions sdk/metric/exemplar.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"slices"

"go.opentelemetry.io/otel/sdk/metric/internal/exemplar"
"go.opentelemetry.io/otel/sdk/metric/internal/x"
)

// reservoirFunc returns the appropriately configured exemplar reservoir
Expand All @@ -20,9 +19,6 @@ import (
// feature is enabled and the OTEL_METRICS_EXEMPLAR_FILTER environment variable
// is not set to always_off.
func reservoirFunc[N int64 | float64](agg Aggregation) func() exemplar.FilteredReservoir[N] {
if !x.Exemplars.Enabled() {
return nil
}
// https://github.com/open-telemetry/opentelemetry-specification/blob/d4b241f451674e8f611bb589477680341006ad2b/specification/configuration/sdk-environment-variables.md#exemplar
const filterEnvKey = "OTEL_METRICS_EXEMPLAR_FILTER"

Expand Down
46 changes: 15 additions & 31 deletions sdk/metric/internal/x/x.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,23 @@ package x // import "go.opentelemetry.io/otel/sdk/metric/internal/x"
import (
"os"
"strconv"
"strings"
)

var (
// Exemplars is an experimental feature flag that defines if exemplars
// should be recorded for metric data-points.
//
// To enable this feature set the OTEL_GO_X_EXEMPLAR environment variable
// to the case-insensitive string value of "true" (i.e. "True" and "TRUE"
// will also enable this).
Exemplars = newFeature("EXEMPLAR", func(v string) (string, bool) {
if strings.ToLower(v) == "true" {
return v, true
}
return "", false
})

// CardinalityLimit is an experimental feature flag that defines if
// cardinality limits should be applied to the recorded metric data-points.
//
// To enable this feature set the OTEL_GO_X_CARDINALITY_LIMIT environment
// variable to the integer limit value you want to use.
//
// Setting OTEL_GO_X_CARDINALITY_LIMIT to a value less than or equal to 0
// will disable the cardinality limits.
CardinalityLimit = newFeature("CARDINALITY_LIMIT", func(v string) (int, bool) {
n, err := strconv.Atoi(v)
if err != nil {
return 0, false
}
return n, true
})
)
// CardinalityLimit is an experimental feature flag that defines if
// cardinality limits should be applied to the recorded metric data-points.
//
// To enable this feature set the OTEL_GO_X_CARDINALITY_LIMIT environment
// variable to the integer limit value you want to use.
//
// Setting OTEL_GO_X_CARDINALITY_LIMIT to a value less than or equal to 0
// will disable the cardinality limits.
var CardinalityLimit = newFeature("CARDINALITY_LIMIT", func(v string) (int, bool) {
n, err := strconv.Atoi(v)
if err != nil {
return 0, false
}
return n, true
})

// Feature is an experimental feature control flag. It provides a uniform way
// to interact with these feature flags and parse their values.
Expand Down
12 changes: 0 additions & 12 deletions sdk/metric/internal/x/x_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,6 @@ import (
"github.com/stretchr/testify/require"
)

func TestExemplars(t *testing.T) {
const key = "OTEL_GO_X_EXEMPLAR"
require.Equal(t, key, Exemplars.Key())

t.Run("true", run(setenv(key, "true"), assertEnabled(Exemplars, "true")))
t.Run("True", run(setenv(key, "True"), assertEnabled(Exemplars, "True")))
t.Run("TRUE", run(setenv(key, "TRUE"), assertEnabled(Exemplars, "TRUE")))
t.Run("false", run(setenv(key, "false"), assertDisabled(Exemplars)))
t.Run("1", run(setenv(key, "1"), assertDisabled(Exemplars)))
t.Run("empty", run(assertDisabled(Exemplars)))
}

func TestCardinalityLimit(t *testing.T) {
const key = "OTEL_GO_X_CARDINALITY_LIMIT"
require.Equal(t, key, CardinalityLimit.Key())
Expand Down
77 changes: 32 additions & 45 deletions sdk/metric/pipeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,59 +448,46 @@ func TestExemplars(t *testing.T) {
})
sampled := trace.ContextWithSpanContext(context.Background(), sc)

t.Run("OTEL_GO_X_EXEMPLAR=true", func(t *testing.T) {
t.Setenv("OTEL_GO_X_EXEMPLAR", "true")

t.Run("Default", func(t *testing.T) {
m, r := setup("default")
measure(ctx, m)
check(t, r, 0, 0, 0)

measure(sampled, m)
check(t, r, nCPU, 1, 20)
})

t.Run("Invalid", func(t *testing.T) {
t.Setenv("OTEL_METRICS_EXEMPLAR_FILTER", "unrecognized")
m, r := setup("default")
measure(ctx, m)
check(t, r, 0, 0, 0)

measure(sampled, m)
check(t, r, nCPU, 1, 20)
})

t.Run("always_on", func(t *testing.T) {
t.Setenv("OTEL_METRICS_EXEMPLAR_FILTER", "always_on")
m, r := setup("always_on")
measure(ctx, m)
check(t, r, nCPU, 1, 20)
})
t.Run("Default", func(t *testing.T) {
m, r := setup("default")
measure(ctx, m)
check(t, r, 0, 0, 0)

t.Run("always_off", func(t *testing.T) {
t.Setenv("OTEL_METRICS_EXEMPLAR_FILTER", "always_off")
m, r := setup("always_off")
measure(ctx, m)
check(t, r, 0, 0, 0)
})
measure(sampled, m)
check(t, r, nCPU, 1, 20)
})

t.Run("trace_based", func(t *testing.T) {
t.Setenv("OTEL_METRICS_EXEMPLAR_FILTER", "trace_based")
m, r := setup("trace_based")
measure(ctx, m)
check(t, r, 0, 0, 0)
t.Run("Invalid", func(t *testing.T) {
t.Setenv("OTEL_METRICS_EXEMPLAR_FILTER", "unrecognized")
m, r := setup("default")
measure(ctx, m)
check(t, r, 0, 0, 0)

measure(sampled, m)
check(t, r, nCPU, 1, 20)
})
measure(sampled, m)
check(t, r, nCPU, 1, 20)
})

t.Run("OTEL_GO_X_EXEMPLAR=false", func(t *testing.T) {
t.Setenv("OTEL_GO_X_EXEMPLAR", "false")

t.Run("always_on", func(t *testing.T) {
t.Setenv("OTEL_METRICS_EXEMPLAR_FILTER", "always_on")
m, r := setup("always_on")
measure(ctx, m)
check(t, r, nCPU, 1, 20)
})

t.Run("always_off", func(t *testing.T) {
t.Setenv("OTEL_METRICS_EXEMPLAR_FILTER", "always_off")
m, r := setup("always_off")
measure(ctx, m)
check(t, r, 0, 0, 0)
})

t.Run("trace_based", func(t *testing.T) {
t.Setenv("OTEL_METRICS_EXEMPLAR_FILTER", "trace_based")
m, r := setup("trace_based")
measure(ctx, m)
check(t, r, 0, 0, 0)

measure(sampled, m)
check(t, r, nCPU, 1, 20)
})
}

0 comments on commit fc1f3ba

Please sign in to comment.