You've already forked opentelemetry-go
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:
@ -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
|
||||||
|
|
||||||
|
@ -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",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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, ""))
|
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user