Skip to content

Commit

Permalink
Enable exemplars by default (#5778)
Browse files Browse the repository at this point in the history
Part of #5249.

Addresses
#5249 (comment)

This removes handling of the `OTEL_GO_X_EXEMPLAR` environment variable.

Instead of changing the default for the existing environment variable to
enable it by default, i'm just removing it entirely. Users can still
disable the feature by setting the filter to always_off. Since we will
continue to support that configuration, it seems better to direct users
there, rather than give them a temporary equivalent.
  • Loading branch information
dashpole committed Sep 11, 2024
1 parent 97ee172 commit 6e2f72f
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)

<!-- Released section -->
<!-- Don't change this section unless doing release -->

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 6e2f72f

Please sign in to comment.