Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(forwarder): add tracing to HTTP client #243

Merged
merged 1 commit into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions cmd/forwarder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ func realInit() (err error) {

logger.V(4).Info("initialized", "config", env)

tracing.SetLogger(logger)

tracerProvider, err := tracing.NewTracerProvider(ctx)
if err != nil {
return fmt.Errorf("failed to initialize tracing: %w", err)
Expand Down Expand Up @@ -116,6 +118,10 @@ func realInit() (err error) {
s3Client, err = s3http.New(&s3http.Config{
DestinationURI: env.DestinationURI,
GetObjectAPIClient: awsS3Client,
HTTPClient: tracing.NewHTTPClient(&tracing.HTTPClientConfig{
TracerProvider: tracerProvider,
Logger: &logger,
}),
})
if err != nil {
return fmt.Errorf("failed to load http client: %w", err)
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
Expand All @@ -57,6 +58,7 @@ require (
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.52.3 // indirect
github.com/prometheus/procfs v0.13.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
Expand Down Expand Up @@ -103,6 +105,8 @@ go.opentelemetry.io/contrib/exporters/autoexport v0.51.0 h1:imlL5MBzKu+NWhnJM62b
go.opentelemetry.io/contrib/exporters/autoexport v0.51.0/go.mod h1:gn1wFA1uVEKIXrM3DC7SN9ee83oJ0yALY/HbUfqMszo=
go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.51.0 h1:FGMfzzxfkNkw+gvKJOeT8dSmBjgrSFh+ClLl+OMKPno=
go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.51.0/go.mod h1:hmHUXiKhyxbIhuNfG5ZTySq9HqqxJFNxaFOfXXvoMmQ=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc=
go.opentelemetry.io/contrib/propagators/b3 v1.26.0 h1:wgFbVA+bK2k+fGVfDOCOG4cfDAoppyr5sI2dVlh8MWM=
go.opentelemetry.io/contrib/propagators/b3 v1.26.0/go.mod h1:DDktFXxA+fyItAAM0Sbl5OBH7KOsCTjvbBdPKtoIf/k=
go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs=
Expand Down
12 changes: 4 additions & 8 deletions handler/forwarder/s3http/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,11 @@ func New(cfg *Config) (*Client, error) {
return nil, fmt.Errorf("failed to validate config: %w", err)
}

r, err := request.NewBuilder(&request.BuilderConfig{
URL: cfg.DestinationURI,
})
if err != nil {
return nil, fmt.Errorf("failed to configure request builder: %w", err)
}

return &Client{
GetObjectAPIClient: cfg.GetObjectAPIClient,
RequestBuilder: r,
RequestBuilder: &request.Builder{
URL: cfg.DestinationURI,
Client: cfg.HTTPClient,
},
}, nil
}
2 changes: 2 additions & 0 deletions handler/forwarder/s3http/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package s3http
import (
"errors"
"fmt"
"net/http"
"net/url"
)

Expand All @@ -14,6 +15,7 @@ var (
type Config struct {
DestinationURI string // HTTP URI to upload data to
GetObjectAPIClient
HTTPClient *http.Client
}

func (c *Config) Validate() error {
Expand Down
63 changes: 6 additions & 57 deletions handler/forwarder/s3http/internal/request/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ package request

import (
"errors"
"fmt"
"net/http"
"net/url"
"time"

"github.com/go-logr/logr"
"github.com/hashicorp/go-retryablehttp"
)

var (
Expand All @@ -21,17 +16,6 @@ type Doer interface {
Do(*http.Request) (*http.Response, error)
}

type BuilderConfig struct {
URL string

RetryWaitMin *time.Duration // Minimum time to wait on retry
RetryWaitMax *time.Duration // Maximumum time to wait on retry
RetryMax *int // Maximum number of retries

HTTPClient *http.Client
Logger *logr.Logger
}

// Builder shares an HTTP client across request handlers.
type Builder struct {
Client Doer
Expand All @@ -48,48 +32,13 @@ func (b *Builder) With(tags map[string]string) *Handler {
u, _ := url.Parse(b.URL)
u.RawQuery = values.Encode()

return &Handler{
URL: u.String(),
Client: b.Client,
client := b.Client
if client == nil {
client = http.DefaultClient
}
}

func NewBuilder(cfg *BuilderConfig) (*Builder, error) {
if cfg == nil {
return nil, ErrNoConfig
}

if _, err := url.Parse(cfg.URL); err != nil {
return nil, fmt.Errorf("failed to parse base uri: %w", err)
}

client := retryablehttp.NewClient()

if cfg.HTTPClient != nil {
client.HTTPClient = cfg.HTTPClient
}

if cfg.RetryWaitMin != nil {
client.RetryWaitMin = *cfg.RetryWaitMin
}

if cfg.RetryWaitMax != nil {
client.RetryWaitMax = *cfg.RetryWaitMax
}

if cfg.RetryMax != nil {
client.RetryMax = *cfg.RetryMax
}

logger := logr.Discard()
if cfg.Logger != nil {
logger = *cfg.Logger
return &Handler{
URL: u.String(),
Client: client,
}

client.Logger = &leveledLogger{logger}

return &Builder{
URL: cfg.URL,
Client: client.StandardClient(),
}, nil
}
26 changes: 0 additions & 26 deletions handler/forwarder/s3http/internal/request/logger.go

This file was deleted.

77 changes: 77 additions & 0 deletions tracing/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package tracing

import (
"net/http"
"time"

"github.com/go-logr/logr"
"github.com/hashicorp/go-retryablehttp"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/sdk/trace"
)

// leveledLogger provides an adapter between logr.Logger and retryablehttp.LeveledLogger.
type leveledLogger struct {
logr.Logger
}

func (l *leveledLogger) Error(msg string, keysAndValues ...interface{}) {
l.V(1).Info(msg, keysAndValues...)
}

func (l *leveledLogger) Warn(msg string, keysAndValues ...interface{}) {
l.V(2).Info(msg, keysAndValues...)
}

func (l *leveledLogger) Info(msg string, keysAndValues ...interface{}) {
l.V(3).Info(msg, keysAndValues...)
}

func (l *leveledLogger) Debug(msg string, keysAndValues ...interface{}) {
l.V(4).Info(msg, keysAndValues...)
}

type HTTPClientConfig struct {
RetryWaitMin *time.Duration // Minimum time to wait on retry
RetryWaitMax *time.Duration // Maximumum time to wait on retry
RetryMax *int // Maximum number of retries
HTTPClient *http.Client
Logger *logr.Logger
TracerProvider *trace.TracerProvider
}

func NewHTTPClient(cfg *HTTPClientConfig) *http.Client {
if cfg == nil {
cfg = &HTTPClientConfig{}
}

client := retryablehttp.NewClient()

if cfg.HTTPClient != nil {
client.HTTPClient = cfg.HTTPClient
}

if cfg.RetryWaitMin != nil {
client.RetryWaitMin = *cfg.RetryWaitMin
}

if cfg.RetryWaitMax != nil {
client.RetryWaitMax = *cfg.RetryWaitMax
}

if cfg.RetryMax != nil {
client.RetryMax = *cfg.RetryMax
}

logger := logr.Discard()
if cfg.Logger != nil {
logger = *cfg.Logger
}

client.Logger = &leveledLogger{logger}

transport := &retryablehttp.RoundTripper{Client: client}
return &http.Client{
Transport: otelhttp.NewTransport(transport, otelhttp.WithTracerProvider(cfg.TracerProvider)),
}
}
6 changes: 6 additions & 0 deletions tracing/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ import (
"net/url"
"os"

"github.com/go-logr/logr"
"go.opentelemetry.io/contrib/detectors/aws/lambda"
"go.opentelemetry.io/contrib/exporters/autoexport"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/sdk/trace"
)

func SetLogger(logger logr.Logger) {
otel.SetLogger(logger)
}

// The OTEL SDK does not handle basic auth in OTEL_EXPORTER_OTLP_ENDPOINT
// Extract username and password and set as OTLP Headers.
func handleOTLPEndpointAuth() error {
Expand Down
Empty file.
19 changes: 19 additions & 0 deletions vendor/github.com/felixge/httpsnoop/LICENSE.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions vendor/github.com/felixge/httpsnoop/Makefile

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading