Skip to content

Commit 787412e

Browse files
committed
Refactored serialization logic to use Span<byte> for buffer manipulation, improving performance, memory efficiency, and code readability. Updated method signatures to eliminate explicit writePosition management, replaced incremental write logic with consistent += operations, and streamlined encoding methods. Enhanced test coverage to validate edge cases and updated all test cases to align with the new implementation. Applied changes consistently across all serializers, ensuring backward compatibility and laying the groundwork for future optimizations. Improved error handling, debugging, and documentation for better maintainability and robustness.
1 parent d61f9ef commit 787412e

File tree

7 files changed

+284
-289
lines changed

7 files changed

+284
-289
lines changed

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpLogSerializer.cs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ internal static int TryWriteResourceLogs(ref byte[] buffer, int writePosition, S
6262

6363
try
6464
{
65-
writePosition = ProtobufSerializer.WriteTag(buffer, writePosition, ProtobufOtlpLogFieldNumberConstants.LogsData_Resource_Logs, ProtobufWireType.LEN);
65+
writePosition += ProtobufSerializer.WriteTag(buffer.AsSpan(writePosition), ProtobufOtlpLogFieldNumberConstants.LogsData_Resource_Logs, ProtobufWireType.LEN);
6666
int logsDataLengthPosition = writePosition;
6767
writePosition += ReserveSizeForLength;
6868

6969
writePosition = WriteResourceLogs(buffer, writePosition, sdkLimitOptions, experimentalOptions, resource, scopeLogs);
7070

71-
ProtobufSerializer.WriteReservedLength(buffer, logsDataLengthPosition, writePosition - (logsDataLengthPosition + ReserveSizeForLength));
71+
ProtobufSerializer.WriteReservedLength(buffer.AsSpan(logsDataLengthPosition), writePosition - (logsDataLengthPosition + ReserveSizeForLength));
7272

7373
// Serialization succeeded, return the final write position
7474
return writePosition;
@@ -129,12 +129,12 @@ internal static int WriteScopeLogs(byte[] buffer, int writePosition, SdkLimitOpt
129129
{
130130
foreach (KeyValuePair<string, List<LogRecord>> entry in scopeLogs)
131131
{
132-
writePosition = ProtobufSerializer.WriteTag(buffer, writePosition, ProtobufOtlpLogFieldNumberConstants.ResourceLogs_Scope_Logs, ProtobufWireType.LEN);
132+
writePosition += ProtobufSerializer.WriteTag(buffer.AsSpan(writePosition), ProtobufOtlpLogFieldNumberConstants.ResourceLogs_Scope_Logs, ProtobufWireType.LEN);
133133
int resourceLogsScopeLogsLengthPosition = writePosition;
134134
writePosition += ReserveSizeForLength;
135135

136136
writePosition = WriteScopeLog(buffer, writePosition, sdkLimitOptions, experimentalOptions, entry.Value[0].Logger.Name, entry.Value);
137-
ProtobufSerializer.WriteReservedLength(buffer, resourceLogsScopeLogsLengthPosition, writePosition - (resourceLogsScopeLogsLengthPosition + ReserveSizeForLength));
137+
ProtobufSerializer.WriteReservedLength(buffer.AsSpan(resourceLogsScopeLogsLengthPosition), writePosition - (resourceLogsScopeLogsLengthPosition + ReserveSizeForLength));
138138
}
139139
}
140140

@@ -148,8 +148,8 @@ internal static int WriteScopeLog(byte[] buffer, int writePosition, SdkLimitOpti
148148
var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)numberOfUtf8CharsInString);
149149

150150
// numberOfUtf8CharsInString + tagSize + length field size.
151-
writePosition = ProtobufSerializer.WriteTagAndLength(buffer, writePosition, numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Scope, ProtobufWireType.LEN);
152-
writePosition = ProtobufSerializer.WriteStringWithTag(buffer, writePosition, ProtobufOtlpCommonFieldNumberConstants.InstrumentationScope_Name, numberOfUtf8CharsInString, value);
151+
writePosition += ProtobufSerializer.WriteTagAndLength(buffer.AsSpan(writePosition), numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Scope, ProtobufWireType.LEN);
152+
writePosition += ProtobufSerializer.WriteStringWithTag(buffer.AsSpan(writePosition), ProtobufOtlpCommonFieldNumberConstants.InstrumentationScope_Name, numberOfUtf8CharsInString, value);
153153

154154
for (int i = 0; i < logRecords.Count; i++)
155155
{
@@ -175,23 +175,23 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
175175

176176
ref var otlpTagWriterState = ref state.TagWriterState;
177177

178-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Log_Records, ProtobufWireType.LEN);
178+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Log_Records, ProtobufWireType.LEN);
179179
int logRecordLengthPosition = otlpTagWriterState.WritePosition;
180180
otlpTagWriterState.WritePosition += ReserveSizeForLength;
181181

182182
var timestamp = (ulong)logRecord.Timestamp.ToUnixTimeNanoseconds();
183-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Time_Unix_Nano, timestamp);
184-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Observed_Time_Unix_Nano, timestamp);
183+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Time_Unix_Nano, timestamp);
184+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Observed_Time_Unix_Nano, timestamp);
185185

186-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteEnumWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Number, logRecord.Severity.HasValue ? (int)logRecord.Severity : 0);
186+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteEnumWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Number, logRecord.Severity.HasValue ? (int)logRecord.Severity : 0);
187187

