Skip to content

Commit

Permalink
Add User-Agent header to OTLP exporter requests
Browse files Browse the repository at this point in the history
Signed-off-by: rogerogers <rogers@rogerogers.com>
  • Loading branch information
rogerogers committed Oct 6, 2022
1 parent 697d245 commit 0d7ab2c
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Added

- Added an example of using metric views to customize instruments. (#3177)
- Add User-Agent header to OTLP exporter requests (#3261)

### Changed

Expand Down
24 changes: 24 additions & 0 deletions 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()
}
26 changes: 26 additions & 0 deletions 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())
}
3 changes: 3 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetricgrpc/client.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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...)
Expand Down
1 change: 1 addition & 0 deletions exporters/otlp/otlpmetric/otlpmetricgrpc/client_test.go
Expand Up @@ -169,6 +169,7 @@ func TestConfig(t *testing.T) {
require.NoError(t, exp.Shutdown(ctx))

got := coll.Headers()
require.Regexp(t, "OTel OTLP Exporter Go/1\\..*", got)
require.Contains(t, got, key)
assert.Equal(t, got[key], []string{headers[key]})
})
Expand Down
3 changes: 3 additions & 0 deletions exporters/otlp/otlpmetric/otlpmetrichttp/client.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions exporters/otlp/otlpmetric/otlpmetrichttp/client_test.go
Expand Up @@ -75,6 +75,7 @@ func TestConfig(t *testing.T) {
require.NoError(t, exp.Shutdown(ctx))

got := coll.Headers()
require.Regexp(t, "OTel OTLP Exporter Go/1\\..*", got)
require.Contains(t, got, key)
assert.Equal(t, got[key], []string{headers[key]})
})
Expand Down
2 changes: 2 additions & 0 deletions exporters/otlp/otlptrace/otlptracegrpc/client.go
Expand Up @@ -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...)
Expand Down
1 change: 1 addition & 0 deletions exporters/otlp/otlptrace/otlptracegrpc/client_test.go
Expand Up @@ -212,6 +212,7 @@ func TestNewWithHeaders(t *testing.T) {
require.NoError(t, exp.ExportSpans(ctx, roSpans))

headers := mc.getHeaders()
require.Regexp(t, "OTel OTLP Exporter Go/1\\..*", headers.Get("user-agent"))
require.Len(t, headers.Get("header1"), 1)
assert.Equal(t, "value1", headers.Get("header1")[0])
}
Expand Down
2 changes: 2 additions & 0 deletions exporters/otlp/otlptrace/otlptracehttp/client.go
Expand Up @@ -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)
}
Expand Down

0 comments on commit 0d7ab2c

Please sign in to comment.