Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
478ba68
feat: add environment carrier
Joibel Jan 21, 2026
aa72967
test: add examples
Joibel Jan 30, 2026
f58fdd1
Merge branch 'main' into envcar
Joibel Jan 30, 2026
02deedc
Update CODEOWNERS
Joibel Jan 30, 2026
edad481
Update CHANGELOG.md
Joibel Jan 30, 2026
166eab6
chore: remove error return and add test
Joibel Jan 30, 2026
1b54363
Update propagators/envcar/carrier.go
Joibel Feb 2, 2026
7533bf3
Merge branch 'main' into envcar
Joibel Feb 3, 2026
9ea9d63
feat: persistent values from carrier
Joibel Feb 3, 2026
f819347
chore: various code review feedback items
Joibel Feb 25, 2026
35a4228
Merge branch 'main' into envcar
Joibel Feb 25, 2026
bd65603
chore: move changelog entry
Joibel Feb 25, 2026
c29d61e
docs: improve godocs
Joibel Feb 25, 2026
a27cbe6
chore: go.sum
Joibel Feb 25, 2026
feb0dc2
Update propagators/envcar/carrier.go
Joibel Feb 26, 2026
311ae22
Update propagators/envcar/carrier.go
Joibel Feb 26, 2026
ba6e72b
Update propagators/envcar/carrier.go
Joibel Feb 26, 2026
2025db5
Update propagators/envcar/carrier.go
Joibel Feb 26, 2026
4a8eead
Update propagators/envcar/carrier.go
Joibel Feb 26, 2026
c667885
chore: fix test
Joibel Mar 3, 2026
e4a9322
Merge remote-tracking branch 'upstream/main' into envcar
Joibel Mar 3, 2026
1e24f82
feat: use underscores for non-A-Z
Joibel Mar 4, 2026
ab56ec0
chore: linter fix
Joibel Mar 4, 2026
4556ab9
chore: fix up the comments and linter problems
Joibel Mar 4, 2026
1dca629
Merge branch 'main' into envcar
pellared Mar 4, 2026
d776978
Fix CHANGELOG
pellared Mar 4, 2026
1f25da6
Merge branch 'main' into envcar
pellared Mar 4, 2026
2e78d6b
docs: small updates from code review
Joibel Mar 4, 2026
f3bac0d
test: new keys and get test
Joibel Mar 5, 2026
bb38d84
Merge branch 'main' into envcar
Joibel Mar 5, 2026
517f352
Update propagators/envcar/carrier_test.go
Joibel Mar 5, 2026
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 CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ processors/minsev @open-te
propagators/autoprop/ @open-telemetry/go-approvers @MrAlias
propagators/aws/ @open-telemetry/go-approvers @akats7
propagators/b3/ @open-telemetry/go-approvers @pellared
propagators/envcar @open-telemetry/go-approvers @Joibel
Comment thread
Joibel marked this conversation as resolved.
Outdated
propagators/jaeger/ @open-telemetry/go-approvers @yurishkuro
propagators/opencensus/ @open-telemetry/go-approvers @dashpole
propagators/ot/ @open-telemetry/go-approvers @pellared
Expand Down
111 changes: 111 additions & 0 deletions propagators/envcar/carrier_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package envcar_test

import (
"context"
"fmt"
"os"
"os/exec"

"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"

"go.opentelemetry.io/contrib/propagators/envcar"
)

// This example is a go program where the environment variables are carrying the
// trace information, and we're going to pick them up into our context.
func ExampleCarrier_extractFromParent() {
// Simulate environment variables set by a parent process.
// In practice, these would already be set when this process starts.
_ = os.Setenv("TRACEPARENT", "00-0102030405060708090a0b0c0d0e0f10-0102030405060708-01")

// Create a carrier to read trace context from environment variables.
carrier := envcar.Carrier{}

// Extract trace context that was propagated by the parent process.
prop := propagation.TraceContext{}
ctx := prop.Extract(context.Background(), carrier)

// The context now contains the span context from the parent.
spanCtx := trace.SpanContextFromContext(ctx)
fmt.Printf("Trace ID: %s\n", spanCtx.TraceID())
fmt.Printf("Span ID: %s\n", spanCtx.SpanID())
fmt.Printf("Sampled: %t\n", spanCtx.IsSampled())
// Output:
// Trace ID: 0102030405060708090a0b0c0d0e0f10
// Span ID: 0102030405060708
// Sampled: true
}

// This example is a go program where we have a trace and we'd like to inject it
// in our current environment variables.
Comment thread
pellared marked this conversation as resolved.
Outdated
func ExampleCarrier_injectWithSetenv() {
// Create a span context with a known trace ID.
traceID := trace.TraceID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}
spanID := trace.SpanID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
spanCtx := trace.NewSpanContext(trace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
})
ctx := trace.ContextWithSpanContext(context.Background(), spanCtx)

// Create a carrier that sets environment variables in the current process.
// This is useful when about to exec() or when child processes will
// inherit the current environment.
carrier := envcar.Carrier{
SetEnvFunc: os.Setenv,
}

// Inject trace context into the current process's environment.
prop := propagation.TraceContext{}
prop.Inject(ctx, carrier)

// The environment variable is now set in the current process.
fmt.Println(os.Getenv("TRACEPARENT"))
// Output: 00-0102030405060708090a0b0c0d0e0f10-0102030405060708-01
}

// This example is a go program where we have a trace and we'd like to inject it
// into a command we're going to run.
func ExampleCarrier_childProcess() {
// Create a span context with a known trace ID.
traceID := trace.TraceID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}
spanID := trace.SpanID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
spanCtx := trace.NewSpanContext(trace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
})
ctx := trace.ContextWithSpanContext(context.Background(), spanCtx)

// Prepare a command that prints the TRACEPARENT environment variable.
cmd := exec.Command("printenv", "TRACEPARENT")
cmd.Env = os.Environ()

// Create a carrier that injects trace context into the child
// process's environment rather than the current process's.
carrier := envcar.Carrier{
SetEnvFunc: func(key, value string) error {
cmd.Env = append(cmd.Env, key+"="+value)
return nil
},
}

// Inject trace context into the child's environment.
prop := propagation.TraceContext{}
prop.Inject(ctx, carrier)

// The child process now has trace context in its environment,
// independent of the parent process's environment variables.
out, err := cmd.Output()
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Print(string(out))
// Output: 00-0102030405060708090a0b0c0d0e0f10-0102030405060708-01
}
5 changes: 4 additions & 1 deletion propagators/envcar/carrier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func TestCarrierKeys(t *testing.T) {
assert.Contains(t, keys, "traceparent")
}

func TestCarrierSetNilFunc(t *testing.T) {
func TestCarrierSetNilFunc(_ *testing.T) {
c := envcar.Carrier{} // SetEnvFunc is nil
c.Set("key", "value") // should not panic, just no-op
}
Expand All @@ -155,13 +155,16 @@ func TestCarrierGetCaseInsensitive(t *testing.T) {

func TestCarrierSetUppercasesKey(t *testing.T) {
var gotKey string
var gotValue string
c := envcar.Carrier{
SetEnvFunc: func(key, value string) error {
gotKey = key
gotValue = value
return nil
},
}

c.Set("traceparent", "value")
assert.Equal(t, "TRACEPARENT", gotKey)
assert.Equal(t, "value", gotValue)
}
3 changes: 3 additions & 0 deletions propagators/envcar/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ require (
require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
15 changes: 14 additions & 1 deletion propagators/envcar/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
Expand All @@ -8,8 +9,19 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
Expand All @@ -20,7 +32,8 @@ go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=