Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions propagators/envcar/carrier.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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]
}
})
}
Expand Down Expand Up @@ -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))
Expand Down
20 changes: 17 additions & 3 deletions propagators/envcar/carrier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -134,21 +147,22 @@ 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) {
c := envcar.Carrier{} // SetEnvFunc is nil
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"))
Expand Down
Loading