Skip to content

Commit f9ed9bf

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 f9ed9bf

File tree

8 files changed

+281
-290
lines changed

8 files changed

+281
-290
lines changed

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

Lines changed: 23 additions & 27 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;
@@ -77,7 +77,6 @@ internal static int TryWriteResourceLogs(ref byte[] buffer, int writePosition, S
7777
{
7878
// Reset write position and attempt to increase the buffer size
7979
writePosition = entryWritePosition;
80-
8180
if (!ProtobufSerializer.IncreaseBufferSize(ref buffer, OtlpSignalType.Logs))
8281
{
8382
throw;
@@ -129,12 +128,12 @@ internal static int WriteScopeLogs(byte[] buffer, int writePosition, SdkLimitOpt
129128
{
130129
foreach (KeyValuePair<string, List<LogRecord>> entry in scopeLogs)
131130
{
132-
writePosition = ProtobufSerializer.WriteTag(buffer, writePosition, ProtobufOtlpLogFieldNumberConstants.ResourceLogs_Scope_Logs, ProtobufWireType.LEN);
131+
writePosition += ProtobufSerializer.WriteTag(buffer.AsSpan(writePosition), ProtobufOtlpLogFieldNumberConstants.ResourceLogs_Scope_Logs, ProtobufWireType.LEN);
133132
int resourceLogsScopeLogsLengthPosition = writePosition;
134133
writePosition += ReserveSizeForLength;
135134

136135
writePosition = WriteScopeLog(buffer, writePosition, sdkLimitOptions, experimentalOptions, entry.Value[0].Logger.Name, entry.Value);
137-
ProtobufSerializer.WriteReservedLength(buffer, resourceLogsScopeLogsLengthPosition, writePosition - (resourceLogsScopeLogsLengthPosition + ReserveSizeForLength));
136+
ProtobufSerializer.WriteReservedLength(buffer.AsSpan(resourceLogsScopeLogsLengthPosition), writePosition - (resourceLogsScopeLogsLengthPosition + ReserveSizeForLength));
138137
}
139138
}
140139

@@ -148,14 +147,13 @@ internal static int WriteScopeLog(byte[] buffer, int writePosition, SdkLimitOpti
148147
var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)numberOfUtf8CharsInString);
149148

150149
// 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);
150+
writePosition += ProtobufSerializer.WriteTagAndLength(buffer.AsSpan(writePosition), numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Scope, ProtobufWireType.LEN);
151+
writePosition += ProtobufSerializer.WriteStringWithTag(buffer.AsSpan(writePosition), ProtobufOtlpCommonFieldNumberConstants.InstrumentationScope_Name, numberOfUtf8CharsInString, value);
153152

154153
for (int i = 0; i < logRecords.Count; i++)
155154
{
156155
writePosition = WriteLogRecord(buffer, writePosition, sdkLimitOptions, experimentalOptions, logRecords[i]);
157156
}
158-
159157
return writePosition;
160158
}
161159

@@ -175,23 +173,23 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
175173

176174
ref var otlpTagWriterState = ref state.TagWriterState;
177175

178-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Log_Records, ProtobufWireType.LEN);
176+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Log_Records, ProtobufWireType.LEN);
179177
int logRecordLengthPosition = otlpTagWriterState.WritePosition;
180178
otlpTagWriterState.WritePosition += ReserveSizeForLength;
181179

182180
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);
181+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Time_Unix_Nano, timestamp);
182+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Observed_Time_Unix_Nano, timestamp);
185183

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

188186
if (!string.IsNullOrWhiteSpace(logRecord.SeverityText))
189187
{
190-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.SeverityText!);
188+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.SeverityText!);
191189
}
192190
else if (logRecord.Severity.HasValue)
193191
{
194-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.Severity.Value.ToShortName());
192+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.Severity.Value.ToShortName());
195193
}
196194

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

249247
if (logRecord.TraceId != default && logRecord.SpanId != default)
250248
{
251-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, TraceIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Trace_Id, ProtobufWireType.LEN);
249+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), TraceIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Trace_Id, ProtobufWireType.LEN);
252250
otlpTagWriterState.WritePosition = ProtobufOtlpTraceSerializer.WriteTraceId(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, logRecord.TraceId);
253251

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

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

260258
if (logRecord.EventId.Name != null)
261259
{
262-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Event_Name, logRecord.EventId.Name!);
260+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Event_Name, logRecord.EventId.Name!);
263261
}
264262

265263
logRecord.ForEachScope(ProcessScope, state);
266264

267265
if (otlpTagWriterState.DroppedTagCount > 0)
268266
{
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);
267+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTag(buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Dropped_Attributes_Count, ProtobufWireType.VARINT);
268+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteVarInt32(buffer.AsSpan(otlpTagWriterState.WritePosition), (uint)otlpTagWriterState.DroppedTagCount);
271269
}
272270

273-
ProtobufSerializer.WriteReservedLength(otlpTagWriterState.Buffer, logRecordLengthPosition, otlpTagWriterState.WritePosition - (logRecordLengthPosition + ReserveSizeForLength));
274-
271+
ProtobufSerializer.WriteReservedLength(otlpTagWriterState.Buffer.AsSpan(logRecordLengthPosition), otlpTagWriterState.WritePosition - (logRecordLengthPosition + ReserveSizeForLength));
275272
return otlpTagWriterState.WritePosition;
276273

277274
static void ProcessScope(LogRecordScope scope, SerializationState state)
@@ -312,10 +309,9 @@ private static int WriteLogRecordBody(byte[] buffer, int writePosition, ReadOnly
312309
{
313310
var numberOfUtf8CharsInString = ProtobufSerializer.GetNumberOfUtf8CharsInString(value);
314311
var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)numberOfUtf8CharsInString);
315-
316312
// 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);
313+
writePosition += ProtobufSerializer.WriteTagAndLength(buffer.AsSpan(writePosition), numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Body, ProtobufWireType.LEN);
314+
writePosition += ProtobufSerializer.WriteStringWithTag(buffer.AsSpan(writePosition), ProtobufOtlpCommonFieldNumberConstants.AnyValue_String_Value, numberOfUtf8CharsInString, value);
319315
return writePosition;
320316
}
321317

@@ -332,14 +328,14 @@ private static void AddLogAttribute(SerializationState state, string key, object
332328
}
333329
else
334330
{
335-
state.TagWriterState.WritePosition = ProtobufSerializer.WriteTag(state.TagWriterState.Buffer, state.TagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Attributes, ProtobufWireType.LEN);
331+
state.TagWriterState.WritePosition += ProtobufSerializer.WriteTag(state.TagWriterState.Buffer.AsSpan(state.TagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Attributes, ProtobufWireType.LEN);
336332
int logAttributesLengthPosition = state.TagWriterState.WritePosition;
337333
state.TagWriterState.WritePosition += ReserveSizeForLength;
338334

339335
ProtobufOtlpTagWriter.Instance.TryWriteTag(ref state.TagWriterState, key, value, state.AttributeValueLengthLimit);
340336

341337
var logAttributesLength = state.TagWriterState.WritePosition - (logAttributesLengthPosition + ReserveSizeForLength);
342-
ProtobufSerializer.WriteReservedLength(state.TagWriterState.Buffer, logAttributesLengthPosition, logAttributesLength);
338+
ProtobufSerializer.WriteReservedLength(state.TagWriterState.Buffer.AsSpan(logAttributesLengthPosition), logAttributesLength);
343339
state.TagWriterState.TagCount++;
344340
}
345341
}

0 commit comments

Comments
 (0)