Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: split methods, docs, error handling, smaller methodes and consistency #176

Merged
merged 14 commits into from
Dec 1, 2017
4 changes: 3 additions & 1 deletion src/NLog.Extensions.Logging/ConfigureExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,13 @@ public static ILoggingBuilder AddNLog(this ILoggingBuilder factory, NLogProvider
}
#endif

/// <summary>
/// Ignore assemblies for ${callsite}
/// </summary>
private static void ConfigureHiddenAssemblies()
{
try
{
//ignore these assemblies for ${callsite}
InternalLogger.Trace("Hide assemblies for callsite");

#if NETCORE1_0
Expand Down
199 changes: 114 additions & 85 deletions src/NLog.Extensions.Logging/NLogLogger.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using NLog.Common;

namespace NLog.Extensions.Logging
{
Expand Down Expand Up @@ -40,71 +41,89 @@ public void Log<TState>(Microsoft.Extensions.Logging.LogLevel logLevel, EventId
LogEventInfo eventInfo = CreateLogEventInfo(nLogLogLevel, message, messageTemplate);
eventInfo.Exception = exception;

CaptureEventId(eventId, eventInfo);
CaptureEventId(eventInfo, eventId);

if (_options.CaptureMessageProperties && messageTemplate == null)
{
CaptureMessageProperties(state, eventInfo);
}
CaptureMessageProperties(eventInfo, state, messageTemplate);

_logger.Log(eventInfo);
}


private LogEventInfo CreateLogEventInfo(LogLevel nLogLogLevel, string message, IReadOnlyList<KeyValuePair<string, object>> parameterList)
{
if (parameterList != null && parameterList.Count > 1)
if (parameterList != null && parameterList.Count > 1 && IsNonDigitValue(parameterList[0].Key))
{
// More than a single parameter (last parameter is the {OriginalFormat})
var firstParameterName = parameterList[0].Key;
if (!string.IsNullOrEmpty(firstParameterName))
{
if (firstParameterName.Length != 1 || !char.IsDigit(firstParameterName[0]))
{
return CreateLogEventInfoWithMultipleParameters(nLogLogLevel, message, parameterList);
}
return LogEventInfo.Create(nLogLogLevel, _logger.Name, message);
}

private static bool IsNonDigitValue(string value)
{
return !string.IsNullOrEmpty(value) && (value.Length != 1 || !char.IsDigit(value[0]));
}

#if !NETSTANDARD1_3
var originalFormat = parameterList[parameterList.Count - 1];
string originalMessage = null;
if (originalFormat.Key == OriginalFormatPropertyName)
{
// Attempt to capture original message with placeholders
originalMessage = originalFormat.Value as string;
}

var messageTemplateParameters = new NLogMessageParameterList(parameterList, originalMessage != null);
var eventInfo = new LogEventInfo(nLogLogLevel, _logger.Name, originalMessage ?? message, messageTemplateParameters);
if (originalMessage != null)
{
eventInfo.Parameters = new object[messageTemplateParameters.Count + 1];
for (int i = 0; i < messageTemplateParameters.Count; ++i)
eventInfo.Parameters[i] = messageTemplateParameters[i].Value;
eventInfo.Parameters[messageTemplateParameters.Count] = message;
eventInfo.MessageFormatter = (l) => (string)l.Parameters[l.Parameters.Length - 1];
}
return eventInfo;
/// <summary>
/// Create Log Event with multiple parameters (last parameter is the {OriginalFormat})
/// </summary>
private LogEventInfo CreateLogEventInfoWithMultipleParameters(LogLevel nLogLogLevel, string message, IReadOnlyList<KeyValuePair<string, object>> parameterList)
{
var originalFormat = parameterList[parameterList.Count - 1];
string originalMessage = null;
if (originalFormat.Key == OriginalFormatPropertyName)
{
// Attempt to capture original message with placeholders
originalMessage = originalFormat.Value as string;
}

var messageTemplateParameters = new NLogMessageParameterList(parameterList, originalMessage != null);
var eventInfo = new LogEventInfo(nLogLogLevel, _logger.Name, originalMessage ?? message, messageTemplateParameters);
if (originalMessage != null)
{
SetEventInfoParameters(eventInfo, messageTemplateParameters);
eventInfo.Parameters[messageTemplateParameters.Count] = message;
eventInfo.MessageFormatter = (l) => (string)l.Parameters[l.Parameters.Length - 1];
}
return eventInfo;
}

private static void SetEventInfoParameters(LogEventInfo eventInfo, NLogMessageParameterList messageTemplateParameters)
{
eventInfo.Parameters = new object[messageTemplateParameters.Count + 1];
for (int i = 0; i < messageTemplateParameters.Count; ++i)
eventInfo.Parameters[i] = messageTemplateParameters[i].Value;
}

#else
var eventInfo = LogEventInfo.Create(nLogLogLevel, _logger.Name, message);
for (int i = 0; i < parameterList.Count; ++i)
{
var parameter = parameterList[i];
if (string.IsNullOrEmpty(parameter.Key))
break; // Skip capture of invalid parameters

var parameterName = parameter.Key;
switch (parameterName[0])
{
case '@': parameterName = parameterName.Substring(1); break;
case '$': parameterName = parameterName.Substring(1); break;
}
eventInfo.Properties[parameterName] = parameter.Value;
}
return eventInfo;
#endif
}

/// <summary>
/// Create Log Event with multiple parameters (last parameter is the {OriginalFormat})
/// </summary>
private LogEventInfo CreateLogEventInfoWithMultipleParameters(LogLevel nLogLogLevel, string message, IReadOnlyList<KeyValuePair<string, object>> parameterList)
{
var eventInfo = LogEventInfo.Create(nLogLogLevel, _logger.Name, message);
for (int i = 0; i < parameterList.Count; ++i)
{
var parameter = parameterList[i];
if (string.IsNullOrEmpty(parameter.Key))
break; // Skip capture of invalid parameters

var parameterName = parameter.Key;
if (parameterName[0] == '@' || parameterName[0] == '$')
{
parameterName = parameterName.Substring(1);
}
eventInfo.Properties[parameterName] = parameter.Value;
}
return LogEventInfo.Create(nLogLogLevel, _logger.Name, message);
return eventInfo;
}

private void CaptureEventId(EventId eventId, LogEventInfo eventInfo)
#endif


private void CaptureEventId(LogEventInfo eventInfo, EventId eventId)
{
if (!_options.IgnoreEmptyEventId || eventId.Id != 0 || !string.IsNullOrEmpty(eventId.Name))
{
Expand All @@ -114,11 +133,7 @@ private void CaptureEventId(EventId eventId, LogEventInfo eventInfo)
if (!ReferenceEquals(eventIdPropertyNames.Item1, eventIdSeparator))
{
// Perform atomic cache update of the string-allocations matching the current separator
eventIdPropertyNames = new Tuple<string, string, string>(
eventIdSeparator,
string.Concat("EventId", eventIdSeparator, "Id"),
string.Concat("EventId", eventIdSeparator, "Name"));
_eventIdPropertyNames = eventIdPropertyNames;
_eventIdPropertyNames = eventIdPropertyNames = CreateEventIdPropertyNames(eventIdSeparator);
}

var idIsZero = eventId.Id == 0;
Expand All @@ -128,9 +143,18 @@ private void CaptureEventId(EventId eventId, LogEventInfo eventInfo)
}
}

private static void CaptureMessageProperties<TState>(TState state, LogEventInfo eventInfo)
private static Tuple<string, string, string> CreateEventIdPropertyNames(string eventIdSeparator)
{
var eventIdPropertyNames = new Tuple<string, string, string>(
eventIdSeparator,
string.Concat("EventId", eventIdSeparator, "Id"),
string.Concat("EventId", eventIdSeparator, "Name"));
return eventIdPropertyNames;
}

private void CaptureMessageProperties<TState>(LogEventInfo eventInfo, TState state, IReadOnlyList<KeyValuePair<string, object>> messageTemplate)
{
if (state is IEnumerable<KeyValuePair<string, object>> messageProperties)
if (_options.CaptureMessageProperties && messageTemplate == null && state is IEnumerable<KeyValuePair<string, object>> messageProperties)
{
foreach (var property in messageProperties)
{
Expand Down Expand Up @@ -192,24 +216,25 @@ private static LogLevel ConvertLogLevel(Microsoft.Extensions.Logging.LogLevel lo
class ScopeProperties : IDisposable
{
List<IDisposable> _properties;
List<IDisposable> Properties { get { return _properties ?? (_properties = new List<IDisposable>()); } }
List<IDisposable> Properties => _properties ?? (_properties = new List<IDisposable>());

class ScopeProperty : IDisposable

public static IDisposable CreateFromState<TState>(TState state, IEnumerable<KeyValuePair<string, object>> messageProperties)
{
string _key;
ScopeProperties scope = new ScopeProperties();

public ScopeProperty(string key, object value)
foreach (var property in messageProperties)
{
_key = key;
MappedDiagnosticsLogicalContext.Set(key, value);
}
if (String.IsNullOrEmpty(property.Key))
continue;

public void Dispose()
{
MappedDiagnosticsLogicalContext.Remove(_key);
scope.AddProperty(property.Key, property.Value);
}
}

scope.AddDispose(NestedDiagnosticsLogicalContext.Push(state));
return scope;
}

public void AddDispose(IDisposable disposable)
{
Properties.Add(disposable);
Expand All @@ -232,12 +257,30 @@ public void Dispose()
{
property.Dispose();
}
catch
catch (Exception ex)
{
InternalLogger.Trace(ex, "Exception in Dispose property {0}", property);
}
}
}
}

class ScopeProperty : IDisposable
{
string _key;

public ScopeProperty(string key, object value)
{
_key = key;
MappedDiagnosticsLogicalContext.Set(key, value);
}

public void Dispose()
{
MappedDiagnosticsLogicalContext.Remove(_key);
}
}

}

/// <summary>
Expand All @@ -252,23 +295,9 @@ public IDisposable BeginScope<TState>(TState state)
throw new ArgumentNullException(nameof(state));
}

if (_options.CaptureMessageProperties)
if (_options.CaptureMessageProperties && state is IEnumerable<KeyValuePair<string, object>> messageProperties)
{
if (state is IEnumerable<KeyValuePair<string, object>> messageProperties)
{
ScopeProperties scope = new ScopeProperties();

foreach (var property in messageProperties)
{
if (string.IsNullOrEmpty(property.Key))
continue;

scope.AddProperty(property.Key, property.Value);
}

scope.AddDispose(NestedDiagnosticsLogicalContext.Push(state));
return scope;
}
return ScopeProperties.CreateFromState(state, messageProperties);
}

return NestedDiagnosticsLogicalContext.Push(state);
Expand Down
34 changes: 16 additions & 18 deletions src/NLog.Extensions.Logging/NLogMessageParameterList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ internal class NLogMessageParameterList : IList<NLog.MessageTemplates.MessageTem

public NLogMessageParameterList(IReadOnlyList<KeyValuePair<string, object>> parameterList, bool includesOriginalMessage)
{
List<KeyValuePair<string, object>> validParameterList = includesOriginalMessage ? null : new List<KeyValuePair<string, object>>();
var validParameterList = includesOriginalMessage ? null : new List<KeyValuePair<string, object>>();
for (int i = 0; i < parameterList.Count; ++i)
{
if (!string.IsNullOrEmpty(parameterList[i].Key) && (parameterList[i].Key != NLogLogger.OriginalFormatPropertyName || i == parameterList.Count - 1))
var paramPair = parameterList[i];
bool isNonOriginalFormatName;
if (!string.IsNullOrEmpty(paramPair.Key) && ((isNonOriginalFormatName = paramPair.Key != NLogLogger.OriginalFormatPropertyName) || i == parameterList.Count - 1))
{
if (validParameterList != null)
if (validParameterList != null && isNonOriginalFormatName)
{
if (parameterList[i].Key != NLogLogger.OriginalFormatPropertyName)
validParameterList.Add(parameterList[i]);
validParameterList.Add(paramPair);
}
}
else
Expand All @@ -38,10 +39,7 @@ public NLogMessageParameterList(IReadOnlyList<KeyValuePair<string, object>> para
}
}
}
if (validParameterList != null)
{
validParameterList.Add(new KeyValuePair<string, object>());
}
validParameterList?.Add(new KeyValuePair<string, object>());
_parameterList = validParameterList ?? parameterList;
}

Expand All @@ -65,7 +63,7 @@ public NLog.MessageTemplates.MessageTemplateParameter this[int index]
}
return new NLog.MessageTemplates.MessageTemplateParameter(parameter.Key, parameter.Value, null, captureType);
}
set => throw new NotImplementedException();
set => throw new NotSupportedException();
}

