1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-07-13 01:00:22 +02:00

Do not handle empty partial OTLP successes (#3438)

* Do not handle empty partial OTLP successes

Fix #3432.

The OTLP server will respond with empty partial success responses (i.e.
empty messages and 0 count). Treat these as equivalent to it not being
set/present like the documentation specifies in the proto:
724e427879/opentelemetry/proto/collector/trace/v1/trace_service.proto (L58)

* Fix tests

* Add changes to changelog
This commit is contained in:
Tyler Yahn
2022-11-03 09:02:39 -07:00
committed by GitHub
parent e8023fab22
commit b5b685249c
5 changed files with 32 additions and 34 deletions

View File

@ -32,6 +32,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Cumulative metrics from the OpenCensus bridge (`go.opentelemetry.io/otel/bridge/opencensus`) are defined as monotonic sums, instead of non-monotonic. (#3389) - Cumulative metrics from the OpenCensus bridge (`go.opentelemetry.io/otel/bridge/opencensus`) are defined as monotonic sums, instead of non-monotonic. (#3389)
- Asynchronous counters (`Counter` and `UpDownCounter`) from the metric SDK now produce delta sums when configured with delta temporality. (#3398) - Asynchronous counters (`Counter` and `UpDownCounter`) from the metric SDK now produce delta sums when configured with delta temporality. (#3398)
- Exported `Status` codes in the `go.opentelemetry.io/otel/exporters/zipkin` exporter are now exported as all upper case values. (#3340) - Exported `Status` codes in the `go.opentelemetry.io/otel/exporters/zipkin` exporter are now exported as all upper case values. (#3340)
- Do not report empty partial-success responses in the `go.opentelemetry.io/otel/exporters/otlp` exporters. (#3438, #3432)
## [1.11.1/0.33.0] 2022-10-19 ## [1.11.1/0.33.0] 2022-10-19

View File

@ -16,19 +16,6 @@ package internal // import "go.opentelemetry.io/otel/exporters/otlp/internal"
import "fmt" import "fmt"
// PartialSuccessDropKind indicates the kind of partial success error
// received by an OTLP exporter, which corresponds with the signal
// being exported.
type PartialSuccessDropKind string
const (
// TracingPartialSuccess indicates that some spans were rejected.
TracingPartialSuccess PartialSuccessDropKind = "spans"
// MetricsPartialSuccess indicates that some metric data points were rejected.
MetricsPartialSuccess PartialSuccessDropKind = "metric data points"
)
// PartialSuccess represents the underlying error for all handling // PartialSuccess represents the underlying error for all handling
// OTLP partial success messages. Use `errors.Is(err, // OTLP partial success messages. Use `errors.Is(err,
// PartialSuccess{})` to test whether an error passed to the OTel // PartialSuccess{})` to test whether an error passed to the OTel
@ -36,7 +23,7 @@ const (
type PartialSuccess struct { type PartialSuccess struct {
ErrorMessage string ErrorMessage string
RejectedItems int64 RejectedItems int64
RejectedKind PartialSuccessDropKind RejectedKind string
} }
var _ error = PartialSuccess{} var _ error = PartialSuccess{}
@ -56,13 +43,22 @@ func (ps PartialSuccess) Is(err error) bool {
return ok return ok
} }
// PartialSuccessToError produces an error suitable for passing to // TracePartialSuccessError returns an error describing a partial success
// `otel.Handle()` out of the fields in a partial success response, // response for the trace signal.
// independent of which signal produced the outcome. func TracePartialSuccessError(itemsRejected int64, errorMessage string) error {
func PartialSuccessToError(kind PartialSuccessDropKind, itemsRejected int64, errorMessage string) error {
return PartialSuccess{ return PartialSuccess{
ErrorMessage: errorMessage, ErrorMessage: errorMessage,
RejectedItems: itemsRejected, RejectedItems: itemsRejected,
RejectedKind: kind, RejectedKind: "spans",
}
}
// MetricPartialSuccessError returns an error describing a partial success
// response for the metric signal.
func MetricPartialSuccessError(itemsRejected int64, errorMessage string) error {
return PartialSuccess{
ErrorMessage: errorMessage,
RejectedItems: itemsRejected,
RejectedKind: "metric data points",
} }
} }

View File

@ -36,9 +36,8 @@ func requireErrorString(t *testing.T, expect string, err error) {
} }
func TestPartialSuccessFormat(t *testing.T) { func TestPartialSuccessFormat(t *testing.T) {
requireErrorString(t, "empty message (0 metric data points rejected)", PartialSuccessToError(MetricsPartialSuccess, 0, "")) requireErrorString(t, "empty message (0 metric data points rejected)", MetricPartialSuccessError(0, ""))
requireErrorString(t, "help help (0 metric data points rejected)", PartialSuccessToError(MetricsPartialSuccess, 0, "help help")) requireErrorString(t, "help help (0 metric data points rejected)", MetricPartialSuccessError(0, "help help"))
requireErrorString(t, "what happened (10 metric data points rejected)", PartialSuccessToError(MetricsPartialSuccess, 10, "what happened")) requireErrorString(t, "what happened (10 metric data points rejected)", MetricPartialSuccessError(10, "what happened"))
requireErrorString(t, "what happened (15 spans rejected)", PartialSuccessToError(TracingPartialSuccess, 15, "what happened")) requireErrorString(t, "what happened (15 spans rejected)", TracePartialSuccessError(15, "what happened"))
requireErrorString(t, "empty message (7 log records rejected)", PartialSuccessToError("log records", 7, ""))
} }

View File

@ -202,11 +202,12 @@ func (c *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc
ResourceSpans: protoSpans, ResourceSpans: protoSpans,
}) })
if resp != nil && resp.PartialSuccess != nil { if resp != nil && resp.PartialSuccess != nil {
otel.Handle(internal.PartialSuccessToError( msg := resp.PartialSuccess.GetErrorMessage()
internal.TracingPartialSuccess, n := resp.PartialSuccess.GetRejectedSpans()
resp.PartialSuccess.RejectedSpans, if n != 0 || msg != "" {
resp.PartialSuccess.ErrorMessage, err := internal.TracePartialSuccessError(n, msg)
)) otel.Handle(err)
}
} }
// nil is converted to OK. // nil is converted to OK.
if status.Code(err) == codes.OK { if status.Code(err) == codes.OK {

View File

@ -180,11 +180,12 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc
} }
if respProto.PartialSuccess != nil { if respProto.PartialSuccess != nil {
otel.Handle(internal.PartialSuccessToError( msg := respProto.PartialSuccess.GetErrorMessage()
internal.TracingPartialSuccess, n := respProto.PartialSuccess.GetRejectedSpans()
respProto.PartialSuccess.RejectedSpans, if n != 0 || msg != "" {
respProto.PartialSuccess.ErrorMessage, err := internal.TracePartialSuccessError(n, msg)
)) otel.Handle(err)
}
} }
} }
return nil return nil