From d96d7d66ac626ec7bbdb377e31cdf25d2327e2d6 Mon Sep 17 00:00:00 2001 From: Matthew Hensley Date: Fri, 21 Feb 2025 15:58:04 -0500 Subject: [PATCH 1/5] add TryWriteEmptyTag implementations and tests --- .../Implementation/ConsoleTagWriter.cs | 7 +++++++ .../Implementation/Serializer/ProtobufOtlpTagWriter.cs | 8 ++++++++ .../Implementation/ZipkinTagWriter.cs | 2 ++ src/Shared/TagWriter/TagWriter.cs | 4 +++- .../OtlpAttributeTests.cs | 8 +++++++- .../Internal/JsonStringArrayTagWriterTests.cs | 5 +++++ 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Console/Implementation/ConsoleTagWriter.cs b/src/OpenTelemetry.Exporter.Console/Implementation/ConsoleTagWriter.cs index fcaf9cdb43c..1fdd4d70030 100644 --- a/src/OpenTelemetry.Exporter.Console/Implementation/ConsoleTagWriter.cs +++ b/src/OpenTelemetry.Exporter.Console/Implementation/ConsoleTagWriter.cs @@ -73,6 +73,13 @@ protected override void OnUnsupportedTagDropped( this.onUnsupportedTagDropped(tagKey, tagValueTypeFullName); } + protected override bool TryWriteEmptyTag(ref ConsoleTag consoleTag, string key, object? value) + { + consoleTag.Key = key; + consoleTag.Value = null; + return true; + } + internal struct ConsoleTag { public string? Key; diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTagWriter.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTagWriter.cs index 1002f90e7c7..803eefba0ff 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTagWriter.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTagWriter.cs @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using System; using System.Diagnostics; using OpenTelemetry.Internal; @@ -81,6 +82,13 @@ protected override void OnUnsupportedTagDropped( tagValueTypeFullName, tagKey); + protected override bool TryWriteEmptyTag(ref OtlpTagWriterState state, string key, object? value) + { + state.WritePosition = ProtobufSerializer.WriteStringWithTag(state.Buffer, state.WritePosition, ProtobufOtlpCommonFieldNumberConstants.KeyValue_Key, key); + state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, 0, ProtobufOtlpCommonFieldNumberConstants.KeyValue_Value, ProtobufWireType.LEN); + return true; + } + internal struct OtlpTagWriterState { public byte[] Buffer; diff --git a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinTagWriter.cs b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinTagWriter.cs index 30e1eb112ee..3e1c42c69ec 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinTagWriter.cs +++ b/src/OpenTelemetry.Exporter.Zipkin/Implementation/ZipkinTagWriter.cs @@ -64,4 +64,6 @@ protected override void OnUnsupportedTagDropped( tagValueTypeFullName, tagKey); } + + protected override bool TryWriteEmptyTag(ref Utf8JsonWriter state, string key, object? value) => false; } diff --git a/src/Shared/TagWriter/TagWriter.cs b/src/Shared/TagWriter/TagWriter.cs index f0d17019473..749f2d6822d 100644 --- a/src/Shared/TagWriter/TagWriter.cs +++ b/src/Shared/TagWriter/TagWriter.cs @@ -36,7 +36,7 @@ public bool TryWriteTag( { if (value == null) { - return false; + return this.TryWriteEmptyTag(ref state, key, value); } switch (value) @@ -117,6 +117,8 @@ public bool TryWriteTag( return true; } + protected abstract bool TryWriteEmptyTag(ref TTagState state, string key, object? value); + protected abstract void WriteIntegralTag(ref TTagState state, string key, long value); protected abstract void WriteFloatingPointTag(ref TTagState state, string key, double value); diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpAttributeTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpAttributeTests.cs index 05ffe584eb0..3991621936b 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpAttributeTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpAttributeTests.cs @@ -14,7 +14,13 @@ public class OtlpAttributeTests public void NullValueAttribute() { var kvp = new KeyValuePair("key", null); - Assert.False(TryTransformTag(kvp, out _)); + Assert.True(TryTransformTag(kvp, out var attribute)); + Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.None, attribute.Value.ValueCase); + Assert.False(attribute.Value.HasBoolValue); + Assert.False(attribute.Value.HasBytesValue); + Assert.False(attribute.Value.HasDoubleValue); + Assert.False(attribute.Value.HasIntValue); + Assert.False(attribute.Value.HasStringValue); } [Fact] diff --git a/test/OpenTelemetry.Tests/Internal/JsonStringArrayTagWriterTests.cs b/test/OpenTelemetry.Tests/Internal/JsonStringArrayTagWriterTests.cs index fbdc3da9cf7..2639b6f6366 100644 --- a/test/OpenTelemetry.Tests/Internal/JsonStringArrayTagWriterTests.cs +++ b/test/OpenTelemetry.Tests/Internal/JsonStringArrayTagWriterTests.cs @@ -193,6 +193,11 @@ protected override void OnUnsupportedTagDropped(string tagKey, string tagValueTy { } + protected override bool TryWriteEmptyTag(ref Tag state, string key, object? value) + { + throw new NotImplementedException(); + } + public struct Tag { public string? Key; From e3ecb26882d0a480dea0e6064d09270fb65a1925 Mon Sep 17 00:00:00 2001 From: Matthew Hensley Date: Fri, 21 Feb 2025 16:26:42 -0500 Subject: [PATCH 2/5] unnecessary using --- .../Implementation/Serializer/ProtobufOtlpTagWriter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTagWriter.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTagWriter.cs index 803eefba0ff..ee23a19b421 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTagWriter.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpTagWriter.cs @@ -1,7 +1,6 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -using System; using System.Diagnostics; using OpenTelemetry.Internal; From f43099b854d9a01c5503788903d85fa123dfed10 Mon Sep 17 00:00:00 2001 From: Matthew Hensley Date: Sat, 22 Feb 2025 10:22:40 -0500 Subject: [PATCH 3/5] CHANGELOG entry --- src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index 9360a87a1a7..b4f95d062b5 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -16,6 +16,9 @@ Notes](../../RELEASENOTES.md). `Activity.StatusDescription` exceeds 127 bytes. ([#6119](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6119)) +* Fixed protobuf serialization handling of null values in OTLP exporter. + ([#6149](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6149)) + ## 1.11.1 Released 2025-Jan-22 From cf958b58c43c0ff0778571a4adc08f85b3794cab Mon Sep 17 00:00:00 2001 From: Matthew Hensley Date: Mon, 24 Feb 2025 13:58:09 -0500 Subject: [PATCH 4/5] updated CHANGELOG --- src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index b4f95d062b5..132ea045e69 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -16,7 +16,8 @@ Notes](../../RELEASENOTES.md). `Activity.StatusDescription` exceeds 127 bytes. ([#6119](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6119)) -* Fixed protobuf serialization handling of null values in OTLP exporter. +* Fixed incorrect log serialization of attributes with null values, causing + some backends to reject logs when using OTLP exporter to output protobuf. ([#6149](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6149)) ## 1.11.1 From 0a0dca9e576303ea46585470756930613847e70b Mon Sep 17 00:00:00 2001 From: Matt Hensley <130569+matt-hensley@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:55:06 -0500 Subject: [PATCH 5/5] Update CHANGELOG.md Co-authored-by: Rajkumar Rangaraj --- src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index 132ea045e69..4e1cddc40a0 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -17,6 +17,7 @@ Notes](../../RELEASENOTES.md). ([#6119](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6119)) * Fixed incorrect log serialization of attributes with null values, causing + some backends to reject logs. some backends to reject logs when using OTLP exporter to output protobuf. ([#6149](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6149))