Skip to content

Instantly share code, notes, and snippets.

@IanYates
Created May 30, 2015 03:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IanYates/7f31abe19610ca653a3b to your computer and use it in GitHub Desktop.
Save IanYates/7f31abe19610ca653a3b to your computer and use it in GitHub Desktop.
System.Diagnostics.TraceListener to Windsor ILogger
using System;
using System.Diagnostics;
using System.Globalization;
using Castle.Core.Logging;
namespace Dox.Server.Web.Utilities.Logging
{
/// <summary>
/// TraceListener implementation that directs all output to Serilog via the Windsor ILogger
/// </summary>
public class TraceListenerToILogger: System.Diagnostics.TraceListener
{
const LoggerLevel FailLevel = LoggerLevel.Fatal;
const LoggerLevel DefaultLogLevel = LoggerLevel.Debug;
const string MessagelessTraceEventMessageTemplate = "{TraceSource:l} {TraceEventType}: {TraceEventId}";
const string MesageMessageTemplate = "{TraceMessage:l}";
const string MessageWithCategoryMessageTemplate = "{Category:l}: {TraceMessage:l}";
const string FailMessageTemplate = "Fail: {TraceMessage:l}";
const string DetailedFailMessageTemplate = "Fail: {TraceMessage:l} {FailDetails:l}";
static readonly string TraceDataMessageTemplate = "{TraceSource:l} {TraceEventType}: {TraceEventId} :" + Environment.NewLine + "{TraceData:l}";
static readonly string TraceEventMessageTemplate = "{TraceSource:l} {TraceEventType}: {TraceEventId} :" + Environment.NewLine + "{TraceMessage:l}";
static readonly string TraceTransferMessageTemplate = "{TraceSource:l} {TraceEventType}: {TraceEventId} :" + Environment.NewLine + "{TraceMessage:l}, relatedActivityId={RelatedActivityId}";
ILogger logger;
/// <summary>
/// Creates a SerilogTraceListener that uses the logger from `Serilog.Log`
/// </summary>
/// <remarks>
/// This is needed because TraceListeners are often configured through XML
/// where there would be no opportunity for constructor injection
/// </remarks>
public TraceListenerToILogger()
: this("Unspecified", new WindsorSerilogLogger(Serilog.Log.Logger))
{
}
/// <summary>
/// Creates a SerilogTraceListener that uses the specified logger
/// </summary>
public TraceListenerToILogger(string logName, ILogger logger)
{
this.logger = logger.ForContext("TraceListener", logName).UpliftTo(DefaultLogLevel);
}
public TraceListenerToILogger(string logName)
:this(logName, new WindsorSerilogLogger(Serilog.Log.Logger))
{
}
public override bool IsThreadSafe
{
get { return true; }
}
public override void Write(string message)
{
logger.DebugFormat(MesageMessageTemplate, message);
}
public override void Write(string message, string category)
{
logger.DebugFormat(MessageWithCategoryMessageTemplate, category, message);
}
public override void WriteLine(string message)
{
Write(message);
}
public override void WriteLine(string message, string category)
{
Write(message, category);
}
public override void Fail(string message)
{
logger.ErrorFormat(FailMessageTemplate, message);
}
public override void Fail(string message, string detailMessage)
{
logger.ErrorFormat(DetailedFailMessageTemplate, message, detailMessage);
}
public override void Close()
{
logger = new NullLogger();
base.Close();
}
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
{
WriteEvent(eventCache, eventType, TraceDataMessageTemplate, source, eventType, id, data);
}
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
{
WriteEvent(eventCache, eventType, TraceDataMessageTemplate, source, eventType, id, data);
}
public override void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
{
WriteEvent(eventCache, TraceEventType.Transfer, TraceTransferMessageTemplate, source, TraceEventType.Transfer, id, message, relatedActivityId);
}
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
{
WriteEvent(eventCache, eventType, MessagelessTraceEventMessageTemplate, source, eventType, id);
}
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
{
WriteEvent(eventCache, eventType, TraceEventMessageTemplate, source, eventType, id, message);
}
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
{
TraceEvent(eventCache, source, eventType, id, string.Format(CultureInfo.InvariantCulture, format, args ?? new object[0]));
}
void WriteEvent(TraceEventCache eventCache, TraceEventType eventType, string messageTemplate, params object[] propertyValues)
{
LoggerLevel level = ToLogEventLevel(eventType);
logger
.UpliftTo(level) //lets us use .Debug and then still get the desired level of output
.DebugFormat(messageTemplate, propertyValues ?? new object[0]);
}
internal static LoggerLevel ToLogEventLevel(TraceEventType eventType)
{
switch (eventType)
{
case TraceEventType.Critical:
{
return LoggerLevel.Fatal;
}
case TraceEventType.Error:
{
return LoggerLevel.Error;
}
case TraceEventType.Information:
{
return LoggerLevel.Info;
}
case TraceEventType.Warning:
{
return LoggerLevel.Warn;
}
case TraceEventType.Verbose:
{
return LoggerLevel.Debug;
}
default:
{
return LoggerLevel.Debug;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment