diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index cd218c3fc86..9360a87a1a7 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -12,6 +12,10 @@ Notes](../../RELEASENOTES.md). exports are correctly marked as successful. ([#6099](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6099)) +* Fixed an issues causing trace exports to fail when + `Activity.StatusDescription` exceeds 127 bytes. + ([#6119](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6119)) + ## 1.11.1 Released 2025-Jan-22 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTraceSerializer.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTraceSerializer.cs index a8e0609f8d0..1f7a2ccf42e 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTraceSerializer.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTraceSerializer.cs @@ -507,7 +507,10 @@ internal static int WriteSpanStatus(byte[] buffer, int position, Activity activi { var descriptionSpan = description.AsSpan(); var numberOfUtf8CharsInString = ProtobufSerializer.GetNumberOfUtf8CharsInString(descriptionSpan); - position = ProtobufSerializer.WriteTagAndLength(buffer, position, numberOfUtf8CharsInString + 4, ProtobufOtlpTraceFieldNumberConstants.Span_Status, ProtobufWireType.LEN); + var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)numberOfUtf8CharsInString); + + // length = numberOfUtf8CharsInString + Status_Message tag size + serializedLengthSize field size + Span_Status tag size + Span_Status length size. + position = ProtobufSerializer.WriteTagAndLength(buffer, position, numberOfUtf8CharsInString + 1 + serializedLengthSize + 2, ProtobufOtlpTraceFieldNumberConstants.Span_Status, ProtobufWireType.LEN); position = ProtobufSerializer.WriteStringWithTag(buffer, position, ProtobufOtlpTraceFieldNumberConstants.Status_Message, numberOfUtf8CharsInString, descriptionSpan); } else diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs index 4a2b4103322..aa05317c9e7 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs @@ -15,7 +15,6 @@ using OtlpCollector = OpenTelemetry.Proto.Collector.Trace.V1; using OtlpCommon = OpenTelemetry.Proto.Common.V1; using OtlpTrace = OpenTelemetry.Proto.Trace.V1; -using Status = OpenTelemetry.Trace.Status; namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests; @@ -500,7 +499,7 @@ public void ToOtlpSpanTest() Assert.NotNull(childActivity); - childActivity.SetStatus(ActivityStatusCode.Error); + childActivity.SetStatus(ActivityStatusCode.Error, new string('a', 150)); var childEvents = new List { new("e0"), new("e1", default, new ActivityTagsCollection(attributes)) }; childActivity.AddEvent(childEvents[0]); @@ -521,7 +520,7 @@ public void ToOtlpSpanTest() Assert.NotNull(otlpSpan.Status); Assert.Equal(OtlpTrace.Status.Types.StatusCode.Error, otlpSpan.Status.Code); - Assert.Equal(Status.Error.Description ?? string.Empty, otlpSpan.Status.Message); + Assert.Equal(childActivity.StatusDescription ?? string.Empty, otlpSpan.Status.Message); Assert.Empty(otlpSpan.Attributes); Assert.Equal(childEvents.Count, otlpSpan.Events.Count); @@ -572,6 +571,7 @@ public void ToOtlpSpanActivitiesWithNullArrayTest() [InlineData(ActivityStatusCode.Unset, "Description will be ignored if status is Unset.")] [InlineData(ActivityStatusCode.Ok, "Description will be ignored if status is Okay.")] [InlineData(ActivityStatusCode.Error, "Description will be kept if status is Error.")] + [InlineData(ActivityStatusCode.Error, "150 Character String - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] public void ToOtlpSpanNativeActivityStatusTest(ActivityStatusCode expectedStatusCode, string statusDescription) { using var activitySource = new ActivitySource(nameof(this.ToOtlpSpanTest)); @@ -645,6 +645,7 @@ void RunTest(SdkLimitOptions sdkOptions, Batch batch) [InlineData(StatusCode.Unset, "Unset", "Description will be ignored if status is Unset.")] [InlineData(StatusCode.Ok, "Ok", "Description must only be used with the Error StatusCode.")] [InlineData(StatusCode.Error, "Error", "Error description.")] + [InlineData(StatusCode.Error, "Error", "150 Character String - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] [Obsolete("Remove when ActivityExtensions status APIs are removed")] public void ToOtlpSpanStatusTagTest(StatusCode expectedStatusCode, string statusCodeTagValue, string statusDescription) {