diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b180174161..8e07dd2aaa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Changed - Prepend `_` to the normalized environment variable name when the key starts with a digit in `go.opentelemetry.io/contrib/propagators/envcar`, ensuring POSIX compliance. (#8678) +- Normalize cached environment variable names in `go.opentelemetry.io/contrib/propagators/envcar`, aligning `Carrier.Keys` output with the carrier's normalized key format. (#8761) ### Fixed diff --git a/propagators/envcar/carrier.go b/propagators/envcar/carrier.go index eee90de8469..9e6206b3f43 100644 --- a/propagators/envcar/carrier.go +++ b/propagators/envcar/carrier.go @@ -12,7 +12,7 @@ import ( ) // Carrier is a TextMapCarrier that uses the environment variables as a -// storage medium for propagated key-value pairs. The keys are normalised +// storage medium for propagated key-value pairs. The keys are normalized // before being used to access the environment variables. // This is useful for propagating values that are set in the environment // and need to be accessed by different processes or services. @@ -43,7 +43,8 @@ func (c *Carrier) fetch() { c.values = make(map[string]string, len(environ)) for _, kv := range environ { kvPair := strings.SplitN(kv, "=", 2) - c.values[kvPair[0]] = kvPair[1] + key := normalize(kvPair[0]) + c.values[key] = kvPair[1] } }) } @@ -74,8 +75,7 @@ func (c *Carrier) Set(key, value string) { // The first call to [Carrier.Get] or [Carrier.Keys] for a // given Carrier will read and store the values from the // environment and all future reads will be from that store. -// Keys are returned as is, without any normalization, but -// this behavior is subject to change. +// The keys are returned in their normalized form. func (c *Carrier) Keys() []string { c.fetch() keys := make([]string, 0, len(c.values)) diff --git a/propagators/envcar/carrier_test.go b/propagators/envcar/carrier_test.go index e2ba9a6cf7e..c37e2a7519f 100644 --- a/propagators/envcar/carrier_test.go +++ b/propagators/envcar/carrier_test.go @@ -61,6 +61,19 @@ func TestExtractValidTraceContextEnvCarrier(t *testing.T) { Remote: true, }), }, + { + name: "lowercase env names", + envs: map[string]string{ + "traceparent": "00-000000000000007b00000000000001c8-000000000000007b-00", + "tracestate": stateStr, + }, + want: trace.NewSpanContext(trace.SpanContextConfig{ + TraceID: traceID, + SpanID: spanID, + TraceState: state, + Remote: true, + }), + }, } for _, tc := range tests { @@ -134,12 +147,13 @@ func TestInjectTraceContextEnvCarrier(t *testing.T) { } func TestCarrierKeys(t *testing.T) { - t.Setenv("TRACEPARENT", "value") + t.Setenv("traceparent", "value") c := envcar.Carrier{} keys := c.Keys() assert.Contains(t, keys, "TRACEPARENT") + assert.NotContains(t, keys, "traceparent") } func TestCarrierSetNilFunc(_ *testing.T) { @@ -147,8 +161,8 @@ func TestCarrierSetNilFunc(_ *testing.T) { c.Set("key", "value") // should not panic, just no-op } -func TestCarrierGetCaseInsensitive(t *testing.T) { - t.Setenv("TRACEPARENT", "myvalue") +func TestCarrierGetNormalizesKey(t *testing.T) { + t.Setenv("traceparent", "myvalue") c := envcar.Carrier{} assert.Equal(t, "myvalue", c.Get("traceparent"))