Skip to content

Commit 34c06eb

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 d8dfaa8 commit 34c06eb

File tree

7 files changed

+279
-284
lines changed

7 files changed

+279
-284
lines changed

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

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,12 @@ internal static int TryWriteResourceLogs(ref byte[] buffer, int writePosition, S
6060

6161
try
6262
{
63-
writePosition = ProtobufSerializer.WriteTag(buffer, writePosition, ProtobufOtlpLogFieldNumberConstants.LogsData_Resource_Logs, ProtobufWireType.LEN);
63+
writePosition += ProtobufSerializer.WriteTag(buffer.AsSpan(writePosition), ProtobufOtlpLogFieldNumberConstants.LogsData_Resource_Logs, ProtobufWireType.LEN);
6464
int logsDataLengthPosition = writePosition;
6565
writePosition += ReserveSizeForLength;
6666

6767
writePosition = WriteResourceLogs(buffer, writePosition, sdkLimitOptions, experimentalOptions, resource, scopeLogs);
68-
69-
ProtobufSerializer.WriteReservedLength(buffer, logsDataLengthPosition, writePosition - (logsDataLengthPosition + ReserveSizeForLength));
68+
ProtobufSerializer.WriteReservedLength(buffer.AsSpan(logsDataLengthPosition), writePosition - (logsDataLengthPosition + ReserveSizeForLength));
7069
}
7170
catch (Exception ex) when (ex is IndexOutOfRangeException || ex is ArgumentException)
7271
{
@@ -121,12 +120,12 @@ internal static int WriteScopeLogs(byte[] buffer, int writePosition, SdkLimitOpt
121120
{
122121
foreach (KeyValuePair<string, List<LogRecord>> entry in scopeLogs)
123122
{
124-
writePosition = ProtobufSerializer.WriteTag(buffer, writePosition, ProtobufOtlpLogFieldNumberConstants.ResourceLogs_Scope_Logs, ProtobufWireType.LEN);
123+
writePosition += ProtobufSerializer.WriteTag(buffer.AsSpan(writePosition), ProtobufOtlpLogFieldNumberConstants.ResourceLogs_Scope_Logs, ProtobufWireType.LEN);
125124
int resourceLogsScopeLogsLengthPosition = writePosition;
126125
writePosition += ReserveSizeForLength;
127126

128127
writePosition = WriteScopeLog(buffer, writePosition, sdkLimitOptions, experimentalOptions, entry.Value[0].Logger.Name, entry.Value);
129-
ProtobufSerializer.WriteReservedLength(buffer, resourceLogsScopeLogsLengthPosition, writePosition - (resourceLogsScopeLogsLengthPosition + ReserveSizeForLength));
128+
ProtobufSerializer.WriteReservedLength(buffer.AsSpan(resourceLogsScopeLogsLengthPosition), writePosition - (resourceLogsScopeLogsLengthPosition + ReserveSizeForLength));
130129
}
131130
}
132131

@@ -140,14 +139,13 @@ internal static int WriteScopeLog(byte[] buffer, int writePosition, SdkLimitOpti
140139
var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)numberOfUtf8CharsInString);
141140

142141
// numberOfUtf8CharsInString + tagSize + length field size.
143-
writePosition = ProtobufSerializer.WriteTagAndLength(buffer, writePosition, numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Scope, ProtobufWireType.LEN);
144-
writePosition = ProtobufSerializer.WriteStringWithTag(buffer, writePosition, ProtobufOtlpCommonFieldNumberConstants.InstrumentationScope_Name, numberOfUtf8CharsInString, value);
142+
writePosition += ProtobufSerializer.WriteTagAndLength(buffer.AsSpan(writePosition), numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Scope, ProtobufWireType.LEN);
143+
writePosition += ProtobufSerializer.WriteStringWithTag(buffer.AsSpan(writePosition), ProtobufOtlpCommonFieldNumberConstants.InstrumentationScope_Name, numberOfUtf8CharsInString, value);
145144

146145
for (int i = 0; i < logRecords.Count; i++)
147146
{
148147
writePosition = WriteLogRecord(buffer, writePosition, sdkLimitOptions, experimentalOptions, logRecords[i]);
149148
}
150-
151149
return writePosition;
152150
}
153151

@@ -167,23 +165,23 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
167165

168166
ref var otlpTagWriterState = ref state.TagWriterState;
169167

170-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Log_Records, ProtobufWireType.LEN);
168+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Log_Records, ProtobufWireType.LEN);
171169
int logRecordLengthPosition = otlpTagWriterState.WritePosition;
172170
otlpTagWriterState.WritePosition += ReserveSizeForLength;
173171

174172
var timestamp = (ulong)logRecord.Timestamp.ToUnixTimeNanoseconds();
175-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Time_Unix_Nano, timestamp);
176-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Observed_Time_Unix_Nano, timestamp);
173+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Time_Unix_Nano, timestamp);
174+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteFixed64WithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Observed_Time_Unix_Nano, timestamp);
177175

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

180178
if (!string.IsNullOrWhiteSpace(logRecord.SeverityText))
181179
{
182-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.SeverityText!);
180+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.SeverityText!);
183181
}
184182
else if (logRecord.Severity.HasValue)
185183
{
186-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.Severity.Value.ToShortName());
184+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Severity_Text, logRecord.Severity.Value.ToShortName());
187185
}
188186

