From 885b26962c0dd0ffbf50a91e3c5622884050b62f Mon Sep 17 00:00:00 2001 From: John Crnjanin Date: Sat, 16 Jan 2016 22:21:00 +1000 Subject: [PATCH 1/4] Enable Event Enrichers from Config Event enrichers implementing the ILogEventEnricher interface (e.g. ThreadIdEnricher, MachineNameEnricher, etc) can be enabled via config, rather than just the Property enricher as was prior. --- .../KeyValuePairs/KeyValuePairSettings.cs | 88 +++++++++++---- .../Settings/AppSettingsTests.cs | 105 ++++++++++++++++++ .../Settings/KeyValuePairSettingsTests.cs | 28 +++++ test/Serilog.Tests/app.config | 5 + test/Serilog.Tests/project.json | 2 +- 5 files changed, 207 insertions(+), 21 deletions(-) diff --git a/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs b/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs index 7b32878bd..b74e9f770 100644 --- a/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs +++ b/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs @@ -32,9 +32,11 @@ class KeyValuePairSettings : ILoggerSettings const string UsingDirective = "using"; const string WriteToDirective = "write-to"; const string MinimumLevelDirective = "minimum-level"; + const string EnrichWithDirective = "enrich:with"; const string EnrichWithPropertyDirective = "enrich:with-property"; const string UsingDirectiveFullFormPrefix = "using:"; + const string EnrichWithEventEnricherPrefix = "enrich:with:"; const string EnrichWithPropertyDirectivePrefix = "enrich:with-property:"; const string WriteToDirectiveRegex = @"^write-to:(?[A-Za-z0-9]*)(\.(?[A-Za-z0-9]*)){0,1}$"; @@ -44,7 +46,8 @@ class KeyValuePairSettings : ILoggerSettings UsingDirective, WriteToDirective, MinimumLevelDirective, - EnrichWithPropertyDirective + EnrichWithPropertyDirective, + EnrichWithDirective }; readonly Dictionary _settings; @@ -71,13 +74,20 @@ public void Configure(LoggerConfiguration loggerConfiguration) loggerConfiguration.MinimumLevel.Is(minimumLevel); } - foreach (var enrichDirective in directives.Where(dir => + foreach (var enrichProperyDirective in directives.Where(dir => dir.Key.StartsWith(EnrichWithPropertyDirectivePrefix) && dir.Key.Length > EnrichWithPropertyDirectivePrefix.Length)) { - var name = enrichDirective.Key.Substring(EnrichWithPropertyDirectivePrefix.Length); - loggerConfiguration.Enrich.WithProperty(name, enrichDirective.Value); + var name = enrichProperyDirective.Key.Substring(EnrichWithPropertyDirectivePrefix.Length); + loggerConfiguration.Enrich.WithProperty(name, enrichProperyDirective.Value); } + var eventEnricherDirectives = directives.Where(dir => + dir.Key.StartsWith(EnrichWithEventEnricherPrefix) && dir.Key.Length > EnrichWithEventEnricherPrefix.Length) + .Select(dir => { + var enricherName = dir.Key.Substring(EnrichWithEventEnricherPrefix.Length); + return !enricherName.EndsWith("Enricher") ? String.Format("{0}Enricher", enricherName) : enricherName; + }); + var splitWriteTo = new Regex(WriteToDirectiveRegex); var sinkDirectives = (from wt in directives @@ -91,36 +101,60 @@ where splitWriteTo.IsMatch(wt.Key) } group call by call.Method).ToList(); - if (sinkDirectives.Any()) + if (sinkDirectives.Any() || eventEnricherDirectives.Any()) { var configurationAssemblies = LoadConfigurationAssemblies(directives); - var sinkConfigurationMethods = FindSinkConfigurationMethods(configurationAssemblies); - foreach (var sinkDirective in sinkDirectives) + if (eventEnricherDirectives.Any()) { - var target = sinkConfigurationMethods - .Where(m => m.Name == sinkDirective.Key && - m.GetParameters().Skip(1).All(p => + var eventEnricherTypes = FindEventEnrichers(configurationAssemblies); + + foreach(var eventEnricherDirective in eventEnricherDirectives) + { + var target = eventEnricherTypes + .Where(e => e.AsType().Name == eventEnricherDirective) + .FirstOrDefault(); + + if (target != null) + { + var instansiatedTarget = Activator.CreateInstance(target.AsType()) as Core.ILogEventEnricher; + loggerConfiguration.Enrich.With(instansiatedTarget); + } + } + + //eventEnricherDirectives + } + + if (sinkDirectives.Any()) + { + var sinkConfigurationMethods = FindSinkConfigurationMethods(configurationAssemblies); + + foreach (var sinkDirective in sinkDirectives) + { + var target = sinkConfigurationMethods + .Where(m => m.Name == sinkDirective.Key && + m.GetParameters().Skip(1).All(p => #if NET40 (p.Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.None #else p.HasDefaultValue #endif || sinkDirective.Any(s => s.Argument == p.Name))) - .OrderByDescending(m => m.GetParameters().Length) - .FirstOrDefault(); + .OrderByDescending(m => m.GetParameters().Length) + .FirstOrDefault(); - if (target != null) - { - var config = loggerConfiguration.WriteTo; + if (target != null) + { + var config = loggerConfiguration.WriteTo; - var call = (from p in target.GetParameters().Skip(1) - let directive = sinkDirective.FirstOrDefault(s => s.Argument == p.Name) - select directive == null ? p.DefaultValue : ConvertToType(directive.Value, p.ParameterType)).ToList(); + var call = (from p in target.GetParameters().Skip(1) + let directive = sinkDirective.FirstOrDefault(s => s.Argument == p.Name) + select directive == null ? p.DefaultValue : ConvertToType(directive.Value, p.ParameterType)).ToList(); - call.Insert(0, config); + call.Insert(0, config); - target.Invoke(null, call.ToArray()); + target.Invoke(null, call.ToArray()); + } } } } @@ -184,5 +218,19 @@ internal static IList FindSinkConfigurationMethods(IEnumerable m.GetParameters()[0].ParameterType == typeof(LoggerSinkConfiguration)) .ToList(); } + + internal static IList FindEventEnrichers(IEnumerable configurationAssemblies) + { + var logEventEnricherInterface = typeof(Core.ILogEventEnricher).GetTypeInfo(); + return configurationAssemblies + .SelectMany(a => a. +#if NET40 + GetTypes().Select(t => t.GetTypeInfo()) +#else + DefinedTypes +#endif + .Where(t => logEventEnricherInterface.IsAssignableFrom(t) && !t.IsAbstract)) + .ToList(); + } } } diff --git a/test/Serilog.Tests/Settings/AppSettingsTests.cs b/test/Serilog.Tests/Settings/AppSettingsTests.cs index 10d855160..33737ec8c 100644 --- a/test/Serilog.Tests/Settings/AppSettingsTests.cs +++ b/test/Serilog.Tests/Settings/AppSettingsTests.cs @@ -4,6 +4,7 @@ using Xunit; using Serilog.Events; using Serilog.Tests.Support; +using Serilog.Context; namespace Serilog.Tests.AppSettings.Tests { @@ -68,6 +69,110 @@ public void CustomPrefixCannotBeSerilog() Assert.Throws(() => new LoggerConfiguration().ReadFrom.AppSettings("serilog")); } + + [Fact] + public void ThreadIdEnricherIsApplied() + { + // Make sure we have the expected key in the App.config + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:ThreadId"]); + + LogEvent evt = null; + var log = new LoggerConfiguration() + .ReadFrom.AppSettings() + .WriteTo.Sink(new DelegatingSink(e => evt = e)) + .CreateLogger(); + + log.Information("Has a ThreadId property with value generated by ThreadIdEnricher"); + + Assert.NotNull(evt); + Assert.NotNull(evt.Properties["ThreadId"]); + Assert.NotNull(evt.Properties["ThreadId"].LiteralValue() as int?); + } +#if !DOTNET5_1 + [Fact] + public void MachineNameEnricherIsApplied() + { + // Make sure we have the expected key in the App.config + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:MachineName"]); + + LogEvent evt = null; + var log = new LoggerConfiguration() + .ReadFrom.AppSettings() + .WriteTo.Sink(new DelegatingSink(e => evt = e)) + .CreateLogger(); + + log.Information("Has a MachineName property with value generated by MachineNameEnricher"); + + Assert.NotNull(evt); + Assert.NotNull(evt.Properties["MachineName"]); + Assert.NotEmpty((string)evt.Properties["MachineName"].LiteralValue()); + } + + [Fact] + public void EnrivonmentUserNameEnricherIsApplied() + { + // Make sure we have the expected key in the App.config + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:EnvironmentUserName"]); + + LogEvent evt = null; + var log = new LoggerConfiguration() + .ReadFrom.AppSettings() + .WriteTo.Sink(new DelegatingSink(e => evt = e)) + .CreateLogger(); + + log.Information("Has a EnrivonmentUserName property with value generated by EnrivonmentUserNameEnricher"); + + Assert.NotNull(evt); + Assert.NotNull(evt.Properties["EnvironmentUserName"]); + Assert.NotEmpty((string)evt.Properties["EnvironmentUserName"].LiteralValue()); + } +#endif + +#if PROCESS + [Fact] + public void ProcessIdEnricherIsApplied() + { + // Make sure we have the expected key in the App.config + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:ProcessId"]); + + LogEvent evt = null; + var log = new LoggerConfiguration() + .ReadFrom.AppSettings() + .WriteTo.Sink(new DelegatingSink(e => evt = e)) + .CreateLogger(); + + log.Information("Has a ProcessId property with value generated by ProcessIdEnricher"); + + Assert.NotNull(evt); + Assert.NotNull(evt.Properties["ProcessId"]); + Assert.NotNull(evt.Properties["ProcessId"].LiteralValue() as int?); + } +#endif + +#if LOGCONTEXT + [Fact] + public void LogContextEnricherIsApplied() + { + // Make sure we have the expected key in the App.config + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:LogContext"]); + + LogEvent evt = null; + var log = new LoggerConfiguration() + .ReadFrom.AppSettings() + .WriteTo.Sink(new DelegatingSink(e => evt = e)) + .CreateLogger(); + + using (LogContext.PushProperty("A", 1)) + { + log.Information("Has a LogContext property with value generated by LogContextEnricher"); + } + + Assert.NotNull(evt); + Assert.NotNull(evt.Properties["A"]); + Assert.NotNull(evt.Properties["A"].LiteralValue() as int?); + Assert.Equal(1, (int)evt.Properties["A"].LiteralValue()); + } +#endif } } #endif diff --git a/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs b/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs index 089f46171..755463184 100644 --- a/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs +++ b/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs @@ -80,6 +80,34 @@ public void FindsConfigurationMethodsWithinAnAssembly() Assert.True(configurationMethods.Contains("Trace")); } + [Fact] + public void FindsEventEnrichersWithinAnAssembly() + { + var eventEnrichers = KeyValuePairSettings + .FindEventEnrichers(new[] { typeof(RollingFileSink) +#if DNXCORE50 + .GetTypeInfo() +#endif + .Assembly + }) + .Select(m => m.Name) + .Distinct() + .ToList(); + + +#if LOGCONTEXT + Assert.True(eventEnrichers.Contains("LogContextEnricher")); +#endif +#if !DOTNET5_1 + Assert.True(eventEnrichers.Contains("EnvironmentUserNameEnricher")); + Assert.True(eventEnrichers.Contains("MachineNameEnricher")); +#endif +#if PROCESS + Assert.True(eventEnrichers.Contains("ProcessIdEnricher")); +#endif + Assert.True(eventEnrichers.Contains("ThreadIdEnricher")); + } + [Fact] public void PropertyEnrichmentIsApplied() { diff --git a/test/Serilog.Tests/app.config b/test/Serilog.Tests/app.config index 346514b7e..c8558df9f 100644 --- a/test/Serilog.Tests/app.config +++ b/test/Serilog.Tests/app.config @@ -4,5 +4,10 @@ + + + + + \ No newline at end of file diff --git a/test/Serilog.Tests/project.json b/test/Serilog.Tests/project.json index a28098071..0aa01e790 100644 --- a/test/Serilog.Tests/project.json +++ b/test/Serilog.Tests/project.json @@ -17,7 +17,7 @@ "dnx451": { "compilationOptions": { "keyFile": "../../assets/Serilog.snk", - "define": [ "APPSETTINGS", "LOGCONTEXT", "FILE_IO", "PERIODIC_BATCHING", "INTERNAL_TESTS" ] + "define": [ "APPSETTINGS", "LOGCONTEXT", "PROCESS", "FILE_IO", "PERIODIC_BATCHING", "INTERNAL_TESTS" ] }, "frameworkAssemblies": { "System.Configuration": "" From e35d82b62fc01c9dd1a215eee5832608f63b56f1 Mon Sep 17 00:00:00 2001 From: John Crnjanin Date: Sun, 17 Jan 2016 09:44:42 +1000 Subject: [PATCH 2/4] Event enrichers by settings uses extension methods Keeps syntax in settings the same as if using config object and uses established extension methods as entry points rather than directly activating the enrichers. --- .../KeyValuePairs/KeyValuePairSettings.cs | 54 +++++++++---------- .../Settings/AppSettingsTests.cs | 10 ++-- .../Settings/KeyValuePairSettingsTests.cs | 12 ++--- test/Serilog.Tests/app.config | 10 ++-- 4 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs b/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs index b74e9f770..8612f313c 100644 --- a/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs +++ b/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs @@ -32,11 +32,11 @@ class KeyValuePairSettings : ILoggerSettings const string UsingDirective = "using"; const string WriteToDirective = "write-to"; const string MinimumLevelDirective = "minimum-level"; - const string EnrichWithDirective = "enrich:with"; + const string EnrichWithDirective = "enrich"; const string EnrichWithPropertyDirective = "enrich:with-property"; const string UsingDirectiveFullFormPrefix = "using:"; - const string EnrichWithEventEnricherPrefix = "enrich:with:"; + const string EnrichWithEventEnricherPrefix = "enrich:"; const string EnrichWithPropertyDirectivePrefix = "enrich:with-property:"; const string WriteToDirectiveRegex = @"^write-to:(?[A-Za-z0-9]*)(\.(?[A-Za-z0-9]*)){0,1}$"; @@ -82,11 +82,8 @@ public void Configure(LoggerConfiguration loggerConfiguration) } var eventEnricherDirectives = directives.Where(dir => - dir.Key.StartsWith(EnrichWithEventEnricherPrefix) && dir.Key.Length > EnrichWithEventEnricherPrefix.Length) - .Select(dir => { - var enricherName = dir.Key.Substring(EnrichWithEventEnricherPrefix.Length); - return !enricherName.EndsWith("Enricher") ? String.Format("{0}Enricher", enricherName) : enricherName; - }); + dir.Key.StartsWith(EnrichWithEventEnricherPrefix) && !dir.Key.StartsWith(EnrichWithPropertyDirectivePrefix) && dir.Key.Length > EnrichWithEventEnricherPrefix.Length) + .Select(dir => dir.Key.Substring(EnrichWithEventEnricherPrefix.Length)); var splitWriteTo = new Regex(WriteToDirectiveRegex); @@ -107,22 +104,27 @@ where splitWriteTo.IsMatch(wt.Key) if (eventEnricherDirectives.Any()) { - var eventEnricherTypes = FindEventEnrichers(configurationAssemblies); + var eventEnricherTypes = FindEventEnricherConfigurationMethods(configurationAssemblies); foreach(var eventEnricherDirective in eventEnricherDirectives) { var target = eventEnricherTypes - .Where(e => e.AsType().Name == eventEnricherDirective) + .Where(e => e.Name == eventEnricherDirective && + e.GetParameters().Skip(1).All(p => +#if NET40 + (p.Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.None +#else + p.HasDefaultValue +#endif + )) + .OrderByDescending(m => m.GetParameters().Length) .FirstOrDefault(); if (target != null) { - var instansiatedTarget = Activator.CreateInstance(target.AsType()) as Core.ILogEventEnricher; - loggerConfiguration.Enrich.With(instansiatedTarget); + target.Invoke(null, new object[] { loggerConfiguration.Enrich }); } } - - //eventEnricherDirectives } if (sinkDirectives.Any()) @@ -204,6 +206,16 @@ internal static object ConvertToType(string value, Type toType) } internal static IList FindSinkConfigurationMethods(IEnumerable configurationAssemblies) + { + return FindConfigurationMethods(configurationAssemblies, typeof(LoggerSinkConfiguration)); + } + + internal static IList FindEventEnricherConfigurationMethods(IEnumerable configurationAssemblies) + { + return FindConfigurationMethods(configurationAssemblies, typeof(LoggerEnrichmentConfiguration)); + } + + internal static IList FindConfigurationMethods(IEnumerable configurationAssemblies, Type configType) { return configurationAssemblies .SelectMany(a => a. @@ -215,21 +227,7 @@ internal static IList FindSinkConfigurationMethods(IEnumerable t.GetTypeInfo()).Where(t => t.IsSealed && t.IsAbstract && !t.IsNested)) .SelectMany(t => t.DeclaredMethods) .Where(m => m.IsStatic && m.IsPublic && m.IsDefined(typeof(ExtensionAttribute), false)) - .Where(m => m.GetParameters()[0].ParameterType == typeof(LoggerSinkConfiguration)) - .ToList(); - } - - internal static IList FindEventEnrichers(IEnumerable configurationAssemblies) - { - var logEventEnricherInterface = typeof(Core.ILogEventEnricher).GetTypeInfo(); - return configurationAssemblies - .SelectMany(a => a. -#if NET40 - GetTypes().Select(t => t.GetTypeInfo()) -#else - DefinedTypes -#endif - .Where(t => logEventEnricherInterface.IsAssignableFrom(t) && !t.IsAbstract)) + .Where(m => m.GetParameters()[0].ParameterType == configType) .ToList(); } } diff --git a/test/Serilog.Tests/Settings/AppSettingsTests.cs b/test/Serilog.Tests/Settings/AppSettingsTests.cs index 33737ec8c..be4b6a3cb 100644 --- a/test/Serilog.Tests/Settings/AppSettingsTests.cs +++ b/test/Serilog.Tests/Settings/AppSettingsTests.cs @@ -74,7 +74,7 @@ public void CustomPrefixCannotBeSerilog() public void ThreadIdEnricherIsApplied() { // Make sure we have the expected key in the App.config - Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:ThreadId"]); + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:WithThreadId"]); LogEvent evt = null; var log = new LoggerConfiguration() @@ -93,7 +93,7 @@ public void ThreadIdEnricherIsApplied() public void MachineNameEnricherIsApplied() { // Make sure we have the expected key in the App.config - Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:MachineName"]); + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:WithMachineName"]); LogEvent evt = null; var log = new LoggerConfiguration() @@ -112,7 +112,7 @@ public void MachineNameEnricherIsApplied() public void EnrivonmentUserNameEnricherIsApplied() { // Make sure we have the expected key in the App.config - Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:EnvironmentUserName"]); + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:WithEnvironmentUserName"]); LogEvent evt = null; var log = new LoggerConfiguration() @@ -133,7 +133,7 @@ public void EnrivonmentUserNameEnricherIsApplied() public void ProcessIdEnricherIsApplied() { // Make sure we have the expected key in the App.config - Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:ProcessId"]); + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:WithProcessId"]); LogEvent evt = null; var log = new LoggerConfiguration() @@ -154,7 +154,7 @@ public void ProcessIdEnricherIsApplied() public void LogContextEnricherIsApplied() { // Make sure we have the expected key in the App.config - Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:with:LogContext"]); + Assert.NotNull(ConfigurationManager.AppSettings["serilog:enrich:FromLogContext"]); LogEvent evt = null; var log = new LoggerConfiguration() diff --git a/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs b/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs index 755463184..26059b6b3 100644 --- a/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs +++ b/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs @@ -84,7 +84,7 @@ public void FindsConfigurationMethodsWithinAnAssembly() public void FindsEventEnrichersWithinAnAssembly() { var eventEnrichers = KeyValuePairSettings - .FindEventEnrichers(new[] { typeof(RollingFileSink) + .FindEventEnricherConfigurationMethods(new[] { typeof(RollingFileSink) #if DNXCORE50 .GetTypeInfo() #endif @@ -96,16 +96,16 @@ public void FindsEventEnrichersWithinAnAssembly() #if LOGCONTEXT - Assert.True(eventEnrichers.Contains("LogContextEnricher")); + Assert.True(eventEnrichers.Contains("FromLogContext")); #endif #if !DOTNET5_1 - Assert.True(eventEnrichers.Contains("EnvironmentUserNameEnricher")); - Assert.True(eventEnrichers.Contains("MachineNameEnricher")); + Assert.True(eventEnrichers.Contains("WithEnvironmentUserName")); + Assert.True(eventEnrichers.Contains("WithMachineName")); #endif #if PROCESS - Assert.True(eventEnrichers.Contains("ProcessIdEnricher")); + Assert.True(eventEnrichers.Contains("WithProcessId")); #endif - Assert.True(eventEnrichers.Contains("ThreadIdEnricher")); + Assert.True(eventEnrichers.Contains("WithThreadId")); } [Fact] diff --git a/test/Serilog.Tests/app.config b/test/Serilog.Tests/app.config index c8558df9f..9a9dafa57 100644 --- a/test/Serilog.Tests/app.config +++ b/test/Serilog.Tests/app.config @@ -4,10 +4,10 @@ - - - - - + + + + + \ No newline at end of file From 18cb4c09c55bb349fb80576c20de27e1d7ea6469 Mon Sep 17 00:00:00 2001 From: John Crnjanin Date: Sun, 17 Jan 2016 16:18:02 +1000 Subject: [PATCH 3/4] Refactored how directives are applied to loggerConfiguration --- .../KeyValuePairs/KeyValuePairSettings.cs | 84 +++++++++---------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs b/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs index 8612f313c..e347d0658 100644 --- a/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs +++ b/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs @@ -90,11 +90,11 @@ public void Configure(LoggerConfiguration loggerConfiguration) var sinkDirectives = (from wt in directives where splitWriteTo.IsMatch(wt.Key) let match = splitWriteTo.Match(wt.Key) - let call = new + let call = new MethodArgumentValue { Method = match.Groups["method"].Value, Argument = match.Groups["argument"].Value, - wt.Value + Value = wt.Value } group call by call.Method).ToList(); @@ -102,61 +102,48 @@ where splitWriteTo.IsMatch(wt.Key) { var configurationAssemblies = LoadConfigurationAssemblies(directives); - if (eventEnricherDirectives.Any()) - { - var eventEnricherTypes = FindEventEnricherConfigurationMethods(configurationAssemblies); + ApplyDirectives(eventEnricherDirectives, () => FindEventEnricherConfigurationMethods(configurationAssemblies), loggerConfiguration.Enrich); + ApplyDirectives(sinkDirectives, () => FindSinkConfigurationMethods(configurationAssemblies), loggerConfiguration.WriteTo); + } + } - foreach(var eventEnricherDirective in eventEnricherDirectives) - { - var target = eventEnricherTypes - .Where(e => e.Name == eventEnricherDirective && - e.GetParameters().Skip(1).All(p => -#if NET40 - (p.Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.None -#else - p.HasDefaultValue -#endif - )) - .OrderByDescending(m => m.GetParameters().Length) - .FirstOrDefault(); - - if (target != null) - { - target.Invoke(null, new object[] { loggerConfiguration.Enrich }); - } - } - } + private static void ApplyDirectives(IEnumerable directives, Func> getConfigurationMethods, object loggerConfigMethod) + { + var directivesGrouped = directives.Select(d => new MethodArgumentValue { Method = d }).GroupBy(m => m.Method).ToList(); + ApplyDirectives(directivesGrouped, getConfigurationMethods, loggerConfigMethod); + } - if (sinkDirectives.Any()) - { - var sinkConfigurationMethods = FindSinkConfigurationMethods(configurationAssemblies); - foreach (var sinkDirective in sinkDirectives) - { - var target = sinkConfigurationMethods - .Where(m => m.Name == sinkDirective.Key && - m.GetParameters().Skip(1).All(p => + private static void ApplyDirectives(List> directives, Func> getConfigurationMethods, object loggerConfigMethod) + { + if (directives.Any()) + { + var configurationMethods = getConfigurationMethods(); + + foreach (var directiveInfo in directives) + { + var target = configurationMethods + .Where(m => m.Name == directiveInfo.Key && + m.GetParameters().Skip(1).All(p => #if NET40 (p.Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.None #else p.HasDefaultValue #endif - || sinkDirective.Any(s => s.Argument == p.Name))) - .OrderByDescending(m => m.GetParameters().Length) - .FirstOrDefault(); + || directiveInfo.Any(s => s.Argument == p.Name))) + .OrderByDescending(m => m.GetParameters().Length) + .FirstOrDefault(); - if (target != null) - { - var config = loggerConfiguration.WriteTo; + if (target != null) + { - var call = (from p in target.GetParameters().Skip(1) - let directive = sinkDirective.FirstOrDefault(s => s.Argument == p.Name) - select directive == null ? p.DefaultValue : ConvertToType(directive.Value, p.ParameterType)).ToList(); + var call = (from p in target.GetParameters().Skip(1) + let directive = directiveInfo.FirstOrDefault(s => s.Argument == p.Name) + select directive == null ? p.DefaultValue : ConvertToType(directive.Value, p.ParameterType)).ToList(); - call.Insert(0, config); + call.Insert(0, loggerConfigMethod); - target.Invoke(null, call.ToArray()); - } + target.Invoke(null, call.ToArray()); } } } @@ -230,5 +217,12 @@ internal static IList FindConfigurationMethods(IEnumerable .Where(m => m.GetParameters()[0].ParameterType == configType) .ToList(); } + + private class MethodArgumentValue + { + public string Method { get; set; } + public string Argument { get; set; } + public string Value { get; set; } + } } } From 54fde6c39c08401a3b4ce9e45cb06d5f3eb80bf5 Mon Sep 17 00:00:00 2001 From: John Crnjanin Date: Sun, 17 Jan 2016 21:57:26 +1000 Subject: [PATCH 4/4] Event enrichers from config refactoring --- .../KeyValuePairs/KeyValuePairSettings.cs | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs b/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs index e347d0658..3c6ad9cc4 100644 --- a/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs +++ b/src/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs @@ -81,10 +81,6 @@ public void Configure(LoggerConfiguration loggerConfiguration) loggerConfiguration.Enrich.WithProperty(name, enrichProperyDirective.Value); } - var eventEnricherDirectives = directives.Where(dir => - dir.Key.StartsWith(EnrichWithEventEnricherPrefix) && !dir.Key.StartsWith(EnrichWithPropertyDirectivePrefix) && dir.Key.Length > EnrichWithEventEnricherPrefix.Length) - .Select(dir => dir.Key.Substring(EnrichWithEventEnricherPrefix.Length)); - var splitWriteTo = new Regex(WriteToDirectiveRegex); var sinkDirectives = (from wt in directives @@ -98,53 +94,57 @@ where splitWriteTo.IsMatch(wt.Key) } group call by call.Method).ToList(); + var eventEnricherDirectives = (from er in directives + where er.Key.StartsWith(EnrichWithEventEnricherPrefix) && !er.Key.StartsWith(EnrichWithPropertyDirectivePrefix) && er.Key.Length > EnrichWithEventEnricherPrefix.Length + let match = er.Key.Substring(EnrichWithEventEnricherPrefix.Length) + let call = new MethodArgumentValue + { + Method = match + } + group call by call.Method).ToList(); + if (sinkDirectives.Any() || eventEnricherDirectives.Any()) { var configurationAssemblies = LoadConfigurationAssemblies(directives); - ApplyDirectives(eventEnricherDirectives, () => FindEventEnricherConfigurationMethods(configurationAssemblies), loggerConfiguration.Enrich); - ApplyDirectives(sinkDirectives, () => FindSinkConfigurationMethods(configurationAssemblies), loggerConfiguration.WriteTo); - } - } + if (sinkDirectives.Any()) + { + ApplyDirectives(sinkDirectives, FindSinkConfigurationMethods(configurationAssemblies), loggerConfiguration.WriteTo); + } - private static void ApplyDirectives(IEnumerable directives, Func> getConfigurationMethods, object loggerConfigMethod) - { - var directivesGrouped = directives.Select(d => new MethodArgumentValue { Method = d }).GroupBy(m => m.Method).ToList(); - ApplyDirectives(directivesGrouped, getConfigurationMethods, loggerConfigMethod); + if (eventEnricherDirectives.Any()) + { + ApplyDirectives(eventEnricherDirectives, FindEventEnricherConfigurationMethods(configurationAssemblies), loggerConfiguration.Enrich); + } + } } - - private static void ApplyDirectives(List> directives, Func> getConfigurationMethods, object loggerConfigMethod) + private static void ApplyDirectives(List> directives, IList configurationMethods, object loggerConfigMethod) { - if (directives.Any()) + foreach (var directiveInfo in directives) { - var configurationMethods = getConfigurationMethods(); - - foreach (var directiveInfo in directives) - { - var target = configurationMethods - .Where(m => m.Name == directiveInfo.Key && - m.GetParameters().Skip(1).All(p => + var target = configurationMethods + .Where(m => m.Name == directiveInfo.Key && + m.GetParameters().Skip(1).All(p => #if NET40 - (p.Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.None + (p.Attributes & ParameterAttributes.HasDefault) != ParameterAttributes.None #else - p.HasDefaultValue + p.HasDefaultValue #endif - || directiveInfo.Any(s => s.Argument == p.Name))) - .OrderByDescending(m => m.GetParameters().Length) - .FirstOrDefault(); + || directiveInfo.Any(s => s.Argument == p.Name))) + .OrderByDescending(m => m.GetParameters().Length) + .FirstOrDefault(); - if (target != null) - { + if (target != null) + { - var call = (from p in target.GetParameters().Skip(1) - let directive = directiveInfo.FirstOrDefault(s => s.Argument == p.Name) - select directive == null ? p.DefaultValue : ConvertToType(directive.Value, p.ParameterType)).ToList(); + var call = (from p in target.GetParameters().Skip(1) + let directive = directiveInfo.FirstOrDefault(s => s.Argument == p.Name) + select directive == null ? p.DefaultValue : ConvertToType(directive.Value, p.ParameterType)).ToList(); - call.Insert(0, loggerConfigMethod); + call.Insert(0, loggerConfigMethod); - target.Invoke(null, call.ToArray()); - } + target.Invoke(null, call.ToArray()); } } }