Skip to content

Commit dc7f1eb

Browse files
authored
[otlp] OTLP Exporter Custom serializer - Log Scopes (open-telemetry#5945)
1 parent 1fc0ebc commit dc7f1eb

File tree

2 files changed

+196
-100
lines changed

2 files changed

+196
-100
lines changed

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

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ internal static class ProtobufOtlpLogSerializer
1616
private static readonly Stack<List<LogRecord>> LogsListPool = [];
1717
private static readonly Dictionary<string, List<LogRecord>> ScopeLogsList = [];
1818

19+
[ThreadStatic]
20+
private static SerializationState? threadSerializationState;
21+
1922
internal static int WriteLogsData(byte[] buffer, int writePosition, SdkLimitOptions sdkLimitOptions, ExperimentalOptions experimentalOptions, Resources.Resource? resource, in Batch<LogRecord> logRecordBatch)
2023
{
2124
foreach (var logRecord in logRecordBatch)
@@ -95,17 +98,20 @@ internal static int WriteScopeLog(byte[] buffer, int writePosition, SdkLimitOpti
9598

9699
internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOptions sdkLimitOptions, ExperimentalOptions experimentalOptions, LogRecord logRecord)
97100
{
98-
var attributeValueLengthLimit = sdkLimitOptions.LogRecordAttributeValueLengthLimit;
99-
var attributeCountLimit = sdkLimitOptions.LogRecordAttributeCountLimit ?? int.MaxValue;
101+
var state = threadSerializationState ??= new();
100102

101-
ProtobufOtlpTagWriter.OtlpTagWriterState otlpTagWriterState = new ProtobufOtlpTagWriter.OtlpTagWriterState
103+
state.AttributeValueLengthLimit = sdkLimitOptions.LogRecordAttributeValueLengthLimit;
104+
state.AttributeCountLimit = sdkLimitOptions.LogRecordAttributeCountLimit ?? int.MaxValue;
105+
state.TagWriterState = new ProtobufOtlpTagWriter.OtlpTagWriterState
102106
{
103107
Buffer = buffer,
104108
WritePosition = writePosition,
105109
TagCount = 0,
106110
DroppedTagCount = 0,
107111
};
108112

113+
ref var otlpTagWriterState = ref state.TagWriterState;
114+
109115
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.ScopeLogs_Log_Records, ProtobufWireType.LEN);
110116
int logRecordLengthPosition = otlpTagWriterState.WritePosition;
111117
otlpTagWriterState.WritePosition += ReserveSizeForLength;
@@ -129,20 +135,20 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
129135
{
130136
if (logRecord.EventId.Id != default)
131137
{
132-
otlpTagWriterState = AddLogAttribute(ref otlpTagWriterState, ExperimentalOptions.LogRecordEventIdAttribute, logRecord.EventId.Id, attributeCountLimit, attributeValueLengthLimit);
138+
AddLogAttribute(state, ExperimentalOptions.LogRecordEventIdAttribute, logRecord.EventId.Id);
133139
}
134140

135141
if (!string.IsNullOrEmpty(logRecord.EventId.Name))
136142
{
137-
otlpTagWriterState = AddLogAttribute(ref otlpTagWriterState, ExperimentalOptions.LogRecordEventNameAttribute, logRecord.EventId.Name!, attributeCountLimit, attributeValueLengthLimit);
143+
AddLogAttribute(state, ExperimentalOptions.LogRecordEventNameAttribute, logRecord.EventId.Name!);
138144
}
139145
}
140146

141147
if (logRecord.Exception != null)
142148
{
143-
otlpTagWriterState = AddLogAttribute(ref otlpTagWriterState, SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name, attributeCountLimit, attributeValueLengthLimit);
144-
otlpTagWriterState = AddLogAttribute(ref otlpTagWriterState, SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message, attributeCountLimit, attributeValueLengthLimit);
145-
otlpTagWriterState = AddLogAttribute(ref otlpTagWriterState, SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString(), attributeCountLimit, attributeValueLengthLimit);
149+
AddLogAttribute(state, SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name);
150+
AddLogAttribute(state, SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message);
151+
AddLogAttribute(state, SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString());
146152
}
147153

148154
bool bodyPopulatedFromFormattedMessage = false;
@@ -169,7 +175,7 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
169175
}
170176
else
171177
{
172-
otlpTagWriterState = AddLogAttribute(ref otlpTagWriterState, attribute, attributeCountLimit, attributeValueLengthLimit);
178+
AddLogAttribute(state, attribute);
173179
}
174180
}
175181

@@ -193,11 +199,19 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
193199
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteFixed32WithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Flags, (uint)logRecord.TraceFlags);
194200
}
195201

