From 40ba994a089ae984d683045d657b9cc33710b106 Mon Sep 17 00:00:00 2001 From: Rolf Kristensen Date: Thu, 18 Dec 2025 08:20:44 +0100 Subject: [PATCH] NLogLogger - Optimize for default EventId capture --- .../Logging/NLogBeginScopeParser.cs | 84 ++++++------------- .../Logging/NLogLogger.cs | 38 ++++----- 2 files changed, 42 insertions(+), 80 deletions(-) diff --git a/src/NLog.Extensions.Logging/Logging/NLogBeginScopeParser.cs b/src/NLog.Extensions.Logging/Logging/NLogBeginScopeParser.cs index 305ffff0..056b0e90 100644 --- a/src/NLog.Extensions.Logging/Logging/NLogBeginScopeParser.cs +++ b/src/NLog.Extensions.Logging/Logging/NLogBeginScopeParser.cs @@ -279,7 +279,8 @@ private static bool TryBuildExtractor(Type propertyType, out Func)) { - return BuildKeyValueExtractor(propertyType, out keyValueExtractor); + keyValueExtractor = BuildKeyValueExtractor(propertyType); + return keyValueExtractor != null; } #if !NETSTANDARD2_1_OR_GREATER && !NETCOREAPP3_1_OR_GREATER && !NET471_OR_GREATER @@ -297,7 +298,8 @@ private static bool TryBuildExtractor(Type propertyType, out Func>? keyValueExtractor) + private static Func>? BuildKeyValueExtractor(Type propertyType, TypeInfo itemType) { var keyPropertyInfo = itemType.GetDeclaredProperty(nameof(KeyValuePair.Key)); var valuePropertyInfo = itemType.GetDeclaredProperty(nameof(KeyValuePair.Value)); if (valuePropertyInfo is null || keyPropertyInfo is null) - { - keyValueExtractor = null; - return false; - } + return null; var keyValuePairObjParam = Expression.Parameter(typeof(object), "KeyValuePair"); var keyValuePairTypeParam = Expression.Convert(keyValuePairObjParam, propertyType); var propertyKeyAccess = Expression.Property(keyValuePairTypeParam, keyPropertyInfo); var propertyValueAccess = Expression.Property(keyValuePairTypeParam, valuePropertyInfo); - return BuildKeyValueExtractor(keyValuePairObjParam, propertyKeyAccess, propertyValueAccess, out keyValueExtractor); + return BuildKeyValueExtractor(keyValuePairObjParam, propertyKeyAccess, propertyValueAccess); } - private static bool BuildKeyValueExtractor(Type propertyType, out Func>? keyValueExtractor) + private static Func>? BuildKeyValueExtractor(Type propertyType) { #if NETSTANDARD || NETFRAMEWORK var itemType = propertyType.GetTypeInfo(); - return BuildKeyValueExtractor(propertyType, itemType, out keyValueExtractor); + return BuildKeyValueExtractor(propertyType, itemType); #else if (propertyType.GenericTypeArguments[0] == typeof(string)) { if (propertyType.GenericTypeArguments[1] == typeof(object)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(string)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(int)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(long)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(decimal)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(double)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(bool)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(Guid)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(DateTime)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(DateTimeOffset)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; if (propertyType.GenericTypeArguments[1] == typeof(TimeSpan)) - { - keyValueExtractor = TypedKeyValueExtractor; - return true; - } + return TypedKeyValueExtractor; var itemType = propertyType.GetTypeInfo(); - return BuildKeyValueExtractor(propertyType, itemType, out keyValueExtractor); + return BuildKeyValueExtractor(propertyType, itemType); } - keyValueExtractor = null; - return false; + return null; #endif } - private static bool BuildKeyValueExtractor(ParameterExpression keyValuePairObjParam, MemberExpression propertyKeyAccess, MemberExpression propertyValueAccess, out Func> keyValueExtractor) + private static Func> BuildKeyValueExtractor(ParameterExpression keyValuePairObjParam, MemberExpression propertyKeyAccess, MemberExpression propertyValueAccess) { var propertyKeyAccessObj = Expression.Convert(propertyKeyAccess, typeof(object)); var propertyKeyLambda = Expression.Lambda>(propertyKeyAccessObj, keyValuePairObjParam).Compile(); @@ -411,13 +376,12 @@ private static bool BuildKeyValueExtractor(ParameterExpression keyValuePairObjPa var propertyValueAccessObj = Expression.Convert(propertyValueAccess, typeof(object)); var propertyValueLambda = Expression.Lambda>(propertyValueAccessObj, keyValuePairObjParam).Compile(); - keyValueExtractor = (obj) => + return (obj) => { return new KeyValuePair( propertyKeyLambda.Invoke(obj)?.ToString() ?? string.Empty, propertyValueLambda.Invoke(obj)); }; - return true; } } } diff --git a/src/NLog.Extensions.Logging/Logging/NLogLogger.cs b/src/NLog.Extensions.Logging/Logging/NLogLogger.cs index 7971c7ca..c987f861 100644 --- a/src/NLog.Extensions.Logging/Logging/NLogLogger.cs +++ b/src/NLog.Extensions.Logging/Logging/NLogLogger.cs @@ -66,14 +66,14 @@ public void Log(Microsoft.Extensions.Logging.LogLevel logLevel, EventId case 0: { var formattedMessage = formatter(state, exception); - return CreateLogEventWithoutParameters(nLogLogLevel, eventId, captureEventId, formattedMessage); + return CreateLogEventWithoutParameters(nLogLogLevel, formattedMessage, eventId, captureEventId); } case 1: parameterCount = 1; if (OriginalFormatPropertyName.Equals(((IReadOnlyList>)state)[0].Key)) { var formattedMessage = formatter(state, exception); - return CreateLogEventWithoutParameters(nLogLogLevel, eventId, captureEventId, formattedMessage); + return CreateLogEventWithoutParameters(nLogLogLevel, formattedMessage, eventId, captureEventId); } break; case 2: @@ -85,17 +85,17 @@ public void Log(Microsoft.Extensions.Logging.LogLevel logLevel, EventId { var formattedMessage = formatter(state, exception); if ("0".Equals(arg1.Name)) - return CreateLogEventWithoutParameters(nLogLogLevel, eventId, captureEventId, formattedMessage); + return CreateLogEventWithoutParameters(nLogLogLevel, formattedMessage, eventId, captureEventId); var originalMessage = ((IReadOnlyList>)state)[1].Value?.ToString() ?? formattedMessage; if (captureEventId) { var eventIdParameterCount = GetEventIdMessageParameters(eventId, out var eventIdArg1, out var eventIdArg2); - if (eventIdParameterCount == 1) - return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, eventIdArg1]); - else if (eventIdParameterCount != 0) + if (eventIdParameterCount == 2) return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, eventIdArg1, eventIdArg2]); + else if (eventIdParameterCount != 0) + return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, eventIdArg1]); } return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1]); } @@ -111,17 +111,17 @@ public void Log(Microsoft.Extensions.Logging.LogLevel logLevel, EventId { var formattedMessage = formatter(state, exception); if ("0".Equals(arg1.Name) && "1".Equals(arg2.Name)) - return CreateLogEventWithoutParameters(nLogLogLevel, eventId, captureEventId, formattedMessage); + return CreateLogEventWithoutParameters(nLogLogLevel, formattedMessage, eventId, captureEventId); var originalMessage = ((IReadOnlyList>)state)[2].Value?.ToString() ?? formattedMessage; if (captureEventId) { var eventIdParameterCount = GetEventIdMessageParameters(eventId, out var eventIdArg1, out var eventIdArg2); - if (eventIdParameterCount == 1) - return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, arg2, eventIdArg1]); - else if (eventIdParameterCount != 0) + if (eventIdParameterCount == 2) return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, arg2, eventIdArg1, eventIdArg2]); + else if (eventIdParameterCount != 0) + return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, arg2, eventIdArg1]); } return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, arg2]); } @@ -139,17 +139,17 @@ public void Log(Microsoft.Extensions.Logging.LogLevel logLevel, EventId { var formattedMessage = formatter(state, exception); if ("0".Equals(arg1.Name) && "1".Equals(arg2.Name) && "2".Equals(arg3.Name)) - return CreateLogEventWithoutParameters(nLogLogLevel, eventId, captureEventId, formattedMessage); + return CreateLogEventWithoutParameters(nLogLogLevel, formattedMessage, eventId, captureEventId); var originalMessage = ((IReadOnlyList>)state)[3].Value?.ToString() ?? formattedMessage; if (captureEventId) { var eventIdParameterCount = GetEventIdMessageParameters(eventId, out var eventIdArg1, out var eventIdArg2); - if (eventIdParameterCount == 1) - return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, arg2, arg3, eventIdArg1]); - else if (eventIdParameterCount != 0) + if (eventIdParameterCount == 2) return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, arg2, arg3, eventIdArg1, eventIdArg2]); + else if (eventIdParameterCount != 0) + return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, arg2, arg3, eventIdArg1]); } return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, originalMessage, [arg1, arg2, arg3]); } @@ -167,17 +167,15 @@ public void Log(Microsoft.Extensions.Logging.LogLevel logLevel, EventId return null; } - private LogEventInfo CreateLogEventWithoutParameters(LogLevel nLogLogLevel, in EventId eventId, bool captureEventId, string formattedMessage) + private LogEventInfo CreateLogEventWithoutParameters(LogLevel nLogLogLevel, string formattedMessage, in EventId eventId, bool captureEventId) { if (captureEventId) { var eventIdParameterCount = GetEventIdMessageParameters(eventId, out var eventIdArg1, out var eventIdArg2); - if (eventIdParameterCount == 0) - return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage); - else if (eventIdParameterCount == 1) - return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, formattedMessage, [eventIdArg1]); - else + if (eventIdParameterCount == 2) return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, formattedMessage, [eventIdArg1, eventIdArg2]); + else if (eventIdParameterCount != 0) + return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage, formattedMessage, [eventIdArg1]); } return new LogEventInfo(nLogLogLevel, _logger.Name, formattedMessage); }