diff --git a/src/OpenTelemetry.Exporter.Geneva/GenevaLogExporter.cs b/src/OpenTelemetry.Exporter.Geneva/GenevaLogExporter.cs index 4d97cfa0ca..ce206f3fd3 100644 --- a/src/OpenTelemetry.Exporter.Geneva/GenevaLogExporter.cs +++ b/src/OpenTelemetry.Exporter.Geneva/GenevaLogExporter.cs @@ -37,6 +37,7 @@ public class GenevaLogExporter : GenevaBaseExporter private readonly IReadOnlyDictionary m_prepopulatedFields; private readonly List m_prepopulatedFieldKeys; private static readonly ThreadLocal m_buffer = new ThreadLocal(() => null); + private static readonly ThreadLocal exporterState = new(() => new ExporterStateForScopes()); private readonly byte[] m_bufferEpilogue; private static readonly string[] logLevels = new string[7] { @@ -417,41 +418,19 @@ internal int SerializeLogRecord(LogRecord logRecord) cntFields += 1; } - ushort scopeDepth = 0; - int indexArrayLength = 0; - logRecord.ForEachScope(ProcessScope, (object)null); - void ProcessScope(LogRecordScope scope, object state) - { - if (++scopeDepth == 1) - { - cursor = MessagePackSerializer.SerializeAsciiString(buffer, cursor, "scopes"); - cursor = MessagePackSerializer.WriteArrayHeader(buffer, cursor, ushort.MaxValue); - indexArrayLength = cursor - 2; - } - - cursor = MessagePackSerializer.WriteMapHeader(buffer, cursor, ushort.MaxValue); - int indexMapSizeScope = cursor - 2; - ushort keysCount = 0; - - foreach (KeyValuePair scopeItem in scope) - { - string key = "scope"; - if (!string.IsNullOrEmpty(scopeItem.Key)) - { - key = scopeItem.Key; - } + var state = exporterState.Value; + state.ScopeDepth = 0; + state.IndexForArrayLength = 0; + state.Cursor = cursor; + state.Buffer = buffer; - cursor = MessagePackSerializer.SerializeUnicodeString(buffer, cursor, key); - cursor = MessagePackSerializer.Serialize(buffer, cursor, scopeItem.Value); - keysCount++; - } + logRecord.ForEachScope(ProcessScope, state); - MessagePackSerializer.WriteUInt16(buffer, indexMapSizeScope, keysCount); - } - - if (scopeDepth > 0) + // logRecord has scopes + if (state.ScopeDepth > 0) { - MessagePackSerializer.WriteUInt16(buffer, indexArrayLength, scopeDepth); + MessagePackSerializer.WriteUInt16(buffer, state.IndexForArrayLength, state.ScopeDepth); + cursor = state.Cursor; cntFields += 1; } @@ -580,4 +559,41 @@ private static int SerializeSanitizedCategoryName(byte[] buffer, int cursor, str return cursor; } + + private class ExporterStateForScopes + { + internal ushort ScopeDepth; + internal int IndexForArrayLength; + internal int Cursor; + internal byte[] Buffer; + } + + private static readonly Action ProcessScope = (scope, state) => + { + if (++state.ScopeDepth == 1) + { + state.Cursor = MessagePackSerializer.SerializeAsciiString(state.Buffer, state.Cursor, "scopes"); + state.Cursor = MessagePackSerializer.WriteArrayHeader(state.Buffer, state.Cursor, ushort.MaxValue); + state.IndexForArrayLength = state.Cursor - 2; + } + + state.Cursor = MessagePackSerializer.WriteMapHeader(state.Buffer, state.Cursor, ushort.MaxValue); + int indexForMapSize = state.Cursor - 2; + ushort keysCount = 0; + + foreach (KeyValuePair scopeItem in scope) + { + string key = "scope"; + if (!string.IsNullOrEmpty(scopeItem.Key)) + { + key = scopeItem.Key; + } + + state.Cursor = MessagePackSerializer.SerializeUnicodeString(state.Buffer, state.Cursor, key); + state.Cursor = MessagePackSerializer.Serialize(state.Buffer, state.Cursor, scopeItem.Value); + keysCount++; + } + + MessagePackSerializer.WriteUInt16(state.Buffer, indexForMapSize, keysCount); + }; }