From c0aad6b073196ad556ea09a190ba54ebff8c835e Mon Sep 17 00:00:00 2001 From: rogerogers Date: Thu, 6 Oct 2022 11:41:28 +0800 Subject: [PATCH] Add User-Agent header to OTLP exporter requests Signed-off-by: rogerogers --- exporters/otlp/internal/header.go | 24 +++++++++++++++++ exporters/otlp/internal/header_test.go | 26 +++++++++++++++++++ .../otlp/otlpmetric/otlpmetricgrpc/client.go | 3 +++ .../otlp/otlpmetric/otlpmetrichttp/client.go | 3 +++ .../otlp/otlptrace/otlptracegrpc/client.go | 2 ++ .../otlp/otlptrace/otlptracehttp/client.go | 2 ++ 6 files changed, 60 insertions(+) create mode 100644 exporters/otlp/internal/header.go create mode 100644 exporters/otlp/internal/header_test.go diff --git a/exporters/otlp/internal/header.go b/exporters/otlp/internal/header.go new file mode 100644 index 00000000000..9aa62ed9e8e --- /dev/null +++ b/exporters/otlp/internal/header.go @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package internal contains common functionality for all OTLP exporters. +package internal // import "go.opentelemetry.io/otel/exporters/otlp/internal" + +import "go.opentelemetry.io/otel" + +// GetUserAgentHeader return an OTLP header value form "OTel OTLP Exporter Go/{{ .Version }}" +// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#user-agent +func GetUserAgentHeader() string { + return "OTel OTLP Exporter Go/" + otel.Version() +} diff --git a/exporters/otlp/internal/header_test.go b/exporters/otlp/internal/header_test.go new file mode 100644 index 00000000000..ecca1a9490e --- /dev/null +++ b/exporters/otlp/internal/header_test.go @@ -0,0 +1,26 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package internal contains common functionality for all OTLP exporters. +package internal // import "go.opentelemetry.io/otel/exporters/otlp/internal" + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestGetUserAgentHeader(t *testing.T) { + require.Regexp(t, "OTel OTLP Exporter Go/1\\..*", GetUserAgentHeader()) +} diff --git a/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go b/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go index 4c5beb8f384..d2f4be38bce 100644 --- a/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go +++ b/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go @@ -24,6 +24,7 @@ import ( "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + "go.opentelemetry.io/otel/exporters/otlp/internal" "go.opentelemetry.io/otel/exporters/otlp/internal/retry" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/oconf" @@ -77,6 +78,8 @@ func newClient(ctx context.Context, options ...Option) (otlpmetric.Client, error } if c.conn == nil { + // Add a User-Agent header when no ClientConn was provided + cfg.DialOptions = append(cfg.DialOptions, grpc.WithUserAgent(internal.GetUserAgentHeader())) // If the caller did not provide a ClientConn when the client was // created, create one using the configuration they did provide. conn, err := grpc.DialContext(ctx, cfg.Metrics.Endpoint, cfg.DialOptions...) diff --git a/exporters/otlp/otlpmetric/otlpmetrichttp/client.go b/exporters/otlp/otlpmetric/otlpmetrichttp/client.go index 7a8d7e14707..0840a2c8fa6 100644 --- a/exporters/otlp/otlpmetric/otlpmetrichttp/client.go +++ b/exporters/otlp/otlpmetric/otlpmetrichttp/client.go @@ -29,6 +29,7 @@ import ( "google.golang.org/protobuf/proto" + "go.opentelemetry.io/otel/exporters/otlp/internal" "go.opentelemetry.io/otel/exporters/otlp/internal/retry" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/internal/oconf" @@ -101,6 +102,8 @@ func newClient(opts ...Option) (otlpmetric.Client, error) { return nil, err } + req.Header.Set("User-Agent", internal.GetUserAgentHeader()) + if n := len(cfg.Metrics.Headers); n > 0 { for k, v := range cfg.Metrics.Headers { req.Header.Set(k, v) diff --git a/exporters/otlp/otlptrace/otlptracegrpc/client.go b/exporters/otlp/otlptrace/otlptracegrpc/client.go index 9d6e1898b14..0eb3cd29c66 100644 --- a/exporters/otlp/otlptrace/otlptracegrpc/client.go +++ b/exporters/otlp/otlptrace/otlptracegrpc/client.go @@ -91,6 +91,8 @@ func newClient(opts ...Option) *client { // Start establishes a gRPC connection to the collector. func (c *client) Start(ctx context.Context) error { if c.conn == nil { + // Add a User-Agent header when no ClientConn was provided + c.dialOpts = append(c.dialOpts, grpc.WithUserAgent(internal.GetUserAgentHeader())) // If the caller did not provide a ClientConn when the client was // created, create one using the configuration they did provide. conn, err := grpc.DialContext(ctx, c.endpoint, c.dialOpts...) diff --git a/exporters/otlp/otlptrace/otlptracehttp/client.go b/exporters/otlp/otlptrace/otlptracehttp/client.go index 745b6541d42..8f742dfc1bd 100644 --- a/exporters/otlp/otlptrace/otlptracehttp/client.go +++ b/exporters/otlp/otlptrace/otlptracehttp/client.go @@ -208,6 +208,8 @@ func (d *client) newRequest(body []byte) (request, error) { return request{Request: r}, err } + r.Header.Set("User-Agent", internal.GetUserAgentHeader()) + for k, v := range d.cfg.Headers { r.Header.Set(k, v) }