188188
if (!string.IsNullOrWhiteSpace(logRecord.SeverityText))
189189
{
190-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.SeverityText!);
190+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.SeverityText!);
191191
}
192192
else if (logRecord.Severity.HasValue)
193193
{
194-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.Severity.Value.ToShortName());
194+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.Severity.Value.ToShortName());
195195
}
196196

197197
if (experimentalOptions.EmitLogEventAttributes)
@@ -248,30 +248,29 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
248248

249249
if (logRecord.TraceId != default && logRecord.SpanId != default)
250250
{
251-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, TraceIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Trace_Id, ProtobufWireType.LEN);
251+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), TraceIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Trace_Id, ProtobufWireType.LEN);
252252
otlpTagWriterState.WritePosition = ProtobufOtlpTraceSerializer.WriteTraceId(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, logRecord.TraceId);
253253

254-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, SpanIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Span_Id, ProtobufWireType.LEN);
254+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), SpanIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Span_Id, ProtobufWireType.LEN);
255255
otlpTagWriterState.WritePosition = ProtobufOtlpTraceSerializer.WriteSpanId(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, logRecord.SpanId);
256256

257-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteFixed32WithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Flags, (uint)logRecord.TraceFlags);
257+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteFixed32WithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Flags, (uint)logRecord.TraceFlags);
258258
}
259259

260260
if (logRecord.EventId.Name != null)
261261
{
262-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Event_Name, logRecord.EventId.Name!);
262+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Event_Name, logRecord.EventId.Name!);
263263
}
264264

265265
logRecord.ForEachScope(ProcessScope, state);
266266

267267
if (otlpTagWriterState.DroppedTagCount > 0)
268268
{
269-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTag(buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Dropped_Attributes_Count, ProtobufWireType.VARINT);
270-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteVarInt32(buffer, otlpTagWriterState.WritePosition, (uint)otlpTagWriterState.DroppedTagCount);
269+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTag(buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Dropped_Attributes_Count, ProtobufWireType.VARINT);
270+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteVarInt32(buffer.AsSpan(otlpTagWriterState.WritePosition), (uint)otlpTagWriterState.DroppedTagCount);
271271
}
272272

273-
ProtobufSerializer.WriteReservedLength(otlpTagWriterState.Buffer, logRecordLengthPosition, otlpTagWriterState.WritePosition - (logRecordLengthPosition + ReserveSizeForLength));
274-
273+
ProtobufSerializer.WriteReservedLength(otlpTagWriterState.Buffer.AsSpan(logRecordLengthPosition), otlpTagWriterState.WritePosition - (logRecordLengthPosition + ReserveSizeForLength));
275274
return otlpTagWriterState.WritePosition;
276275

277276
static void ProcessScope(LogRecordScope scope, SerializationState state)
@@ -314,8 +313,9 @@ private static int WriteLogRecordBody(byte[] buffer, int writePosition, ReadOnly
314313
var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)numberOfUtf8CharsInString);
315314

316315
// length = numberOfUtf8CharsInString + tagSize + length field size.
317-
writePosition = ProtobufSerializer.WriteTagAndLength(buffer, writePosition, numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Body, ProtobufWireType.LEN);
318-
writePosition = ProtobufSerializer.WriteStringWithTag(buffer, writePosition, ProtobufOtlpCommonFieldNumberConstants.AnyValue_String_Value, numberOfUtf8CharsInString, value);
316+
317+
writePosition += ProtobufSerializer.WriteTagAndLength(buffer.AsSpan(writePosition), numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Body, ProtobufWireType.LEN);
318+
writePosition += ProtobufSerializer.WriteStringWithTag(buffer.AsSpan(writePosition), ProtobufOtlpCommonFieldNumberConstants.AnyValue_String_Value, numberOfUtf8CharsInString, value);
319319
return writePosition;
320320
}
321321

@@ -332,14 +332,14 @@ private static void AddLogAttribute(SerializationState state, string key, object
332332
}
333333
else
334334
{
335-
state.TagWriterState.WritePosition = ProtobufSerializer.WriteTag(state.TagWriterState.Buffer, state.TagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Attributes, ProtobufWireType.LEN);
335+
state.TagWriterState.WritePosition += ProtobufSerializer.WriteTag(state.TagWriterState.Buffer.AsSpan(state.TagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Attributes, ProtobufWireType.LEN);
336336
int logAttributesLengthPosition = state.TagWriterState.WritePosition;
337337
state.TagWriterState.WritePosition += ReserveSizeForLength;
338338

339339
ProtobufOtlpTagWriter.Instance.TryWriteTag(ref state.TagWriterState, key, value, state.AttributeValueLengthLimit);
340340

341341
var logAttributesLength = state.TagWriterState.WritePosition - (logAttributesLengthPosition + ReserveSizeForLength);
342-
ProtobufSerializer.WriteReservedLength(state.TagWriterState.Buffer, logAttributesLengthPosition, logAttributesLength);
342+
ProtobufSerializer.WriteReservedLength(state.TagWriterState.Buffer.AsSpan(logAttributesLengthPosition), logAttributesLength);
343343
state.TagWriterState.TagCount++;
344344
}
345345
}

0 commit comments

Comments
 (0)