You've already forked opentelemetry-go
							
							
				mirror of
				https://github.com/open-telemetry/opentelemetry-go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	Add the internal x package to otlptracehttp (#7476)
				
					
				
			Part of #7006 - Generate the base `x` package content - Add a README.md describing the observability feature - Add the observability feature
This commit is contained in:
		| @@ -23,3 +23,6 @@ package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/ot | ||||
| //go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/collector.go.tmpl "--data={}" --out=otlptracetest/collector.go | ||||
| //go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/data.go.tmpl "--data={}" --out=otlptracetest/data.go | ||||
| //go:generate gotmpl --body=../../../../../internal/shared/otlp/otlptrace/otlptracetest/otlptest.go.tmpl "--data={}" --out=otlptracetest/otlptest.go | ||||
|  | ||||
| //go:generate gotmpl --body=../../../../../internal/shared/x/x.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp\" }" --out=x/x.go | ||||
| //go:generate gotmpl --body=../../../../../internal/shared/x/x_test.go.tmpl "--data={}" --out=x/x_test.go | ||||
|   | ||||
							
								
								
									
										22
									
								
								exporters/otlp/otlptrace/otlptracehttp/internal/x/observ.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								exporters/otlp/otlptrace/otlptracehttp/internal/x/observ.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
|  | ||||
| package x // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/x" | ||||
|  | ||||
| import "strings" | ||||
|  | ||||
| // Observability is an experimental feature flag that determines if exporter | ||||
| // observability metrics are enabled. | ||||
| // | ||||
| // To enable this feature set the OTEL_GO_X_OBSERVABILITY environment variable | ||||
| // to the case-insensitive string value of "true" (i.e. "True" and "TRUE" | ||||
| // will also enable this). | ||||
| var Observability = newFeature( | ||||
| 	[]string{"OBSERVABILITY"}, | ||||
| 	func(v string) (string, bool) { | ||||
| 		if strings.EqualFold(v, "true") { | ||||
| 			return v, true | ||||
| 		} | ||||
| 		return "", false | ||||
| 	}, | ||||
| ) | ||||
| @@ -0,0 +1,21 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
|  | ||||
| package x | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
|  | ||||
| func TestObservability(t *testing.T) { | ||||
| 	const key = "OTEL_GO_X_OBSERVABILITY" | ||||
| 	require.Contains(t, Observability.Keys(), key) | ||||
|  | ||||
| 	t.Run("100", run(setenv(key, "100"), assertDisabled(Observability))) | ||||
| 	t.Run("true", run(setenv(key, "true"), assertEnabled(Observability, "true"))) | ||||
| 	t.Run("True", run(setenv(key, "True"), assertEnabled(Observability, "True"))) | ||||
| 	t.Run("false", run(setenv(key, "false"), assertDisabled(Observability))) | ||||
| 	t.Run("empty", run(assertDisabled(Observability))) | ||||
| } | ||||
							
								
								
									
										58
									
								
								exporters/otlp/otlptrace/otlptracehttp/internal/x/x.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								exporters/otlp/otlptrace/otlptracehttp/internal/x/x.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| // Code generated by gotmpl. DO NOT MODIFY. | ||||
| // source: internal/shared/x/x.go.tmpl | ||||
|  | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
|  | ||||
| // Package x documents experimental features for [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp]. | ||||
| package x // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/x" | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| // 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 { | ||||
| 	keys  []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_" | ||||
| 	keys := make([]string, 0, len(suffix)) | ||||
| 	for _, s := range suffix { | ||||
| 		keys = append(keys, envKeyRoot+s) | ||||
| 	} | ||||
| 	return Feature[T]{ | ||||
| 		keys:  keys, | ||||
| 		parse: parse, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Keys returns the environment variable keys that can be set to enable the | ||||
| // feature. | ||||
| func (f Feature[T]) Keys() []string { return f.keys } | ||||
|  | ||||
| // 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. | ||||
| 	for _, key := range f.keys { | ||||
| 		vRaw := os.Getenv(key) | ||||
| 		if vRaw != "" { | ||||
| 			return f.parse(vRaw) | ||||
| 		} | ||||
| 	} | ||||
| 	return v, ok | ||||
| } | ||||
|  | ||||
| // Enabled reports whether the feature is enabled. | ||||
| func (f Feature[T]) Enabled() bool { | ||||
| 	_, ok := f.Lookup() | ||||
| 	return ok | ||||
| } | ||||
							
								
								
									
										75
									
								
								exporters/otlp/otlptrace/otlptracehttp/internal/x/x_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								exporters/otlp/otlptrace/otlptracehttp/internal/x/x_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| // Code generated by gotmpl. DO NOT MODIFY. | ||||
| // source: internal/shared/x/x_text.go.tmpl | ||||
|  | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
|  | ||||
| package x | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	mockKey  = "OTEL_GO_X_MOCK_FEATURE" | ||||
| 	mockKey2 = "OTEL_GO_X_MOCK_FEATURE2" | ||||
| ) | ||||
|  | ||||
| var mockFeature = newFeature([]string{"MOCK_FEATURE", "MOCK_FEATURE2"}, func(v string) (string, bool) { | ||||
| 	if strings.EqualFold(v, "true") { | ||||
| 		return v, true | ||||
| 	} | ||||
| 	return "", false | ||||
| }) | ||||
|  | ||||
| func TestFeature(t *testing.T) { | ||||
| 	require.Contains(t, mockFeature.Keys(), mockKey) | ||||
| 	require.Contains(t, mockFeature.Keys(), mockKey2) | ||||
|  | ||||
| 	t.Run("100", run(setenv(mockKey, "100"), assertDisabled(mockFeature))) | ||||
| 	t.Run("true", run(setenv(mockKey, "true"), assertEnabled(mockFeature, "true"))) | ||||
| 	t.Run("True", run(setenv(mockKey, "True"), assertEnabled(mockFeature, "True"))) | ||||
| 	t.Run("false", run(setenv(mockKey, "false"), assertDisabled(mockFeature))) | ||||
| 	t.Run("empty", run(assertDisabled(mockFeature))) | ||||
| } | ||||
|  | ||||
| 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) { //nolint:unparam // This is a reusable test utility function. | ||||
| 	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") | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user