diff --git a/build.ps1 b/build.ps1 index 905f8175..f77a9808 100644 --- a/build.ps1 +++ b/build.ps1 @@ -9,7 +9,7 @@ $versionProduct = $versionPrefix; if (-Not $versionSuffix.Equals("")) { $versionProduct = $versionProduct + "-" + $versionSuffix } -msbuild /t:Restore,Pack .\src\NLog.Extensions.Logging\ /p:targetFrameworks='"net451;net461;netstandard1.5;netstandard2.0;uap10.0"' /p:VersionPrefix=$versionPrefix /p:VersionSuffix=$versionSuffix /p:FileVersion=$versionFile /p:ProductVersion=$versionProduct /p:Configuration=Release /p:IncludeSymbols=true /p:PackageOutputPath=..\..\artifacts /verbosity:minimal +msbuild /t:Restore,Pack .\src\NLog.Extensions.Logging\ /p:targetFrameworks='"net451;net461;netstandard1.3;netstandard1.5;netstandard2.0"' /p:VersionPrefix=$versionPrefix /p:VersionSuffix=$versionSuffix /p:FileVersion=$versionFile /p:ProductVersion=$versionProduct /p:Configuration=Release /p:IncludeSymbols=true /p:PackageOutputPath=..\..\artifacts /verbosity:minimal if (-Not $LastExitCode -eq 0) { exit $LastExitCode } diff --git a/examples/NetCore2/ConsoleExample/Program.cs b/examples/NetCore2/ConsoleExample/Program.cs index 85607bf5..c85032c0 100644 --- a/examples/NetCore2/ConsoleExample/Program.cs +++ b/examples/NetCore2/ConsoleExample/Program.cs @@ -9,15 +9,28 @@ class Program { static void Main(string[] args) { - var servicesProvider = BuildDi(); - var runner = servicesProvider.GetRequiredService<Runner>(); - - runner.DoAction("Action1"); - - Console.WriteLine("Press ANY key to exit"); - Console.ReadLine(); - - NLog.LogManager.Shutdown(); // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) + var logger = NLog.LogManager.LoadConfiguration("nlog.config").GetCurrentClassLogger(); + try + { + var servicesProvider = BuildDi(); + var runner = servicesProvider.GetRequiredService<Runner>(); + + runner.DoAction("Action1"); + + Console.WriteLine("Press ANY key to exit"); + Console.ReadLine(); + } + catch (Exception ex) + { + //NLog: catch setup errors + logger.Error(ex, "Stopped program because of exception"); + throw; + } + finally + { + // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) + NLog.LogManager.Shutdown(); + } } @@ -38,8 +51,6 @@ private static IServiceProvider BuildDi() //configure NLog loggerFactory.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true }); - loggerFactory.ConfigureNLog("nlog.config"); - return serviceProvider; } } @@ -58,7 +69,5 @@ public void DoAction(string name) { _logger.LogDebug(20, "Doing hard work! {Action}", name); } - - } } diff --git a/examples/NetCore2/ConsoleExample/nlog.config b/examples/NetCore2/ConsoleExample/nlog.config index 710225a9..d31b5ead 100644 --- a/examples/NetCore2/ConsoleExample/nlog.config +++ b/examples/NetCore2/ConsoleExample/nlog.config @@ -6,21 +6,17 @@ internalLogFile="c:\temp\console-example-internal.log" internalLogLevel="Info" > - <!-- the targets to write to --> <targets> <!-- write logs to file --> - <target xsi:type="File" name="target1" fileName="c:\temp\console-example.log" - layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" /> - <target xsi:type="Console" name="target2" - layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" /> - - + <target xsi:type="File" name="fileTarget" fileName="c:\temp\console-example.log" + layout="${date}|${level:uppercase=true}|${message} ${exception:format=tostring}|${logger}|${all-event-properties}" /> + <target xsi:type="Console" name="consoleTarget" + layout="${date}|${level:uppercase=true}|${message} ${exception:format=tostring}|${logger}|${all-event-properties}" /> </targets> <!-- rules to map from logger name to target --> <rules> - <logger name="*" minlevel="Trace" writeTo="target1,target2" /> - + <logger name="*" minlevel="Trace" writeTo="fileTarget,consoleTarget" /> </rules> </nlog> \ No newline at end of file diff --git a/src/NLog.Extensions.Logging/Extensions/ConfigureExtensions.cs b/src/NLog.Extensions.Logging/Extensions/ConfigureExtensions.cs index b956f746..af0415e0 100644 --- a/src/NLog.Extensions.Logging/Extensions/ConfigureExtensions.cs +++ b/src/NLog.Extensions.Logging/Extensions/ConfigureExtensions.cs @@ -108,6 +108,7 @@ private static void SafeAddHiddenAssembly(string assemblyName, bool logOnExcepti /// <param name="loggerFactory"></param> /// <param name="configFileRelativePath">relative path to NLog configuration file.</param> /// <returns>Current configuration for chaining.</returns> + [Obsolete("Instead use NLog.LogManager.LoadConfiguration()")] public static LoggingConfiguration ConfigureNLog(this ILoggerFactory loggerFactory, string configFileRelativePath) { ConfigureHiddenAssemblies(); @@ -120,6 +121,7 @@ public static LoggingConfiguration ConfigureNLog(this ILoggerFactory loggerFacto /// <param name="loggerFactory"></param> /// <param name="config">New NLog config.</param> /// <returns>Current configuration for chaining.</returns> + [Obsolete("Instead assign property NLog.LogManager.Configuration")] public static LoggingConfiguration ConfigureNLog(this ILoggerFactory loggerFactory, LoggingConfiguration config) { ConfigureHiddenAssemblies(); diff --git a/src/NLog.Extensions.Logging/Logging/NLogLogger.cs b/src/NLog.Extensions.Logging/Logging/NLogLogger.cs index 44416dea..df467cd1 100644 --- a/src/NLog.Extensions.Logging/Logging/NLogLogger.cs +++ b/src/NLog.Extensions.Logging/Logging/NLogLogger.cs @@ -51,7 +51,7 @@ public void Log<TState>(Microsoft.Extensions.Logging.LogLevel logLevel, EventId CaptureMessageProperties(eventInfo, state); } - _logger.Log(eventInfo); + _logger.Log(typeof(Microsoft.Extensions.Logging.ILogger), eventInfo); } diff --git a/src/NLog.Extensions.Logging/NLog.Extensions.Logging.csproj b/src/NLog.Extensions.Logging/NLog.Extensions.Logging.csproj index 224757e1..8574178e 100644 --- a/src/NLog.Extensions.Logging/NLog.Extensions.Logging.csproj +++ b/src/NLog.Extensions.Logging/NLog.Extensions.Logging.csproj @@ -2,7 +2,7 @@ <PropertyGroup> <RestoreProjectStyle>PackageReference</RestoreProjectStyle> - <TargetFrameworks>net451;net461;netstandard1.5;netstandard2.0</TargetFrameworks> + <TargetFrameworks>net451;net461;netstandard1.3;netstandard1.5;netstandard2.0</TargetFrameworks> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <GenerateDocumentationFile>true</GenerateDocumentationFile> @@ -43,6 +43,11 @@ rc3: Support for .NET 4.6.1, support for message templates .NET standard 1.5+ an <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences> <DefineConstants>$(DefineConstants);NETCORE1_0</DefineConstants> </PropertyGroup> + <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> + <Title>NLog.Extensions.Logging for NetStandard 1.3</Title> + <NetStandardImplicitPackageVersion>1.6.0</NetStandardImplicitPackageVersion> + <DefineConstants>$(DefineConstants);NETCORE1_0</DefineConstants> + </PropertyGroup> <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' "> <Title>NLog.Extensions.Logging for NetStandard 1.5</Title> <NetStandardImplicitPackageVersion>1.6.0</NetStandardImplicitPackageVersion> @@ -51,20 +56,8 @@ rc3: Support for .NET 4.6.1, support for message templates .NET standard 1.5+ an <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> <Title>NLog.Extensions.Logging for NetStandard 2.0</Title> </PropertyGroup> - <PropertyGroup Condition=" '$(TargetFramework)' == 'uap10.0' "> - <Title>NLog.Extensions.Logging for UWP</Title> - <NugetTargetMoniker>UAP,Version=v10.0</NugetTargetMoniker> - <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences> - <NetStandardImplicitPackageVersion>1.6.0</NetStandardImplicitPackageVersion> - <TargetFrameworkIdentifier>.NETCore</TargetFrameworkIdentifier> - <TargetFrameworkVersion>v5.0</TargetFrameworkVersion> - <TargetPlatformIdentifier>UAP</TargetPlatformIdentifier> - <TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.15083.0</TargetPlatformVersion> - <TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion> - <DefineConstants>$(DefineConstants);NETCORE1_0</DefineConstants> - </PropertyGroup> <ItemGroup> - <PackageReference Include="NLog" Version="[4.5.0-rc06,5)" /> + <PackageReference Include="NLog" Version="[4.5.0-rc07,5)" /> </ItemGroup> <ItemGroup Condition=" '$(TargetFramework)' == 'net451' "> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.2" /> @@ -76,7 +69,7 @@ rc3: Support for .NET 4.6.1, support for message templates .NET standard 1.5+ an <Reference Include="System" /> <Reference Include="Microsoft.CSharp" /> </ItemGroup> - <ItemGroup Condition=" '$(TargetFramework)' == 'uap10.0' "> + <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.2" /> </ItemGroup> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' "> diff --git a/test/CustomLoggerCallSiteTest.cs b/test/CustomLoggerCallSiteTest.cs new file mode 100644 index 00000000..4d84f45c --- /dev/null +++ b/test/CustomLoggerCallSiteTest.cs @@ -0,0 +1,73 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Xunit; + +namespace NLog.Extensions.Logging.Tests +{ + public class CustomLoggerCallSiteTest : NLogTestBase + { + [Fact] + public void TestCallSiteSayHello() + { + ConfigureServiceProvider<CustomLoggerCallSiteTestRunner>((s) => s.AddSingleton(typeof(ILogger<>), typeof(SameAssemblyLogger<>))); + var runner = GetRunner<CustomLoggerCallSiteTestRunner>(); + + var target = new NLog.Targets.MemoryTarget() { Layout = "${callsite}|${message}" }; + NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target); + runner.SayHello(); + Assert.Single(target.Logs); + Assert.Contains("SayHello", target.Logs[0]); + Assert.Contains("stuff", target.Logs[0]); + } + + public class SameAssemblyLogger<T> : ILogger<T> + { + private readonly Microsoft.Extensions.Logging.ILogger _logger; + + public SameAssemblyLogger(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger<T>(); + } + + public void Log<TState>(Microsoft.Extensions.Logging.LogLevel logLevel, EventId eventId, TState state, Exception exception, + Func<TState, Exception, string> formatter) + { + string Formatter(TState innserState, Exception innerException) + { + // additional logic for all providers goes here + var message = formatter(innserState, innerException) ?? string.Empty; + return message + " additional stuff in here"; + } + + _logger.Log(logLevel, eventId, state, exception, Formatter); + } + + public bool IsEnabled(Microsoft.Extensions.Logging.LogLevel logLevel) + { + return _logger.IsEnabled(logLevel); + } + + public IDisposable BeginScope<TState>(TState state) + { + return _logger.BeginScope(state); + } + } + + public class CustomLoggerCallSiteTestRunner + { + private readonly ILogger<CustomLoggerCallSiteTestRunner> _logger; + + public CustomLoggerCallSiteTestRunner(ILogger<CustomLoggerCallSiteTestRunner> logger) + { + _logger = logger; + } + + public void SayHello() + { + _logger.LogInformation("Hello"); + } + } + + } +} diff --git a/test/LoggerTests.cs b/test/LoggerTests.cs index e184293e..83d977da 100644 --- a/test/LoggerTests.cs +++ b/test/LoggerTests.cs @@ -8,10 +8,8 @@ namespace NLog.Extensions.Logging.Tests { - public class LoggerTests + public class LoggerTests : NLogTestBase { - private static Lazy<IServiceProvider> ServiceProvider = new Lazy<IServiceProvider>(BuildDi); - public LoggerTests() { var target = GetTarget(); @@ -144,7 +142,7 @@ public void TestExceptionWithNullMessage(Microsoft.Extensions.Logging.LogLevel l [InlineData(Microsoft.Extensions.Logging.LogLevel.Warning, "NLog.Extensions.Logging.Tests.LoggerTests.Runner|WARN|message |20")] public void TestMessageWithNullException(Microsoft.Extensions.Logging.LogLevel logLevel, string expectedLogMessage) { - GetRunner().Log(logLevel, 20, null, "message"); + GetRunner<Runner>().Log(logLevel, 20, null, "message"); var target = GetTarget(); Assert.Equal(expectedLogMessage, target.Logs.FirstOrDefault()); @@ -180,43 +178,25 @@ public void TestWithEmptyMessageAndNullException(Microsoft.Extensions.Logging.Lo Assert.Equal(expectedLogMessage, target.Logs.FirstOrDefault()); } - private static Runner GetRunner() - { - var serviceProvider = ServiceProvider.Value; - - // Start program - var runner = serviceProvider.GetRequiredService<Runner>(); - return runner; - } - private static MemoryTarget GetTarget() { var target = LogManager.Configuration.FindTargetByName<MemoryTarget>("target1"); return target; } - private static IServiceProvider BuildDi() + private Runner GetRunner() { - var services = new ServiceCollection(); - - services.AddTransient<Runner>(); - services.AddSingleton<ILoggerFactory, LoggerFactory>(); - - var serviceProvider = services.BuildServiceProvider(); - var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>(); - - loggerFactory.AddNLog(new NLogProviderOptions() { CaptureMessageTemplates = true, CaptureMessageProperties = true }); - loggerFactory.ConfigureNLog("nlog.config"); - return serviceProvider; + base.ConfigureServiceProvider<Runner>((s) => LogManager.LoadConfiguration("nlog.config")); + return base.GetRunner<Runner>(); } public class Runner { private readonly ILogger<Runner> _logger; - public Runner(ILoggerFactory fac) + public Runner(ILogger<Runner> logger) { - _logger = fac.CreateLogger<Runner>(); + _logger = logger; } public void LogDebugWithId() diff --git a/test/NLogTestBase.cs b/test/NLogTestBase.cs new file mode 100644 index 00000000..3819b697 --- /dev/null +++ b/test/NLogTestBase.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace NLog.Extensions.Logging.Tests +{ + public class NLogTestBase + { + IServiceProvider _serviceProvider; + + protected IServiceProvider ConfigureServiceProvider<T>(Action<ServiceCollection> configureServices = null, NLogProviderOptions options = null) where T : class + { + if (_serviceProvider == null) + { + var services = new ServiceCollection(); + + services.AddTransient<T>(); + services.AddSingleton<ILoggerFactory, LoggerFactory>(); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + configureServices?.Invoke(services); + + _serviceProvider = services.BuildServiceProvider(); + + var loggerFactory = _serviceProvider.GetRequiredService<ILoggerFactory>(); + loggerFactory.AddNLog(options ?? new NLogProviderOptions() { CaptureMessageTemplates = true, CaptureMessageProperties = true }); + } + return _serviceProvider; + } + + protected T GetRunner<T>(NLogProviderOptions options = null) where T : class + { + // Start program + var runner = ConfigureServiceProvider<T>(null, options).GetRequiredService<T>(); + return runner; + } + } +} diff --git a/test/Properties/AssemblyInfo-test.cs b/test/Properties/AssemblyInfo-test.cs new file mode 100644 index 00000000..97f073b7 --- /dev/null +++ b/test/Properties/AssemblyInfo-test.cs @@ -0,0 +1,14 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +[assembly: Xunit.CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file