196-
/*
197-
* TODO: Handle scopes, otlpTagWriterState needs to be passed as ref.
198-
logRecord.ForEachScope(ProcessScope, otlpTagWriterState);
202+
logRecord.ForEachScope(ProcessScope, state);
203+
204+
if (otlpTagWriterState.DroppedTagCount > 0)
205+
{
206+
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTag(buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Dropped_Attributes_Count, ProtobufWireType.VARINT);
207+
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteVarInt32(buffer, otlpTagWriterState.WritePosition, (uint)otlpTagWriterState.DroppedTagCount);
208+
}
209+
210+
ProtobufSerializer.WriteReservedLength(otlpTagWriterState.Buffer, logRecordLengthPosition, otlpTagWriterState.WritePosition - (logRecordLengthPosition + ReserveSizeForLength));
211+
212+
return otlpTagWriterState.WritePosition;
199213

200-
void ProcessScope(LogRecordScope scope, ProtobufOtlpTagWriter.OtlpTagWriterState otlpTagWriterState)
214+
static void ProcessScope(LogRecordScope scope, SerializationState state)
201215
{
202216
foreach (var scopeItem in scope)
203217
{
@@ -225,21 +239,10 @@ void ProcessScope(LogRecordScope scope, ProtobufOtlpTagWriter.OtlpTagWriterState
225239
}
226240
else
227241
{
228-
otlpTagWriterState = AddLogAttribute(ref otlpTagWriterState, scopeItem, attributeCountLimit, attributeValueLengthLimit);
242+
AddLogAttribute(state, scopeItem);
229243
}
230244
}
231245
}
232-
*/
233-
234-
if (otlpTagWriterState.DroppedTagCount > 0)
235-
{
236-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTag(buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Dropped_Attributes_Count, ProtobufWireType.VARINT);
237-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteVarInt32(buffer, otlpTagWriterState.WritePosition, (uint)otlpTagWriterState.DroppedTagCount);
238-
}
239-
240-
ProtobufSerializer.WriteReservedLength(otlpTagWriterState.Buffer, logRecordLengthPosition, otlpTagWriterState.WritePosition - (logRecordLengthPosition + ReserveSizeForLength));
241-
242-
return otlpTagWriterState.WritePosition;
243246
}
244247

245248
private static int WriteLogRecordBody(byte[] buffer, int writePosition, ReadOnlySpan<char> value)
@@ -253,30 +256,35 @@ private static int WriteLogRecordBody(byte[] buffer, int writePosition, ReadOnly
253256
return writePosition;
254257
}
255258

256-
private static ProtobufOtlpTagWriter.OtlpTagWriterState AddLogAttribute(ref ProtobufOtlpTagWriter.OtlpTagWriterState otlpTagWriterState, KeyValuePair<string, object?> attribute, int maxAttributeCount, int? maxValueLength)
259+
private static void AddLogAttribute(SerializationState state, KeyValuePair<string, object?> attribute)
257260
{
258-
return AddLogAttribute(ref otlpTagWriterState, attribute.Key, attribute.Value, maxAttributeCount, maxValueLength);
261+
AddLogAttribute(state, attribute.Key, attribute.Value);
259262
}
260263

261-
private static ProtobufOtlpTagWriter.OtlpTagWriterState AddLogAttribute(ref ProtobufOtlpTagWriter.OtlpTagWriterState otlpTagWriterState, string key, object? value, int maxAttributeCount, int? maxValueLength)
264+
private static void AddLogAttribute(SerializationState state, string key, object? value)
262265
{
263-
if (otlpTagWriterState.TagCount == maxAttributeCount)
266+
if (state.TagWriterState.TagCount == state.AttributeCountLimit)
264267
{
265-
otlpTagWriterState.DroppedTagCount++;
268+
state.TagWriterState.DroppedTagCount++;
266269
}
267270
else
268271
{
269-
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Attributes, ProtobufWireType.LEN);
270-
int logAttributesLengthPosition = otlpTagWriterState.WritePosition;
271-
otlpTagWriterState.WritePosition += ReserveSizeForLength;
272+
state.TagWriterState.WritePosition = ProtobufSerializer.WriteTag(state.TagWriterState.Buffer, state.TagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Attributes, ProtobufWireType.LEN);
273+
int logAttributesLengthPosition = state.TagWriterState.WritePosition;
274+
state.TagWriterState.WritePosition += ReserveSizeForLength;
272275

273-
ProtobufOtlpTagWriter.Instance.TryWriteTag(ref otlpTagWriterState, key, value, maxValueLength);
276+
ProtobufOtlpTagWriter.Instance.TryWriteTag(ref state.TagWriterState, key, value, state.AttributeValueLengthLimit);
274277

275-
var logAttributesLength = otlpTagWriterState.WritePosition - (logAttributesLengthPosition + ReserveSizeForLength);
276-
ProtobufSerializer.WriteReservedLength(otlpTagWriterState.Buffer, logAttributesLengthPosition, logAttributesLength);
277-
otlpTagWriterState.TagCount++;
278+
var logAttributesLength = state.TagWriterState.WritePosition - (logAttributesLengthPosition + ReserveSizeForLength);
279+
ProtobufSerializer.WriteReservedLength(state.TagWriterState.Buffer, logAttributesLengthPosition, logAttributesLength);
280+
state.TagWriterState.TagCount++;
278281
}
282+
}
279283

280-
return otlpTagWriterState;
284+
private sealed class SerializationState
285+
{
286+
public int? AttributeValueLengthLimit;
287+
public int AttributeCountLimit;
288+
public ProtobufOtlpTagWriter.OtlpTagWriterState TagWriterState;
281289
}
282290
}

0 commit comments

Comments
 (0)