Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ Notes](../../RELEASENOTES.md).
now set the `TE=trailers` HTTP request header to improve interoperability.
([#6449](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6449))

* Improved performance exporting `byte[]` attributes as native binary format
instead of arrays.
([#6534](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6534))

## 1.12.0

Released 2025-Apr-29
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ protected override bool TryWriteEmptyTag(ref OtlpTagWriterState state, string ke
return true;
}

protected override bool TryWriteByteArrayTag(ref OtlpTagWriterState state, string key, ReadOnlySpan<byte> value)
{
// Write KeyValue tag
state.WritePosition = ProtobufSerializer.WriteStringWithTag(state.Buffer, state.WritePosition, ProtobufOtlpCommonFieldNumberConstants.KeyValue_Key, key);

var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)value.Length);

// length = value.Length + tagSize + length field size.
state.WritePosition = ProtobufSerializer.WriteTagAndLength(state.Buffer, state.WritePosition, value.Length + 1 + serializedLengthSize, ProtobufOtlpCommonFieldNumberConstants.KeyValue_Value, ProtobufWireType.LEN);
state.WritePosition = ProtobufSerializer.WriteByteArrayWithTag(state.Buffer, state.WritePosition, ProtobufOtlpCommonFieldNumberConstants.AnyValue_Bytes_Value, value);

return true;
}

internal struct OtlpTagWriterState
{
public byte[] Buffer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,17 @@ internal static int ComputeVarInt64Size(ulong value)
return 10;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int WriteByteArrayWithTag(byte[] buffer, int writePosition, int fieldNumber, ReadOnlySpan<byte> value)
{
writePosition = WriteTag(buffer, writePosition, fieldNumber, ProtobufWireType.LEN);
writePosition = WriteLength(buffer, writePosition, value.Length);
value.CopyTo(buffer.AsSpan(writePosition));

writePosition += value.Length;
return writePosition;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int WriteStringWithTag(byte[] buffer, int writePosition, int fieldNumber, string value)
{
Expand Down
2 changes: 2 additions & 0 deletions src/Shared/TagWriter/JsonStringArrayTagWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ protected sealed override void WriteArrayTag(ref TTagState writer, string key, r

protected abstract void WriteArrayTag(ref TTagState writer, string key, ArraySegment<byte> arrayUtf8JsonBytes);

protected override bool TryWriteByteArrayTag(ref TTagState consoleTag, string key, ReadOnlySpan<byte> value) => false;

internal readonly struct JsonArrayTagWriterState(MemoryStream stream, Utf8JsonWriter writer)
{
public MemoryStream Stream { get; } = stream;
Expand Down
7 changes: 7 additions & 0 deletions src/Shared/TagWriter/TagWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ public bool TryWriteTag(
this.WriteFloatingPointTag(ref state, key, Convert.ToDouble(value, CultureInfo.InvariantCulture));
break;
case Array array:
if (value.GetType() == typeof(byte[]) && this.TryWriteByteArrayTag(ref state, key, ((byte[])value).AsSpan()))
{
return true;
}

try
{
this.WriteArrayTagInternal(ref state, key, array, tagValueMaxLength);
Expand Down Expand Up @@ -119,6 +124,8 @@ public bool TryWriteTag(

protected abstract bool TryWriteEmptyTag(ref TTagState state, string key, object? value);

protected abstract bool TryWriteByteArrayTag(ref TTagState state, string key, ReadOnlySpan<byte> value);

protected abstract void WriteIntegralTag(ref TTagState state, string key, long value);

protected abstract void WriteFloatingPointTag(ref TTagState state, string key, double value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,23 @@ public void IntegralTypesSupported(object value)
switch (value)
{
case Array array:
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase);
var expectedArray = new long[array.Length];
for (var i = 0; i < array.Length; i++)
if (value.GetType() == typeof(byte[]))
{
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.BytesValue, attribute.Value.ValueCase);
Assert.Equal((byte[])value, attribute.Value.BytesValue.ToByteArray());
}
else
{
expectedArray[i] = Convert.ToInt64(array.GetValue(i), CultureInfo.InvariantCulture);
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, attribute.Value.ValueCase);
var expectedArray = new long[array.Length];
for (var i = 0; i < array.Length; i++)
{
expectedArray[i] = Convert.ToInt64(array.GetValue(i), CultureInfo.InvariantCulture);
}

Assert.Equal(expectedArray, attribute.Value.ArrayValue.Values.Select(x => x.IntValue));
}

Assert.Equal(expectedArray, attribute.Value.ArrayValue.Values.Select(x => x.IntValue));
break;
default:
Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.IntValue, attribute.Value.ValueCase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ protected override bool TryWriteEmptyTag(ref Tag state, string key, object? valu
throw new NotImplementedException();
}

protected override bool TryWriteByteArrayTag(ref Tag consoleTag, string key, ReadOnlySpan<byte> value) => false;

public struct Tag
{
public string? Key;
Expand Down
Loading