Skip to content

Commit 2ded441

Browse files
authored
Set Headers when using gRPC (#1702)
1 parent b91e8c2 commit 2ded441

File tree

5 files changed

+84
-6
lines changed

5 files changed

+84
-6
lines changed

Diff for: pkg/export/otel/common.go

+7
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ type otlpOptions struct {
230230
URLPath string
231231
SkipTLSVerify bool
232232
HTTPHeaders map[string]string
233+
GRPCHeaders map[string]string
233234
}
234235

235236
func (o *otlpOptions) AsMetricHTTP() []otlpmetrichttp.Option {
@@ -261,6 +262,9 @@ func (o *otlpOptions) AsMetricGRPC() []otlpmetricgrpc.Option {
261262
if o.SkipTLSVerify {
262263
opts = append(opts, otlpmetricgrpc.WithTLSCredentials(credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})))
263264
}
265+
if len(o.GRPCHeaders) > 0 {
266+
opts = append(opts, otlpmetricgrpc.WithHeaders(o.GRPCHeaders))
267+
}
264268
return opts
265269
}
266270

@@ -293,6 +297,9 @@ func (o *otlpOptions) AsTraceGRPC() []otlptracegrpc.Option {
293297
if o.SkipTLSVerify {
294298
opts = append(opts, otlptracegrpc.WithTLSCredentials(credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})))
295299
}
300+
if len(o.GRPCHeaders) > 0 {
301+
opts = append(opts, otlptracegrpc.WithHeaders(o.GRPCHeaders))
302+
}
296303
return opts
297304
}
298305

Diff for: pkg/export/otel/grafana.go

+4
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,9 @@ func (cfg *GrafanaOTLP) setupOptions(opt *otlpOptions) {
8686
opt.HTTPHeaders = map[string]string{}
8787
}
8888
opt.HTTPHeaders["Authorization"] = cfg.AuthHeader()
89+
if opt.GRPCHeaders == nil {
90+
opt.GRPCHeaders = map[string]string{}
91+
}
92+
opt.GRPCHeaders["Authorization"] = cfg.AuthHeader()
8993
}
9094
}

Diff for: pkg/export/otel/metrics_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ func TestHTTPMetricsWithGrafanaOptions(t *testing.T) {
9393
// Basic + output of: echo -n 12345:affafafaafkd | gbase64 -w 0
9494
"Authorization": "Basic MTIzNDU6YWZmYWZhZmFhZmtk",
9595
},
96+
GRPCHeaders: map[string]string{
97+
// Basic + output of: echo -n 12345:affafafaafkd | gbase64 -w 0
98+
"Authorization": "Basic MTIzNDU6YWZmYWZhZmFhZmtk",
99+
},
96100
}, &mcfg)
97101
})
98102
mcfg.CommonEndpoint = "https://localhost:3939"
@@ -104,6 +108,10 @@ func TestHTTPMetricsWithGrafanaOptions(t *testing.T) {
104108
// Basic + output of: echo -n 12345:affafafaafkd | gbase64 -w 0
105109
"Authorization": "Basic MTIzNDU6YWZmYWZhZmFhZmtk",
106110
},
111+
GRPCHeaders: map[string]string{
112+
// Basic + output of: echo -n 12345:affafafaafkd | gbase64 -w 0
113+
"Authorization": "Basic MTIzNDU6YWZmYWZhZmFhZmtk",
114+
},
107115
}, &mcfg)
108116
})
109117
}

Diff for: pkg/export/otel/traces.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ func getTracesExporter(ctx context.Context, cfg TracesConfig, ctxInfo *global.Co
349349
Insecure: opts.Insecure,
350350
InsecureSkipVerify: cfg.InsecureSkipVerify,
351351
},
352+
Headers: convertHeaders(opts.GRPCHeaders),
352353
}
353354
set := getTraceSettings(ctxInfo, t)
354355
return factory.CreateTraces(ctx, set, config)
@@ -797,7 +798,7 @@ func getHTTPTracesEndpointOptions(cfg *TracesConfig) (otlpOptions, error) {
797798
}
798799

799800
func getGRPCTracesEndpointOptions(cfg *TracesConfig) (otlpOptions, error) {
800-
opts := otlpOptions{}
801+
opts := otlpOptions{GRPCHeaders: map[string]string{}}
801802
log := tlog().With("transport", "grpc")
802803
murl, _, err := parseTracesEndpoint(cfg)
803804
if err != nil {
@@ -817,6 +818,9 @@ func getGRPCTracesEndpointOptions(cfg *TracesConfig) (otlpOptions, error) {
817818
opts.SkipTLSVerify = true
818819
}
819820

821+
cfg.Grafana.setupOptions(&opts)
822+
maps.Copy(opts.GRPCHeaders, headersFromEnv(envHeaders))
823+
maps.Copy(opts.GRPCHeaders, headersFromEnv(envTracesHeaders))
820824
return opts, nil
821825
}
822826

Diff for: pkg/export/otel/traces_test.go

+60-5
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ func TestHTTPTracesWithGrafanaOptions(t *testing.T) {
9696
// Basic + output of: echo -n 12345:affafafaafkd | gbase64 -w 0
9797
"Authorization": "Basic MTIzNDU6YWZmYWZhZmFhZmtk",
9898
},
99+
GRPCHeaders: map[string]string{
100+
// Basic + output of: echo -n 12345:affafafaafkd | gbase64 -w 0
101+
"Authorization": "Basic MTIzNDU6YWZmYWZhZmFhZmtk",
102+
},
99103
}, &mcfg)
100104
})
101105
mcfg.CommonEndpoint = "https://localhost:3939"
@@ -108,6 +112,10 @@ func TestHTTPTracesWithGrafanaOptions(t *testing.T) {
108112
// Base64 representation of 12345:affafafaafkd
109113
"Authorization": "Basic MTIzNDU6YWZmYWZhZmFhZmtk",
110114
},
115+
GRPCHeaders: map[string]string{
116+
// Base64 representation of 12345:affafafaafkd
117+
"Authorization": "Basic MTIzNDU6YWZmYWZhZmFhZmtk",
118+
},
111119
}, &mcfg)
112120
})
113121
}
@@ -200,7 +208,7 @@ func TestGRPCTracesEndpointOptions(t *testing.T) {
200208
}
201209