189187
if (experimentalOptions.EmitLogEventAttributes)
@@ -240,30 +238,29 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
240238

241239
if (logRecord.TraceId != default && logRecord.SpanId != default)
242240
{
243-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, TraceIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Trace_Id, ProtobufWireType.LEN);
241+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), TraceIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Trace_Id, ProtobufWireType.LEN);
244242
otlpTagWriterState.WritePosition = ProtobufOtlpTraceSerializer.WriteTraceId(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, logRecord.TraceId);
245243

246-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, SpanIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Span_Id, ProtobufWireType.LEN);
244+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTagAndLength(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), SpanIdSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Span_Id, ProtobufWireType.LEN);
247245
otlpTagWriterState.WritePosition = ProtobufOtlpTraceSerializer.WriteSpanId(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, logRecord.SpanId);
248246

249-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteFixed32WithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Flags, (uint)logRecord.TraceFlags);
247+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteFixed32WithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Flags, (uint)logRecord.TraceFlags);
250248
}
251249

252250
if (logRecord.EventId.Name != null)
253251
{
254-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Event_Name, logRecord.EventId.Name!);
252+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Event_Name, logRecord.EventId.Name!);
255253
}
256254

257255
logRecord.ForEachScope(ProcessScope, state);
258256

259257
if (otlpTagWriterState.DroppedTagCount > 0)
260258
{
261-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTag(buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Dropped_Attributes_Count, ProtobufWireType.VARINT);
262-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteVarInt32(buffer, otlpTagWriterState.WritePosition, (uint)otlpTagWriterState.DroppedTagCount);
259+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteTag(buffer.AsSpan(otlpTagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Dropped_Attributes_Count, ProtobufWireType.VARINT);
260+
otlpTagWriterState.WritePosition += ProtobufSerializer.WriteVarInt32(buffer.AsSpan(otlpTagWriterState.WritePosition), (uint)otlpTagWriterState.DroppedTagCount);
263261
}
264262

265-
ProtobufSerializer.WriteReservedLength(otlpTagWriterState.Buffer, logRecordLengthPosition, otlpTagWriterState.WritePosition - (logRecordLengthPosition + ReserveSizeForLength));
266-
263+
ProtobufSerializer.WriteReservedLength(otlpTagWriterState.Buffer.AsSpan(logRecordLengthPosition), otlpTagWriterState.WritePosition - (logRecordLengthPosition + ReserveSizeForLength));
267264
return otlpTagWriterState.WritePosition;
268265

269266
static void ProcessScope(LogRecordScope scope, SerializationState state)
@@ -304,10 +301,9 @@ private static int WriteLogRecordBody(byte[] buffer, int writePosition, ReadOnly
304301
{
305302
var numberOfUtf8CharsInString = ProtobufSerializer.GetNumberOfUtf8CharsInString(value);
306303
var serializedLengthSize = ProtobufSerializer.ComputeVarInt64Size((ulong)numberOfUtf8CharsInString);
307-
308304
// length = numberOfUtf8CharsInString + tagSize + length field size.
309-
writePosition = ProtobufSerializer.WriteTagAndLength(buffer, writePosition, numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Body, ProtobufWireType.LEN);
310-
writePosition = ProtobufSerializer.WriteStringWithTag(buffer, writePosition, ProtobufOtlpCommonFieldNumberConstants.AnyValue_String_Value, numberOfUtf8CharsInString, value);
305+
writePosition += ProtobufSerializer.WriteTagAndLength(buffer.AsSpan(writePosition), numberOfUtf8CharsInString + 1 + serializedLengthSize, ProtobufOtlpLogFieldNumberConstants.LogRecord_Body, ProtobufWireType.LEN);
306+
writePosition += ProtobufSerializer.WriteStringWithTag(buffer.AsSpan(writePosition), ProtobufOtlpCommonFieldNumberConstants.AnyValue_String_Value, numberOfUtf8CharsInString, value);
311307
return writePosition;
312308
}
313309

@@ -324,14 +320,14 @@ private static void AddLogAttribute(SerializationState state, string key, object
324320
}
325321
else
326322
{
327-
state.TagWriterState.WritePosition = ProtobufSerializer.WriteTag(state.TagWriterState.Buffer, state.TagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Attributes, ProtobufWireType.LEN);
323+
state.TagWriterState.WritePosition += ProtobufSerializer.WriteTag(state.TagWriterState.Buffer.AsSpan(state.TagWriterState.WritePosition), ProtobufOtlpLogFieldNumberConstants.LogRecord_Attributes, ProtobufWireType.LEN);
328324
int logAttributesLengthPosition = state.TagWriterState.WritePosition;
329325
state.TagWriterState.WritePosition += ReserveSizeForLength;
330326

331327
ProtobufOtlpTagWriter.Instance.TryWriteTag(ref state.TagWriterState, key, value, state.AttributeValueLengthLimit);
332328

333329
var logAttributesLength = state.TagWriterState.WritePosition - (logAttributesLengthPosition + ReserveSizeForLength);
334-
ProtobufSerializer.WriteReservedLength(state.TagWriterState.Buffer, logAttributesLengthPosition, logAttributesLength);
330+
ProtobufSerializer.WriteReservedLength(state.TagWriterState.Buffer.AsSpan(logAttributesLengthPosition), logAttributesLength);
335331
state.TagWriterState.TagCount++;
336332
}
337333
}

0 commit comments

Comments
 (0)