Skip to content

Commit

Permalink
NLogProviderOptions with support for CaptureEventId.EventId + EventName
Browse files Browse the repository at this point in the history
  • Loading branch information
snakefoot committed Nov 21, 2021
1 parent 0f63040 commit 603a234
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 36 deletions.
18 changes: 13 additions & 5 deletions src/NLog.Extensions.Logging/Logging/EventIdCaptureType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,28 @@ public enum EventIdCaptureType
/// </summary>
None = 0,
/// <summary>
/// Capture entire <see cref="Microsoft.Extensions.Logging.EventId"/> as "EventId"-property (with boxing)
/// Capture entire <see cref="Microsoft.Extensions.Logging.EventId.Id"/> as "EventId"-property
/// </summary>
EventId = 1,
/// <summary>
/// Capture entire <see cref="Microsoft.Extensions.Logging.EventId.Name"/> as "EventName"-property
/// </summary>
EventName = 2,
/// <summary>
/// Capture entire <see cref="Microsoft.Extensions.Logging.EventId"/> as "EventId"-property (with boxing)
/// </summary>
EventIdStruct = 4,
/// <summary>
/// Capture <see cref="Microsoft.Extensions.Logging.EventId.Id"/> as "EventId_Id"-property.
/// </summary>
EventId_Id = 2,
EventId_Id = 8,
/// <summary>
/// Capture <see cref="Microsoft.Extensions.Logging.EventId.Name"/> as "EventId_Name"-property.
/// </summary>
EventId_Name = 4,
EventId_Name = 16,
/// <summary>
/// Capture all properties (Legacy)
/// Capture all old properties (Legacy)
/// </summary>
All = EventId | EventId_Id | EventId_Name,
Legacy = EventIdStruct | EventId_Id | EventId_Name,
}
}
35 changes: 22 additions & 13 deletions src/NLog.Extensions.Logging/Logging/NLogLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,23 +299,32 @@ private void CaptureEventIdProperties(LogEventInfo logEvent, EventId eventId)
var captureEventId = _options.CaptureEventId;
if (captureEventId != EventIdCaptureType.None && IncludeEventIdProperties(eventId))
{
// Attempt to reuse the same string-allocations based on the current <see cref="NLogProviderOptions.EventIdSeparator"/>
var eventIdPropertyNames = _eventIdPropertyNames ?? new Tuple<string, string, string>(null, null, null);
var eventIdSeparator = _options.EventIdSeparator ?? String.Empty;
if (!ReferenceEquals(eventIdPropertyNames.Item1, eventIdSeparator))
if ((captureEventId & EventIdCaptureType.EventId) != 0)
logEvent.Properties[nameof(EventId)] = eventId.Id == 0 ? ZeroEventId : GetEventId(eventId.Id);

if ((captureEventId & EventIdCaptureType.EventName) != 0 && eventId.Name != null)
logEvent.Properties["EventName"] = eventId.Name;

if ((captureEventId & EventIdCaptureType.Legacy) != 0)
{
// Perform atomic cache update of the string-allocations matching the current separator
_eventIdPropertyNames = eventIdPropertyNames = CreateEventIdPropertyNames(eventIdSeparator);
}
// Attempt to reuse the same string-allocations based on the current <see cref="NLogProviderOptions.EventIdSeparator"/>
var eventIdPropertyNames = _eventIdPropertyNames ?? new Tuple<string, string, string>(null, null, null);
var eventIdSeparator = _options.EventIdSeparator ?? String.Empty;
if (!ReferenceEquals(eventIdPropertyNames.Item1, eventIdSeparator))
{
// Perform atomic cache update of the string-allocations matching the current separator
_eventIdPropertyNames = eventIdPropertyNames = CreateEventIdPropertyNames(eventIdSeparator);
}

if ((captureEventId & EventIdCaptureType.EventId_Id) != 0)
logEvent.Properties[eventIdPropertyNames.Item2] = eventId.Id == 0 ? ZeroEventId : GetEventId(eventId.Id);
if ((captureEventId & EventIdCaptureType.EventId_Id) != 0)
logEvent.Properties[eventIdPropertyNames.Item2] = eventId.Id == 0 ? ZeroEventId : GetEventId(eventId.Id);

if ((captureEventId & EventIdCaptureType.EventId_Name) != 0 && eventId.Name != null)
logEvent.Properties[eventIdPropertyNames.Item3] = eventId.Name;
if ((captureEventId & EventIdCaptureType.EventId_Name) != 0 && eventId.Name != null)
logEvent.Properties[eventIdPropertyNames.Item3] = eventId.Name;

if ((captureEventId & EventIdCaptureType.EventId) != 0)
logEvent.Properties[nameof(EventId)] = eventId;
if ((captureEventId & EventIdCaptureType.EventIdStruct) != 0)
logEvent.Properties[nameof(EventId)] = eventId;
}
}
}

Expand Down
9 changes: 6 additions & 3 deletions src/NLog.Extensions.Logging/Logging/NLogProviderOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,23 @@ public class NLogProviderOptions
/// <summary>
/// Separator between for EventId.Id and EventId.Name. Default to _
/// </summary>
/// <remarks>
/// Only relevant for <see cref="EventIdCaptureType.EventId_Id"/>, <see cref="EventIdCaptureType.EventId_Name"/> or <see cref="EventIdCaptureType.Legacy"/>
/// </remarks>
public string EventIdSeparator { get; set; } = "_";

