private static object[] CreateStructuredLogEventInfoParameters(NLogMessageParameterList messageParameters, MessageTemplateParameters messagetTemplateParameters, out List <MessageTemplateParameter> extraProperties) { extraProperties = null; var paramsArray = new object[messagetTemplateParameters.Count]; var startPos = 0; for (var i = 0; i < messageParameters.Count; ++i) { var extraProperty = true; for (var j = startPos; j < messagetTemplateParameters.Count; ++j) { if (messageParameters[i].Name == messagetTemplateParameters[j].Name) { extraProperty = false; paramsArray[j] = messageParameters[i].Value; if (startPos == j) { startPos++; } break; } } if (extraProperty) { extraProperties = AddExtraProperty(extraProperties, messageParameters[i]); } } return(paramsArray); }
private static object[] CreatePositionalLogEventInfoParameters(NLogMessageParameterList messageParameters, MessageTemplateParameters messagetTemplateParameters, out List <MessageTemplateParameter> extraProperties) { extraProperties = null; var maxIndex = FindMaxIndex(messagetTemplateParameters); object[] paramsArray = null; for (var i = 0; i < messageParameters.Count; ++i) { // First positional name is the startPos if (char.IsDigit(messageParameters[i].Name[0]) && paramsArray == null) { paramsArray = new object[maxIndex + 1]; for (var j = 0; j <= maxIndex; ++j) { if (i + j < messageParameters.Count) { paramsArray[j] = messageParameters[i + j].Value; } } i += maxIndex; } else { extraProperties = AddExtraProperty(extraProperties, messageParameters[i]); } } return(paramsArray ?? new object[maxIndex + 1]); }
/// <summary> /// Allocates object[]-array for <see cref="LogEventInfo.Parameters"/> after checking /// for mismatch between Microsoft Extension Logging and NLog Message Template Parser /// </summary> /// <remarks> /// Cannot trust the parameters received from Microsoft Extension Logging, as extra parameters can be injected /// </remarks> private static object[] CreateLogEventInfoParameters(NLogMessageParameterList messageParameters, MessageTemplateParameters messagetTemplateParameters, out List <MessageTemplateParameter> extraProperties) { if (AllParameterCorrectlyPositionalMapped(messageParameters, messagetTemplateParameters)) { // Everything is mapped correctly, inject messageParameters directly as params-array extraProperties = null; var paramsArray = new object[messagetTemplateParameters.Count]; for (var i = 0; i < paramsArray.Length; ++i) { paramsArray[i] = messageParameters[i].Value; } return(paramsArray); } else { // Resolves mismatch between the input from Microsoft Extension Logging TState and NLog Message Template Parser if (messagetTemplateParameters.IsPositional) { return(CreatePositionalLogEventInfoParameters(messageParameters, messagetTemplateParameters, out extraProperties)); } else { return(CreateStructuredLogEventInfoParameters(messageParameters, messagetTemplateParameters, out extraProperties)); } } }
private static void SetLogEventMessageFormatter(LogEventInfo logEvent, NLogMessageParameterList messageTemplateParameters, string formattedMessage) { var parameters = new object[messageTemplateParameters.Count + 1]; for (var i = 0; i < parameters.Length - 1; ++i) { parameters[i] = messageTemplateParameters[i].Value; } parameters[parameters.Length - 1] = formattedMessage; logEvent.Parameters = parameters; logEvent.MessageFormatter = (l) => (string)l.Parameters[l.Parameters.Length - 1]; }
/// <summary> /// Are all parameters positional and correctly mapped? /// </summary> /// <param name="messageParameters"></param> /// <param name="messagetTemplateParameters"></param> /// <returns>true if correct</returns> private static bool AllParameterCorrectlyPositionalMapped(NLogMessageParameterList messageParameters, MessageTemplateParameters messagetTemplateParameters) { if (messagetTemplateParameters.Count != messageParameters.Count || messagetTemplateParameters.IsPositional) { return(false); } for (var i = 0; i < messagetTemplateParameters.Count; ++i) { if (messagetTemplateParameters[i].Name != messageParameters[i].Name) { return(false); } } return(true); }
/// <summary> /// Checks if the already parsed input message-parameters must be sent through /// the NLog MessageTemplate Parser for proper handling of message-template syntax. /// </summary> /// <remarks> /// Using the NLog MesageTemplate Parser will hurt performance: 1 x Microsoft Parser - 2 x NLog Parser - 1 x NLog Formatter /// </remarks> private LogEventInfo TryParseMessageTemplate(LogLevel nLogLogLevel, IList <KeyValuePair <string, object> > messageProperties, out NLogMessageParameterList messageParameters) { messageParameters = TryParseMessageParameterList(messageProperties); if (messageParameters?.HasMessageTemplateSyntax(_options.ParseMessageTemplates) == true) { var originalMessage = messageParameters.GetOriginalMessage(messageProperties); var eventInfo = new LogEventInfo(nLogLogLevel, _logger.Name, null, originalMessage, _singleItemArray); var messagetTemplateParameters = eventInfo.MessageTemplateParameters; // Forces parsing of OriginalMessage if (messagetTemplateParameters.Count > 0) { // We have parsed the message and found parameters, now we need to do the parameter mapping eventInfo.Parameters = CreateLogEventInfoParameters(messageParameters, messagetTemplateParameters, out var extraProperties); AddExtraPropertiesToLogEvent(eventInfo, extraProperties); return(eventInfo); } return(null); // Parsing not possible } return(null); // Parsing not needed }
private LogEventInfo CreateLogEventInfo(LogLevel nLogLogLevel, string formattedMessage, IList <KeyValuePair <string, object> > messageProperties, NLogMessageParameterList messageParameters) { return(TryCaptureMessageTemplate(nLogLogLevel, formattedMessage, messageProperties, messageParameters) ?? CreateSimpleLogEventInfo(nLogLogLevel, formattedMessage, messageProperties, messageParameters)); }
private LogEventInfo CreateSimpleLogEventInfo(LogLevel nLogLogLevel, string message, IList <KeyValuePair <string, object> > messageProperties, NLogMessageParameterList messageParameters) { // Parsing failed or no messageParameters var eventInfo = LogEventInfo.Create(nLogLogLevel, _logger.Name, message); if (messageParameters != null) { for (var i = 0; i < messageParameters.Count; ++i) { var property = messageParameters[i]; eventInfo.Properties[property.Name] = property.Value; } } else if (messageProperties != null && _options.CaptureMessageProperties) { CaptureMessagePropertiesList(eventInfo, messageProperties); } return(eventInfo); }
private LogEventInfo TryCaptureMessageTemplate(LogLevel nLogLogLevel, string message, IList <KeyValuePair <string, object> > messageProperties, NLogMessageParameterList messageParameters) { if (messageParameters?.HasComplexParameters == false) { // Parsing not needed, we take the fast route var originalMessage = messageParameters.GetOriginalMessage(messageProperties); var eventInfo = new LogEventInfo(nLogLogLevel, _logger.Name, originalMessage ?? message, messageParameters.IsPositional ? _emptyParameterArray : messageParameters); if (originalMessage != null) { SetLogEventMessageFormatter(eventInfo, messageParameters, message); } return(eventInfo); } return(null); }
/// <summary> /// Convert IList to <see cref="NLogMessageParameterList"/> /// </summary> /// <param name="messageProperties"></param> /// <returns></returns> private NLogMessageParameterList TryParseMessageParameterList(IList <KeyValuePair <string, object> > messageProperties) { return((messageProperties != null && _options.CaptureMessageTemplates) ? NLogMessageParameterList.TryParse(messageProperties) : null); }