diff --git a/processor/spanmetricsprocessor/processor.go b/processor/spanmetricsprocessor/processor.go index f7de852dcb18..76a98765eeba 100644 --- a/processor/spanmetricsprocessor/processor.go +++ b/processor/spanmetricsprocessor/processor.go @@ -381,6 +381,16 @@ func (p *processorImp) aggregateMetricsForServiceSpans(rspans pdata.ResourceSpan func (p *processorImp) aggregateMetricsForSpan(serviceName string, span pdata.Span, resourceAttr pdata.Map) { latencyInMilliseconds := float64(span.EndTimestamp()-span.StartTimestamp()) / float64(time.Millisecond.Nanoseconds()) + if latencyInMilliseconds > maxDurationMs { + p.logger.Warn("Latency exceeds max of int64", + zap.String("service.name", serviceName), + zap.Uint64("startTimeUnixNano", uint64(span.StartTimestamp().AsTime().UnixNano())), + zap.Uint64("endTimeUnixNano", uint64(span.EndTimestamp().AsTime().UnixNano())), + zap.String("span.kind", span.Kind().String()), + zap.String("operation", span.Name())) + return + } + // Binary search to find the latencyInMilliseconds bucket index. index := sort.SearchFloat64s(p.latencyBounds, latencyInMilliseconds) diff --git a/processor/spanmetricsprocessor/processor_test.go b/processor/spanmetricsprocessor/processor_test.go index c740026763ff..6d340302bd39 100644 --- a/processor/spanmetricsprocessor/processor_test.go +++ b/processor/spanmetricsprocessor/processor_test.go @@ -840,3 +840,50 @@ func TestProcessorResetExemplarData(t *testing.T) { assert.NoError(t, err) assert.Empty(t, p.latencyExemplarsData[key]) } + +// ------------------------------------------------------- start of additional block of tests ------------------------------------------------------- + +func TestTraceLatencyExceedsMaxInt64(t *testing.T) { + mexp := &mocks.MetricsExporter{} + tcon := &mocks.TracesConsumer{} + + mexp.On("ConsumeMetrics", mock.Anything, mock.Anything).Return(nil) + tcon.On("ConsumeTraces", mock.Anything, mock.Anything).Return(nil) + + defaultNullValue := "defaultNullValue" + p := newProcessorImp(mexp, tcon, &defaultNullValue, cumulative, t) + + traces := buildTraceWithHighLatency() + + // Test + ctx := metadata.NewIncomingContext(context.Background(), nil) + + err := p.ConsumeTraces(ctx, traces) + // Validate + require.NoError(t, err) +} + +func buildTraceWithHighLatency() pdata.Traces { + traces := pdata.NewTraces() + rs := traces.ResourceSpans().AppendEmpty() + rs.Resource().Attributes(). + InsertString(conventions.AttributeServiceName, "test-service") + ils := rs.InstrumentationLibrarySpans().AppendEmpty() + span := ils.Spans().AppendEmpty() + span.SetName("/test") + span.SetKind(pdata.SpanKindClient) + span.Status().SetCode(pdata.StatusCodeOk) + span.SetStartTimestamp(0) + span.SetEndTimestamp(18446744073709551615) + span.Attributes().InsertString(stringAttrName, "stringAttrValue") + span.Attributes().InsertInt(intAttrName, 99) + span.Attributes().InsertDouble(doubleAttrName, 99.99) + span.Attributes().InsertBool(boolAttrName, true) + span.Attributes().InsertNull(nullAttrName) + span.Attributes().Insert(mapAttrName, pdata.NewAttributeValueMap()) + span.Attributes().Insert(arrayAttrName, pdata.NewAttributeValueArray()) + span.SetTraceID(pdata.NewTraceID([16]byte{byte(42)})) + return traces +} + +// ------------------------------------------------------- end of additional block of tests -------------------------------------------------------