/// <summary>
/// Skip capture of "EventId_Id" and "EventId_Name" as <see cref="LogEventInfo.Properties" /> when <c>default(EventId)</c>
/// Skip skip capture of <see cref="Microsoft.Extensions.Logging.EventId"/> in <see cref="LogEventInfo.Properties" /> when <c>default(EventId)</c>
/// </summary>
public bool IgnoreEmptyEventId { get; set; } = true;

/// <summary>
/// Control capture of <see cref="Microsoft.Extensions.Logging.EventId"/> as "EventId"-property.
/// </summary>
/// <remarks>
/// Enabling capture of the entire "EventId" will increase memory allocation and gives a performance hit. Faster to use "EventId_Id" + "EventId_Name".
/// Enabling capture of the entire "EventId" will increase memory allocation and gives a performance hit. Faster to use "EventId" + "EventName".
/// </remarks>
public EventIdCaptureType CaptureEventId { get; set; } = EventIdCaptureType.EventId_Id | EventIdCaptureType.EventId_Name;
public EventIdCaptureType CaptureEventId { get; set; } = EventIdCaptureType.EventId | EventIdCaptureType.EventName;

/// <summary>
/// Enable structured logging by capturing message template parameters with support for "@" and "$". Enables use of ${message:raw=true}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ public void AddNLog_LoggerFactory_LogInfo_ShouldLogToNLog()

[Theory]
[InlineData("EventId", "eventId_2", true)]
[InlineData("EventId_Name", "eventId_2", true)]
[InlineData("EventName", "", true)]
[InlineData("EventId_Id", "2", true)]
[InlineData("EventId", "", false)]
[InlineData("EventId_Name", "eventId_2", false)]
[InlineData("EventId_Id", "2", false)]
[InlineData("EventId_Name", "eventId_2", true)]
[InlineData("EventId", "2", false)]
[InlineData("EventName", "eventId_2", false)]
[InlineData("EventId_Id", "", false)]
[InlineData("EventId_Name", "", false)]
[Obsolete("Instead use ILoggingBuilder.AddNLog() or IHostBuilder.UseNLog()")]
public void AddNLog_LoggerFactory_LogInfoWithEventId_ShouldLogToNLogWithEventId(string eventPropery, string expectedEventInLog, bool captureEntireEventId)
{
Expand All @@ -45,7 +47,7 @@ public void AddNLog_LoggerFactory_LogInfoWithEventId_ShouldLogToNLogWithEventId(
var config = CreateConfigWithMemoryTarget(out var memoryTarget, $"${{event-properties:{eventPropery}}} - ${{message}}");

// Act
loggerFactory.AddNLog(new NLogProviderOptions { EventIdSeparator = "_", CaptureEventId = captureEntireEventId ? EventIdCaptureType.All : EventIdCaptureType.EventId_Id | EventIdCaptureType.EventId_Name });
loggerFactory.AddNLog(new NLogProviderOptions { EventIdSeparator = "_", CaptureEventId = captureEntireEventId ? EventIdCaptureType.Legacy : (EventIdCaptureType.EventId | EventIdCaptureType.EventName) });
LogManager.Configuration = config;
var logger = loggerFactory.CreateLogger("logger1");
logger.LogInformation(new EventId(2, "eventId_2"), "test message with {0} arg", 1);
Expand Down Expand Up @@ -98,17 +100,19 @@ public void AddNLog_LoggingBuilder_LogInfo_ShouldLogToNLog()

[Theory]
[InlineData("EventId", "eventId2", true)]
[InlineData("EventName", "", true)]
[InlineData("EventId_Name", "eventId2", true)]
[InlineData("EventId_Id", "2", true)]
[InlineData("EventId", "", false)]
[InlineData("EventId_Name", "eventId2", false)]
[InlineData("EventId_Id", "2", false)]
[InlineData("EventId", "2", false)]
[InlineData("EventName", "eventId2", false)]
[InlineData("EventId_Id", "", false)]
[InlineData("EventId_Name", "", false)]
public void AddNLog_LoggingBuilder_LogInfoWithEventId_ShouldLogToNLogWithEventId(string eventPropery, string expectedEventInLog, bool captureEntireEventId)
{
// Arrange
ILoggingBuilder builder = new LoggingBuilderStub();
var config = CreateConfigWithMemoryTarget(out var memoryTarget, $"${{event-properties:{eventPropery}}} - ${{message}}");
var options = new NLogProviderOptions { EventIdSeparator = "_", CaptureEventId = captureEntireEventId ? EventIdCaptureType.All : EventIdCaptureType.EventId_Id | EventIdCaptureType.EventId_Name };
var options = new NLogProviderOptions { EventIdSeparator = "_", CaptureEventId = captureEntireEventId ? EventIdCaptureType.Legacy : (EventIdCaptureType.EventId | EventIdCaptureType.EventName) };

// Act
builder.AddNLog(config, options);
Expand Down
8 changes: 2 additions & 6 deletions test/NLog.Extensions.Logging.Tests/nlog.config
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true" >

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="Memory" name="target1"
layout="${logger}|${uppercase:${level}}|${message} ${exception}|${event-properties:EventId_Id}${event-properties:ParameterCount}${scopeproperty:item=scope1}" />

layout="${logger}|${uppercase:${level}}|${message} ${exception}|${event-properties:EventId}${event-properties:ParameterCount}${scopeproperty:item=scope1}" />
</targets>

<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Trace" writeTo="target1" />

</rules>
</nlog>

0 comments on commit 603a234

Please sign in to comment.