mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-01-18 03:22:12 +02:00
otlptracehttp, otlpmetrichttp: Retry temporary HTTP request failures (#4679)
This commit is contained in:
parent
aea3eab43a
commit
5ec67e83df
@ -51,6 +51,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||||||
- Retry for `502 Bad Gateway` and `504 Gateway Timeout` HTTP statuses in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#4670)
|
- Retry for `502 Bad Gateway` and `504 Gateway Timeout` HTTP statuses in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#4670)
|
||||||
- Retry for `RESOURCE_EXHAUSTED` only if RetryInfo is returned in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#4669)
|
- Retry for `RESOURCE_EXHAUSTED` only if RetryInfo is returned in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#4669)
|
||||||
- Retry for `RESOURCE_EXHAUSTED` only if RetryInfo is returned in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#4669)
|
- Retry for `RESOURCE_EXHAUSTED` only if RetryInfo is returned in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#4669)
|
||||||
|
- Retry temporary HTTP request failures in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#4679)
|
||||||
|
- Retry temporary HTTP request failures in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#4679)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@ -147,6 +148,10 @@ func (c *client) UploadMetrics(ctx context.Context, protoMetrics *metricpb.Resou
|
|||||||
|
|
||||||
request.reset(iCtx)
|
request.reset(iCtx)
|
||||||
resp, err := c.httpClient.Do(request.Request)
|
resp, err := c.httpClient.Do(request.Request)
|
||||||
|
var urlErr *url.Error
|
||||||
|
if errors.As(err, &urlErr) && urlErr.Temporary() {
|
||||||
|
return newResponseError(http.Header{})
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,13 @@ func TestClient(t *testing.T) {
|
|||||||
t.Run("Integration", otest.RunClientTests(factory))
|
t.Run("Integration", otest.RunClientTests(factory))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewWithInvalidEndpoint(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
exp, err := New(ctx, WithEndpoint("host:invalid-port"))
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, exp)
|
||||||
|
}
|
||||||
|
|
||||||
func TestConfig(t *testing.T) {
|
func TestConfig(t *testing.T) {
|
||||||
factoryFunc := func(ePt string, rCh <-chan otest.ExportResult, o ...Option) (metric.Exporter, *otest.HTTPCollector) {
|
factoryFunc := func(ePt string, rCh <-chan otest.ExportResult, o ...Option) (metric.Exporter, *otest.HTTPCollector) {
|
||||||
coll, err := otest.NewHTTPCollector(ePt, rCh)
|
coll, err := otest.NewHTTPCollector(ePt, rCh)
|
||||||
@ -113,7 +120,7 @@ func TestConfig(t *testing.T) {
|
|||||||
t.Cleanup(func() { close(rCh) })
|
t.Cleanup(func() { close(rCh) })
|
||||||
t.Cleanup(func() { require.NoError(t, exp.Shutdown(ctx)) })
|
t.Cleanup(func() { require.NoError(t, exp.Shutdown(ctx)) })
|
||||||
err := exp.Export(ctx, &metricdata.ResourceMetrics{})
|
err := exp.Export(ctx, &metricdata.ResourceMetrics{})
|
||||||
assert.ErrorContains(t, err, context.DeadlineExceeded.Error())
|
assert.ErrorAs(t, err, new(retryableError))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("WithCompressionGZip", func(t *testing.T) {
|
t.Run("WithCompressionGZip", func(t *testing.T) {
|
||||||
@ -174,17 +181,6 @@ func TestConfig(t *testing.T) {
|
|||||||
assert.Len(t, coll.Collect().Dump(), 1)
|
assert.Len(t, coll.Collect().Dump(), 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("WithURLPath", func(t *testing.T) {
|
|
||||||
path := "/prefix/v2/metrics"
|
|
||||||
ePt := fmt.Sprintf("http://localhost:0%s", path)
|
|
||||||
exp, coll := factoryFunc(ePt, nil, WithURLPath(path))
|
|
||||||
ctx := context.Background()
|
|
||||||
t.Cleanup(func() { require.NoError(t, coll.Shutdown(ctx)) })
|
|
||||||
t.Cleanup(func() { require.NoError(t, exp.Shutdown(ctx)) })
|
|
||||||
assert.NoError(t, exp.Export(ctx, &metricdata.ResourceMetrics{}))
|
|
||||||
assert.Len(t, coll.Collect().Dump(), 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("WithTLSClientConfig", func(t *testing.T) {
|
t.Run("WithTLSClientConfig", func(t *testing.T) {
|
||||||
ePt := "https://localhost:0"
|
ePt := "https://localhost:0"
|
||||||
tlsCfg := &tls.Config{InsecureSkipVerify: true}
|
tlsCfg := &tls.Config{InsecureSkipVerify: true}
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@ -152,6 +153,10 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc
|
|||||||
|
|
||||||
request.reset(ctx)
|
request.reset(ctx)
|
||||||
resp, err := d.client.Do(request.Request)
|
resp, err := d.client.Do(request.Request)
|
||||||
|
var urlErr *url.Error
|
||||||
|
if errors.As(err, &urlErr) && urlErr.Temporary() {
|
||||||
|
return newResponseError(http.Header{})
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -213,6 +212,7 @@ func TestTimeout(t *testing.T) {
|
|||||||
otlptracehttp.WithEndpoint(mc.Endpoint()),
|
otlptracehttp.WithEndpoint(mc.Endpoint()),
|
||||||
otlptracehttp.WithInsecure(),
|
otlptracehttp.WithInsecure(),
|
||||||
otlptracehttp.WithTimeout(time.Nanosecond),
|
otlptracehttp.WithTimeout(time.Nanosecond),
|
||||||
|
otlptracehttp.WithRetry(otlptracehttp.RetryConfig{Enabled: false}),
|
||||||
)
|
)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
exporter, err := otlptrace.New(ctx, client)
|
exporter, err := otlptrace.New(ctx, client)
|
||||||
@ -221,9 +221,7 @@ func TestTimeout(t *testing.T) {
|
|||||||
assert.NoError(t, exporter.Shutdown(ctx))
|
assert.NoError(t, exporter.Shutdown(ctx))
|
||||||
}()
|
}()
|
||||||
err = exporter.ExportSpans(ctx, otlptracetest.SingleReadOnlySpan())
|
err = exporter.ExportSpans(ctx, otlptracetest.SingleReadOnlySpan())
|
||||||
unwrapped := errors.Unwrap(err)
|
assert.ErrorContains(t, err, "retry-able request failure")
|
||||||
assert.Equalf(t, true, os.IsTimeout(unwrapped), "expected timeout error, got: %v", unwrapped)
|
|
||||||
assert.True(t, strings.HasPrefix(err.Error(), "traces export: "), err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoRetry(t *testing.T) {
|
func TestNoRetry(t *testing.T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user