-
Notifications
You must be signed in to change notification settings - Fork 129
Logging with .NET Standard 2.0
jbe2277 edited this page Mar 12, 2021
·
6 revisions
- Various loggers exist for .NET. Examples:
- Microsoft.Extensions.Logging (Designed for ASP .NET)
- NLog
- Serilog
- Application decides which one to use.
- But which one to use for a re-usable library?
-
Microsoft.Extensions.Logging.Abstractions
- Adapters exists for common .NET logging implementations
- Requires an additional dependency to a NuGet package
-
TraceSource
- No dependency needed
This chapter contains some guidelines how the TraceSource might be used for logging.
using System.Diagnostics;
namespace SampleLibrary.Logging
{
public static class Log
{
public static TraceSource Default { get; } = new TraceSource("SampleLibrary");
}
}
- Create a public static
Log
class per assembly.- It must be
public
so that an application can configure the TraceSource. The configuration includes defining Listeners (e.g. File, Console) and the minimum log level (Switch). - .NET Framework apps can use
App.config
files to configure TraceSources. .NET Core does not support this approach anymore.
- It must be
- Provide a
Default
TraceSource instance.- Optional: Add more static instances if more selective log configuration is needed.
- Use a separate namespace
xx.Logging
for the Log class because multipleLog
classes might exist.- Note: The application need to use this namespace just once for configuration.
Extract of TraceSourceExtensions.cs
internal static class TraceSourceExtensions
{
public static bool IsInfoEnabled(this TraceSource traceSource)
{
return traceSource.Switch.ShouldTrace(TraceEventType.Information);
}
public static void Info(this TraceSource traceSource, [Localizable(false)] string message)
{
if (IsInfoEnabled(traceSource)) traceSource.TraceEvent(TraceEventType.Information, 0, message);
}
public static void Info(this TraceSource traceSource, [Localizable(false)] string format, params object[] arguments)
{
if (IsInfoEnabled(traceSource)) traceSource.TraceEvent(TraceEventType.Information, 0, format, arguments);
}
...
- Consider including the
TraceSourceExtensions
class. It provides a more compact API for logging.- Copy the source file to your project (keep it as an
internal
class). - If your library references
System.Waf.Core
then you could use the implementation from this library.
- Copy the source file to your project (keep it as an
- Most 3rd party logging frameworks provide TraceSource Listeners for integration.
- Sample for NLog: https://github.com/jbe2277/LoggingSample
- NLogConfigSample: Use NLog via
NLog.config
file and listens to TraceSource logging. - NLogCodeSample: Use NLog via code configuration and listens to TraceSource logging.
- Integration is done with the NLogHelper class.
- NLogConfigSample: Use NLog via
internal static class NLogHelper
{
public static SourceLevels ToSourceLevels(this LogLevel level)
{
if (level == LogLevel.Trace) return SourceLevels.Verbose;
if (level == LogLevel.Debug) return SourceLevels.Verbose;
if (level == LogLevel.Info) return SourceLevels.Information;
if (level == LogLevel.Warn) return SourceLevels.Warning;
if (level == LogLevel.Error) return SourceLevels.Error;
if (level == LogLevel.Fatal) return SourceLevels.Critical;
return SourceLevels.Off;
}
public static void ConfigureTraceSource(TraceSource traceSource)
{
traceSource.Listeners.Clear();
traceSource.Listeners.Add(new NLogTraceListener());
var rule = LogManager.Configuration.LoggingRules
.FirstOrDefault(x => x.LoggerNamePattern == traceSource.Name)
?? throw new NotSupportedException(traceSource.Name);
// Levels.First -> minLevel (ordered list)
traceSource.Switch.Level = rule.Levels.Any() ? rule.Levels[0].ToSourceLevels() : SourceLevels.Off;
}
}