-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the `x` package to handle experimental feature flagging within the go.opentelemetry.io/otel/sdk module.
- Loading branch information
Showing
3 changed files
with
172 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Experimental Features | ||
|
||
The SDK contains features that have not yet stabilized in the OpenTelemetry specification. | ||
These features are added to the OpenTelemetry Go SDK prior to stabilization in the specification so that users can start experimenting with them and provide feedback. | ||
|
||
These feature may change in backwards incompatible ways as feedback is applied. | ||
See the [Compatibility and Stability](#compatibility-and-stability) section for more information. | ||
|
||
## Features | ||
|
||
- [Resource](#resource) | ||
|
||
### Resource | ||
|
||
[OpenTelemetry resource semantic conventions] include many attribute definitions that are defined as experimental. | ||
To have experimental semantic conventions be added by [resource detectors] set the `OTEL_GO_X_RESOURCE` environment variable. | ||
The value set must be the case-insensitive string of `"true"` to enable the feature. | ||
All other values are ignored. | ||
|
||
<!-- TODO: document what attributes are added by which detector --> | ||
|
||
[OpenTelemetry resource semantic conventions]: https://opentelemetry.io/docs/specs/semconv/resource/ | ||
[resource detectors]: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/resource#Detector | ||
|
||
#### Examples | ||
|
||
Enable experimental resource semantic conventions. | ||
|
||
```console | ||
export OTEL_GO_X_RESOURCE=true | ||
``` | ||
|
||
Disable experimental resource semantic conventions. | ||
|
||
```console | ||
unset OTEL_GO_X_RESOURCE | ||
``` | ||
|
||
## Compatibility and Stability | ||
|
||
Experimental features do not fall within the scope of the OpenTelemetry Go versioning and stability [policy](../../../../VERSIONING.md). | ||
These features may be removed or modified in successive version releases, including patch versions. | ||
|
||
When an experimental feature is promoted to a stable feature, a migration path will be included in the changelog entry of the release. | ||
There is no guarantee that any environment variable feature flags that enabled the experimental feature will be supported by the stable version. | ||
If they are supported, they may be accompanied with a deprecation notice stating a timeline for the removal of that support. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// Package x contains support for OTel SDK experimental features. | ||
// | ||
// This package should only be used for features defined in the specification. | ||
// It should not be used for experiments or new project ideas. | ||
package x // import "go.opentelemetry.io/otel/sdk/internal/x" | ||
|
||
import ( | ||
"os" | ||
"strings" | ||
) | ||
|
||
// Resource is an experimental feature flag that defines if resource detectors | ||
// should be included experimental semantic conventions. | ||
// | ||
// To enable this feature set the OTEL_GO_X_RESOURCE environment variable | ||
// to the case-insensitive string value of "true" (i.e. "True" and "TRUE" | ||
// will also enable this). | ||
var Resource = newFeature("RESOURCE", func(v string) (string, bool) { | ||
if strings.ToLower(v) == "true" { | ||
return v, true | ||
} | ||
return "", false | ||
}) | ||
|
||
// Feature is an experimental feature control flag. It provides a uniform way | ||
// to interact with these feature flags and parse their values. | ||
type Feature[T any] struct { | ||
key string | ||
parse func(v string) (T, bool) | ||
} | ||
|
||
func newFeature[T any](suffix string, parse func(string) (T, bool)) Feature[T] { | ||
const envKeyRoot = "OTEL_GO_X_" | ||
return Feature[T]{ | ||
key: envKeyRoot + suffix, | ||
parse: parse, | ||
} | ||
} | ||
|
||
// Key returns the environment variable key that needs to be set to enable the | ||
// feature. | ||
func (f Feature[T]) Key() string { return f.key } | ||
|
||
// Lookup returns the user configured value for the feature and true if the | ||
// user has enabled the feature. Otherwise, if the feature is not enabled, a | ||
// zero-value and false are returned. | ||
func (f Feature[T]) Lookup() (v T, ok bool) { | ||
// https://github.com/open-telemetry/opentelemetry-specification/blob/62effed618589a0bec416a87e559c0a9d96289bb/specification/configuration/sdk-environment-variables.md#parsing-empty-value | ||
// | ||
// > The SDK MUST interpret an empty value of an environment variable the | ||
// > same way as when the variable is unset. | ||
vRaw := os.Getenv(f.key) | ||
if vRaw == "" { | ||
return v, ok | ||
} | ||
return f.parse(vRaw) | ||
} | ||
|
||
// Enabled returns if the feature is enabled. | ||
func (f Feature[T]) Enabled() bool { | ||
_, ok := f.Lookup() | ||
return ok | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package x | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestExemplars(t *testing.T) { | ||
const key = "OTEL_GO_X_RESOURCE" | ||
require.Equal(t, key, Resource.Key()) | ||
|
||
t.Run("true", run(setenv(key, "true"), assertEnabled(Resource, "true"))) | ||
t.Run("True", run(setenv(key, "True"), assertEnabled(Resource, "True"))) | ||
t.Run("TRUE", run(setenv(key, "TRUE"), assertEnabled(Resource, "TRUE"))) | ||
t.Run("false", run(setenv(key, "false"), assertDisabled(Resource))) | ||
t.Run("1", run(setenv(key, "1"), assertDisabled(Resource))) | ||
t.Run("empty", run(assertDisabled(Resource))) | ||
} | ||
|
||
func run(steps ...func(*testing.T)) func(*testing.T) { | ||
return func(t *testing.T) { | ||
t.Helper() | ||
for _, step := range steps { | ||
step(t) | ||
} | ||
} | ||
} | ||
|
||
func setenv(k, v string) func(t *testing.T) { | ||
return func(t *testing.T) { t.Setenv(k, v) } | ||
} | ||
|
||
func assertEnabled[T any](f Feature[T], want T) func(*testing.T) { | ||
return func(t *testing.T) { | ||
t.Helper() | ||
assert.True(t, f.Enabled(), "not enabled") | ||
|
||
v, ok := f.Lookup() | ||
assert.True(t, ok, "Lookup state") | ||
assert.Equal(t, want, v, "Lookup value") | ||
} | ||
} | ||
|
||
func assertDisabled[T any](f Feature[T]) func(*testing.T) { | ||
var zero T | ||
return func(t *testing.T) { | ||
t.Helper() | ||
|
||
assert.False(t, f.Enabled(), "enabled") | ||
|
||
v, ok := f.Lookup() | ||
assert.False(t, ok, "Lookup state") | ||
assert.Equal(t, zero, v, "Lookup value") | ||
} | ||
} |