Skip to content

Commit bf6a7e1

Browse files
mrasuMrAlias
andauthored
otlpmetricgrpc: Keep metadata for gRPC in context (open-telemetry#5892)
When using otlpmetricgrpc, we can inject metadata dynamically with `metadata.AppendToOutgoingContext`. However when specifying headers with `WithHeaders`, it becomes impossible to add additional metadata. For example, the code below sends additional metadata in the header ```go exp := otlpmetricgrpc.New(context.Background()) ctx := context.Background() ctx = metadata.AppendToOutgoingContext(ctx, "dynamic-key", "value") exp.Export(ctx, &metricdata.ResourceMetrics{})) ``` But when using `WithHeader` like below, no additional metadata will be sent ```go exp := otlpmetricgrpc.New(context.Background(), otlpmetricgrpc.WithHeaders("custom-key", "value")) ctx := context.Background() ctx = metadata.AppendToOutgoingContext(ctx, "dynamic-key", "value") exp.Export(ctx, &metricdata.ResourceMetrics{})) ``` To eliminate this inconsistency, keep the metadata in the context and send them in the header. --------- Co-authored-by: Tyler Yahn <[email protected]>
1 parent bd88af9 commit bf6a7e1

File tree

3 files changed

+15
-1
lines changed

3 files changed

+15
-1
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
2222

2323
- Global MeterProvider registration unwraps global instrument Observers, the undocumented Unwrap() methods are now private. (#5881)
2424

25+
### Changed
26+
27+
- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` now keeps the metadata already present in the context when `WithHeaders` is used. (#5892)
28+
2529
<!-- Released section -->
2630
<!-- Don't change this section unless doing release -->
2731

exporters/otlp/otlpmetric/otlpmetricgrpc/client.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,12 @@ func (c *client) exportContext(parent context.Context) (context.Context, context
155155
}
156156

157157
if c.metadata.Len() > 0 {
158-
ctx = metadata.NewOutgoingContext(ctx, c.metadata)
158+
md := c.metadata
159+
if outMD, ok := metadata.FromOutgoingContext(ctx); ok {
160+
md = metadata.Join(md, outMD)
161+
}
162+
163+
ctx = metadata.NewOutgoingContext(ctx, md)
159164
}
160165

161166
return ctx, cancel

exporters/otlp/otlpmetric/otlpmetricgrpc/client_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"google.golang.org/genproto/googleapis/rpc/errdetails"
1414
"google.golang.org/grpc"
1515
"google.golang.org/grpc/codes"
16+
"google.golang.org/grpc/metadata"
1617
"google.golang.org/grpc/status"
1718
"google.golang.org/protobuf/types/known/durationpb"
1819

@@ -207,14 +208,18 @@ func TestConfig(t *testing.T) {
207208
headers := map[string]string{key: "custom-value"}
208209
exp, coll := factoryFunc(nil, WithHeaders(headers))
209210
t.Cleanup(coll.Shutdown)
211+
210212
ctx := context.Background()
213+
additionalKey := "additional-custom-header"
214+
ctx = metadata.AppendToOutgoingContext(ctx, additionalKey, "additional-value")
211215
require.NoError(t, exp.Export(ctx, &metricdata.ResourceMetrics{}))
212216
// Ensure everything is flushed.
213217
require.NoError(t, exp.Shutdown(ctx))
214218

215219
got := coll.Headers()
216220
require.Regexp(t, "OTel Go OTLP over gRPC metrics exporter/[01]\\..*", got)
217221
require.Contains(t, got, key)
222+
require.Contains(t, got, additionalKey)
218223
assert.Equal(t, []string{headers[key]}, got[key])
219224
})
220225

0 commit comments

Comments
 (0)