diff --git a/src/Serilog/Core/ForContextExtension.cs b/src/Serilog/Core/ForContextExtension.cs new file mode 100644 index 000000000..92e1dc0c1 --- /dev/null +++ b/src/Serilog/Core/ForContextExtension.cs @@ -0,0 +1,34 @@ +using Serilog.Events; + +namespace Serilog +{ + /// + /// Extension method 'ForContext' for ILogger. + /// + public static class ForContextExtension + { + /// + /// Create a logger that enriches log events with the specified property based on log event level. + /// + /// The type of the property value. + /// The logger + /// The log event level used to determine if log is enriched with property. + /// The name of the property. Must be non-empty. + /// The property value. + /// If true, the value will be serialized as a structured + /// object if possible; if false, the object will be recorded as a scalar or simple array. + /// A logger that will enrich log events as specified. + /// + public static ILogger ForContext( + this ILogger logger, + LogEventLevel level, + string propertyName, + TValue value, + bool destructureObjects = false) + { + return !logger.IsEnabled(level) + ? logger + : logger.ForContext(propertyName, value, destructureObjects); + } + } +} diff --git a/test/Serilog.Tests/Core/ForContextExtensionsTests.cs b/test/Serilog.Tests/Core/ForContextExtensionsTests.cs new file mode 100644 index 000000000..d8ba20a59 --- /dev/null +++ b/test/Serilog.Tests/Core/ForContextExtensionsTests.cs @@ -0,0 +1,61 @@ +using System; +using Serilog.Events; +using Serilog.Tests.Support; +using Xunit; + +namespace Serilog.Tests.Core +{ + public class ForContextExtensionsTests + { + [Theory] + [InlineData(LogEventLevel.Debug, LogEventLevel.Debug)] + [InlineData(LogEventLevel.Debug, LogEventLevel.Information)] + [InlineData(LogEventLevel.Debug, LogEventLevel.Error)] + [InlineData(LogEventLevel.Debug, LogEventLevel.Fatal)] + [InlineData(LogEventLevel.Debug, LogEventLevel.Warning)] + public void ShouldEnrichLogEventWhenLevelIsSameOrHigherThanMinLevel(LogEventLevel logMinLevel, LogEventLevel propertLogLevel) + { + // Arrange + var propValue = Guid.NewGuid(); + var propKey = Some.String(); + var sink = new CollectingSink(); + var logger = new LoggerConfiguration() + .MinimumLevel.Is(logMinLevel) + .WriteTo.Sink(sink) + .CreateLogger(); + + // Act + logger.ForContext(propertLogLevel, propKey, propValue) + .Write(logMinLevel, string.Empty); + + // Assert + Assert.True(sink.SingleEvent.Properties.ContainsKey(propKey)); + Assert.Equal(sink.SingleEvent.Properties[propKey].LiteralValue(), propValue); + } + + [Theory] + [InlineData(LogEventLevel.Debug, LogEventLevel.Verbose)] + [InlineData(LogEventLevel.Information, LogEventLevel.Debug)] + [InlineData(LogEventLevel.Warning, LogEventLevel.Information)] + [InlineData(LogEventLevel.Error, LogEventLevel.Warning)] + [InlineData(LogEventLevel.Fatal, LogEventLevel.Error)] + public void ShouldNotEnrichLogEventsWhenMinLevelIsHigherThanProvidedLogLevel(LogEventLevel logMinLevel, LogEventLevel propertLogLevel) + { + // Arrange + var propValue = Guid.NewGuid(); + var propKey = Some.String(); + var sink = new CollectingSink(); + var logger = new LoggerConfiguration() + .MinimumLevel.Is(logMinLevel) + .WriteTo.Sink(sink) + .CreateLogger(); + + // Act + logger.ForContext(propertLogLevel, propKey, propValue) + .Write(logMinLevel, string.Empty); + + // Assert + Assert.True(!sink.SingleEvent.Properties.ContainsKey(propKey)); + } + } +}