Skip to content

Add support and tests for more configuration methods #140

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

Merged
merged 9 commits into from
Oct 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ internal static MethodInfo SelectConfigurationMethod(IEnumerable<MethodInfo> can
.FirstOrDefault();
}

internal static IList<MethodInfo> FindSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
static IList<MethodInfo> FindSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
{
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerSinkConfiguration));
if (configurationAssemblies.Contains(typeof(LoggerSinkConfiguration).GetTypeInfo().Assembly))
Expand All @@ -371,14 +371,15 @@ internal static IList<MethodInfo> FindSinkConfigurationMethods(IReadOnlyCollecti
return found;
}

internal static IList<MethodInfo> FindAuditSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
static IList<MethodInfo> FindAuditSinkConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
{
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerAuditSinkConfiguration));

if (configurationAssemblies.Contains(typeof(LoggerAuditSinkConfiguration).GetTypeInfo().Assembly))
found.AddRange(SurrogateConfigurationMethods.AuditTo);
return found;
}

internal static IList<MethodInfo> FindFilterConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
static IList<MethodInfo> FindFilterConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
{
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerFilterConfiguration));
if (configurationAssemblies.Contains(typeof(LoggerFilterConfiguration).GetTypeInfo().Assembly))
Expand All @@ -387,7 +388,7 @@ internal static IList<MethodInfo> FindFilterConfigurationMethods(IReadOnlyCollec
return found;
}

internal static IList<MethodInfo> FindDestructureConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
static IList<MethodInfo> FindDestructureConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
{
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerDestructuringConfiguration));
if (configurationAssemblies.Contains(typeof(LoggerDestructuringConfiguration).GetTypeInfo().Assembly))
Expand All @@ -396,7 +397,7 @@ internal static IList<MethodInfo> FindDestructureConfigurationMethods(IReadOnlyC
return found;
}