public int Count => _parameterList.Count - 1;
Expand All @@ -74,22 +72,22 @@ public NLog.MessageTemplates.MessageTemplateParameter this[int index]

public void Add(NLog.MessageTemplates.MessageTemplateParameter item)
{
throw new NotImplementedException();
throw new NotSupportedException();
}

public void Clear()
{
throw new NotImplementedException();
throw new NotSupportedException();
}

public bool Contains(NLog.MessageTemplates.MessageTemplateParameter item)
{
throw new NotImplementedException();
throw new NotSupportedException();
}

public void CopyTo(NLog.MessageTemplates.MessageTemplateParameter[] array, int arrayIndex)
{
throw new NotImplementedException();
throw new NotSupportedException();
}

public IEnumerator<NLog.MessageTemplates.MessageTemplateParameter> GetEnumerator()
Expand All @@ -99,22 +97,22 @@ public void CopyTo(NLog.MessageTemplates.MessageTemplateParameter[] array, int a

public int IndexOf(NLog.MessageTemplates.MessageTemplateParameter item)
{
throw new NotImplementedException();
throw new NotSupportedException();
}

public void Insert(int index, NLog.MessageTemplates.MessageTemplateParameter item)
{
throw new NotImplementedException();
throw new NotSupportedException();
}

public bool Remove(NLog.MessageTemplates.MessageTemplateParameter item)
{
throw new NotImplementedException();
throw new NotSupportedException();
}

public void RemoveAt(int index)
{
throw new NotImplementedException();
throw new NotSupportedException();
}

IEnumerator IEnumerable.GetEnumerator()
Expand Down