202210
t.Run("testing with two endpoints", func(t *testing.T) {
203-
testTracesGRPOptions(t, otlpOptions{Endpoint: "localhost:3232"}, &tcfg)
211+
testTracesGRPCOptions(t, otlpOptions{Endpoint: "localhost:3232", GRPCHeaders: map[string]string{}}, &tcfg)
204212
})
205213

206214
tcfg = TracesConfig{
@@ -209,7 +217,7 @@ func TestGRPCTracesEndpointOptions(t *testing.T) {
209217
}
210218

211219
t.Run("testing with only common endpoint", func(t *testing.T) {
212-
testTracesGRPOptions(t, otlpOptions{Endpoint: "localhost:3131"}, &tcfg)
220+
testTracesGRPCOptions(t, otlpOptions{Endpoint: "localhost:3131", GRPCHeaders: map[string]string{}}, &tcfg)
213221
})
214222

215223
tcfg = TracesConfig{
@@ -218,7 +226,7 @@ func TestGRPCTracesEndpointOptions(t *testing.T) {
218226
Instrumentations: []string{instrumentations.InstrumentationALL},
219227
}
220228
t.Run("testing with insecure endpoint", func(t *testing.T) {
221-
testTracesGRPOptions(t, otlpOptions{Endpoint: "localhost:3232", Insecure: true}, &tcfg)
229+
testTracesGRPCOptions(t, otlpOptions{Endpoint: "localhost:3232", Insecure: true, GRPCHeaders: map[string]string{}}, &tcfg)
222230
})
223231

224232
tcfg = TracesConfig{
@@ -228,11 +236,58 @@ func TestGRPCTracesEndpointOptions(t *testing.T) {
228236
}
229237

230238
t.Run("testing with skip TLS verification", func(t *testing.T) {
231-
testTracesGRPOptions(t, otlpOptions{Endpoint: "localhost:3232", SkipTLSVerify: true}, &tcfg)
239+
testTracesGRPCOptions(t, otlpOptions{Endpoint: "localhost:3232", SkipTLSVerify: true, GRPCHeaders: map[string]string{}}, &tcfg)
232240
})
233241
}
234242

235-
func testTracesGRPOptions(t *testing.T, expected otlpOptions, tcfg *TracesConfig) {
243+
func TestGRPCTracesEndpointHeaders(t *testing.T) {
244+
type testCase struct {
245+
Description string
246+
Env map[string]string
247+
ExpectedHeaders map[string]string
248+
Grafana GrafanaOTLP
249+
}
250+
for _, tc := range []testCase{
251+
{Description: "No headers",
252+
ExpectedHeaders: map[string]string{}},
253+
{Description: "defining common OTLP_HEADERS",
254+
Env: map[string]string{"OTEL_EXPORTER_OTLP_HEADERS": "Foo=Bar ==,Authorization=Base 2222=="},
255+
ExpectedHeaders: map[string]string{"Foo": "Bar ==", "Authorization": "Base 2222=="}},
256+
{Description: "defining common OTLP_TRACES_HEADERS",
257+
Env: map[string]string{"OTEL_EXPORTER_OTLP_TRACES_HEADERS": "Foo=Bar ==,Authorization=Base 1234=="},
258+
ExpectedHeaders: map[string]string{"Foo": "Bar ==", "Authorization": "Base 1234=="}},
259+
{Description: "OTLP_TRACES_HEADERS takes precedence over OTLP_HEADERS",
260+
Env: map[string]string{
261+
"OTEL_EXPORTER_OTLP_HEADERS": "Foo=Bar ==,Authorization=Base 3210==",
262+
"OTEL_EXPORTER_OTLP_TRACES_HEADERS": "Authorization=Base 1111==",
263+
},
264+
ExpectedHeaders: map[string]string{"Foo": "Bar ==", "Authorization": "Base 1111=="}},
265+
} {
266+
// mutex to avoid running testcases in parallel so we don't mess up with env vars
267+
mt := sync.Mutex{}
268+
t.Run(fmt.Sprint(tc.Description), func(t *testing.T) {
269+
mt.Lock()
270+
restore := restoreEnvAfterExecution()
271+
defer func() {
272+
restore()
273+
mt.Unlock()
274+
}()
275+
for k, v := range tc.Env {
276+
require.NoError(t, os.Setenv(k, v))
277+
}
278+
279+
opts, err := getGRPCTracesEndpointOptions(&TracesConfig{
280+
TracesEndpoint: "https://localhost:1234/v1/traces",
281+
Grafana: &tc.Grafana,
282+
Instrumentations: []string{instrumentations.InstrumentationALL},
283+
})
284+
require.NoError(t, err)
285+
assert.Equal(t, tc.ExpectedHeaders, opts.GRPCHeaders)
286+
})
287+
}
288+
}
289+
290+
func testTracesGRPCOptions(t *testing.T, expected otlpOptions, tcfg *TracesConfig) {
236291
defer restoreEnvAfterExecution()()
237292
opts, err := getGRPCTracesEndpointOptions(tcfg)
238293
require.NoError(t, err)

0 commit comments

Comments
 (0)