internal static IList<MethodInfo> FindEventEnricherConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
static IList<MethodInfo> FindEventEnricherConfigurationMethods(IReadOnlyCollection<Assembly> configurationAssemblies)
{
var found = FindConfigurationExtensionMethods(configurationAssemblies, typeof(LoggerEnrichmentConfiguration));
if (configurationAssemblies.Contains(typeof(LoggerEnrichmentConfiguration).GetTypeInfo().Assembly))
Expand All @@ -405,7 +406,7 @@ internal static IList<MethodInfo> FindEventEnricherConfigurationMethods(IReadOnl
return found;
}

internal static List<MethodInfo> FindConfigurationExtensionMethods(IReadOnlyCollection<Assembly> configurationAssemblies, Type configType)
static List<MethodInfo> FindConfigurationExtensionMethods(IReadOnlyCollection<Assembly> configurationAssemblies, Type configType)
{
return configurationAssemblies
.SelectMany(a => a.ExportedTypes
Expand All @@ -422,7 +423,7 @@ internal static bool IsValidSwitchName(string input)
return Regex.IsMatch(input, LevelSwitchNameRegex);
}

internal static LogEventLevel ParseLogEventLevel(string value)
static LogEventLevel ParseLogEventLevel(string value)
{
if (!Enum.TryParse(value, out LogEventLevel parsedLevel))
throw new InvalidOperationException($"The value {value} is not a valid Serilog level.");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Linq;
using System.Reflection;
using Serilog.Configuration;
using Serilog.Core;
Expand All @@ -10,66 +10,73 @@ namespace Serilog.Settings.Configuration
{
/// <summary>
/// Contains "fake extension" methods for the Serilog configuration API.
/// By default the settings knows how to find extension methods, but some configuration
/// By default the settings know how to find extension methods, but some configuration
/// are actually "regular" method calls and would not be found otherwise.
///
/// This static class contains internal methods that can be used instead.
///
/// </summary>
static class SurrogateConfigurationMethods
{
public static IEnumerable<MethodInfo> WriteTo
{
get
{
yield return GetSurrogateConfigurationMethod<LoggerSinkConfiguration, Action<LoggerConfiguration>, LoggingLevelSwitch>((c, a, s) => Logger(c, a, LevelAlias.Minimum, s));
}
}

public static IEnumerable<MethodInfo> Filter
{
get
{
yield return GetSurrogateConfigurationMethod<LoggerFilterConfiguration, ILogEventFilter, object>((c, f, _) => With(c, f));
}
}

public static IEnumerable<MethodInfo> Destructure
{
get
{
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, IDestructuringPolicy, object>((c, d, _) => With(c, d));
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, int, object>((c, m, _) => ToMaximumDepth(c, m));
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, int, object>((c, m, _) => ToMaximumStringLength(c, m));
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, int, object>((c, m, _) => ToMaximumCollectionCount(c, m));
yield return GetSurrogateConfigurationMethod<LoggerDestructuringConfiguration, Type, object>((c, t, _) => AsScalar(c, t));
}
}

public static IEnumerable<MethodInfo> Enrich
{
get
{
yield return GetSurrogateConfigurationMethod<LoggerEnrichmentConfiguration, object, object>((c, _, __) => FromLogContext(c));
}
}

static MethodInfo GetSurrogateConfigurationMethod<TConfiguration, TArg1, TArg2>(Expression<Action<TConfiguration, TArg1, TArg2>> method)
=> (method.Body as MethodCallExpression)?.Method;
static readonly Dictionary<Type, MethodInfo[]> SurrogateMethodCandidates = typeof(SurrogateConfigurationMethods)
.GetTypeInfo().DeclaredMethods
.GroupBy(m => m.GetParameters().First().ParameterType)
.ToDictionary(g => g.Key, g => g.ToArray());


internal static readonly MethodInfo[] WriteTo = SurrogateMethodCandidates[typeof(LoggerSinkConfiguration)];
internal static readonly MethodInfo[] AuditTo = SurrogateMethodCandidates[typeof(LoggerAuditSinkConfiguration)];
internal static readonly MethodInfo[] Enrich = SurrogateMethodCandidates[typeof(LoggerEnrichmentConfiguration)];
internal static readonly MethodInfo[] Destructure = SurrogateMethodCandidates[typeof(LoggerDestructuringConfiguration)];
internal static readonly MethodInfo[] Filter = SurrogateMethodCandidates[typeof(LoggerFilterConfiguration)];

/*
Pass-through calls to various Serilog config methods which are
implemented as instance methods rather than extension methods. The
FindXXXConfigurationMethods calls (above) use these to add method
invocation expressions as surrogates so that SelectConfigurationMethod
has a way to match and invoke these instance methods.
implemented as instance methods rather than extension methods.
ConfigurationReader adds those to the already discovered extension methods
so they can be invoked as well.
*/

// ReSharper disable UnusedMember.Local
// those methods are discovered through reflection by `SurrogateMethodCandidates`
// ReSharper has no way to see that they are actually used ...

// .WriteTo...
// ========
static LoggerConfiguration Sink(
LoggerSinkConfiguration loggerSinkConfiguration,
ILogEventSink sink,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
LoggingLevelSwitch levelSwitch = null)
=> loggerSinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch);

static LoggerConfiguration Logger(
LoggerSinkConfiguration loggerSinkConfiguration,
Action<LoggerConfiguration> configureLogger,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
LoggingLevelSwitch levelSwitch = null)
=> loggerSinkConfiguration.Logger(configureLogger, restrictedToMinimumLevel, levelSwitch);

// .AuditTo...
// ========
static LoggerConfiguration Sink(
LoggerAuditSinkConfiguration auditSinkConfiguration,
ILogEventSink sink,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
LoggingLevelSwitch levelSwitch = null)
=> auditSinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch);

// .Filter...
// =======
// TODO: add overload for array argument (ILogEventEnricher[])
// expose `With(params ILogEventFilter[] filters)` as if it was `With(ILogEventFilter filter)`
static LoggerConfiguration With(LoggerFilterConfiguration loggerFilterConfiguration, ILogEventFilter filter)
=> loggerFilterConfiguration.With(filter);

// .Destructure...
// ============
// TODO: add overload for array argument (IDestructuringPolicy[])
// expose `With(params IDestructuringPolicy[] destructuringPolicies)` as if it was `With(IDestructuringPolicy policy)`
static LoggerConfiguration With(LoggerDestructuringConfiguration loggerDestructuringConfiguration, IDestructuringPolicy policy)
=> loggerDestructuringConfiguration.With(policy);

Expand All @@ -85,15 +92,17 @@ static LoggerConfiguration ToMaximumCollectionCount(LoggerDestructuringConfigura
static LoggerConfiguration AsScalar(LoggerDestructuringConfiguration loggerDestructuringConfiguration, Type scalarType)
=> loggerDestructuringConfiguration.AsScalar(scalarType);

// .Enrich...
// =======
// expose `With(params ILogEventEnricher[] enrichers)` as if it was `With(ILogEventEnricher enricher)`
static LoggerConfiguration With(
LoggerEnrichmentConfiguration loggerEnrichmentConfiguration,
ILogEventEnricher enricher)
=> loggerEnrichmentConfiguration.With(enricher);

static LoggerConfiguration FromLogContext(LoggerEnrichmentConfiguration loggerEnrichmentConfiguration)
=> loggerEnrichmentConfiguration.FromLogContext();

// Unlike the other configuration methods, Logger is an instance method rather than an extension.
static LoggerConfiguration Logger(
LoggerSinkConfiguration loggerSinkConfiguration,
Action<LoggerConfiguration> configureLogger,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
LoggingLevelSwitch levelSwitch = null)
=> loggerSinkConfiguration.Logger(configureLogger, restrictedToMinimumLevel, levelSwitch);
// ReSharper restore UnusedMember.Local
}
}
Loading