#region License
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
using System;
using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
namespace Common.Logging.EntLib{
/// <summary>
/// Use this <see cref="TraceListener"/> implementation to route all Entlib logging events to the
/// Common.Logging infrastructure.
/// </summary>
/// <remarks>
/// See <see cref="CommonLoggingEntlibTraceListenerData"/> for a list of properties to configure.
/// </remarks>
/// <example>
/// To route all <see cref="Logger"/> events to Common.Logging, configure <see cref="CommonLoggingEntlibTraceListener"/>:
/// <code lang="XML">
/// <?xml version="1.0" encoding="utf-8"?>
/// <configuration>
/// <configSections>
/// <section name="loggingConfiguration"
/// type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings,
/// Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral,
/// PublicKeyToken=b03f5f7f11d50a3a" />
/// </configSections>
/// <loggingConfiguration name="Logging Application Block" tracingEnabled="true"
/// defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
/// <listeners>
/// <add name="Common.Logging Listener"
/// type="Common.Logging.EntLib.CommonLoggingEntlibTraceListener, Common.Logging.EntLib"
/// listenerDataType="Common.Logging.EntLib.CommonLoggingEntlibTraceListenerData,
/// Common.Logging.EntLib"
/// loggerNameFormat="{listenerName}.{sourceName}"
/// formatter="Text Formatter"
/// />
/// </listeners>
/// <formatters>
/// <add template="Timestamp: {timestamp}&#xD;&#xA;Message: {message}&#xD;&#xA;Category:
/// {category}&#xD;&#xA;Priority: {priority}&#xD;&#xA;EventId: {eventid}&#xD;&#xA;Severity:
/// {severity}&#xD;&#xA;Title:{title}&#xD;&#xA;Machine: {machine}&#xD;&#xA;Application Domain:
/// {appDomain}&#xD;&#xA;Process Id: {processId}&#xD;&#xA;Process Name: {processName}&#xD;&#xA;Win32
/// Thread Id: {win32ThreadId}&#xD;&#xA;Thread Name: {threadName}&#xD;&#xA;Extended Properties:
/// {dictionary({key} - {value}&#xD;&#xA;)}"
/// type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter,
/// Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral,
/// PublicKeyToken=b03f5f7f11d50a3a"
/// name="Text Formatter" />
/// </formatters>
/// <specialSources>
/// <allEvents switchValue="All" name="All Events">
/// <listeners>
/// <add name="Test Capturing Listener" />
/// </listeners>
/// </allEvents>
/// </specialSources>
/// </loggingConfiguration>
/// </configuration>
/// </code>
/// </example>
/// <author>Erich Eichinger</author>
public class CommonLoggingEntlibTraceListener : FormattedTraceListenerBase
{
/// <summary>
/// The message object to be logged. Overrides <see cref="ToString"/> to format
/// the associated <see cref="LogEntry"/>
/// </summary>
private class LogEntryMessage
{
private readonly ILogFormatter _logFormatter;
private readonly LogEntry _logEntry;
private string _cachedResult;
public LogEntryMessage(ILogFormatter logFormatter, LogEntry logEntry)
{
_logFormatter = logFormatter;
_logEntry = logEntry;
}
public override string ToString()
{
if (_cachedResult == null)
{
if (_logFormatter == null)
{
_cachedResult = _logEntry.ToString();
}
else
{
_cachedResult = _logFormatter.Format(_logEntry);
}
}
return _cachedResult;
}
}
// used to format the loggername from listener + source names
private readonly string _loggerNameFormat = "{listenerName}.{sourceName}";
/// <summary>
/// Initializes this instance from <see cref="CommonLoggingEntlibTraceListenerData"/> configuration
/// information.
/// </summary>
public CommonLoggingEntlibTraceListener(CommonLoggingEntlibTraceListenerData data, ILogFormatter formatter)
:base(formatter)
{
if (data.LoggerNameFormat != null)
{
_loggerNameFormat = data.LoggerNameFormat;
}
}
/// <summary>
/// Format to use for creating the logger name. Defaults to "{listenerName}.{sourceName}".
/// </summary>
/// <remarks>
/// Available placeholders are:
/// <list type="bullet">
/// <item>{listenerName}: the configured name of this listener instance.</item>
/// <item>{sourceName}: the trace source name an event originates from (see e.g. <see cref="TraceListener.TraceEvent(System.Diagnostics.TraceEventCache,string,System.Diagnostics.TraceEventType,int,string,object[])"/>.</item>
/// </list>
/// </remarks>
public string LoggerNameFormat
{
get { return _loggerNameFormat; }
}
/// <summary>
/// NOT USED BY ENTLIB
/// </summary>
/// <exception cref="NotImplementedException"/>
public override void Write(string message)
{
throw new NotImplementedException();
}
/// <summary>
/// NOT USED BY ENTLIB
/// </summary>
/// <exception cref="NotImplementedException"/>
public override void WriteLine(string message)
{
throw new NotImplementedException();
}
/// <summary>
/// Overridden to redirect to call <see cref="Log"/>.
/// </summary>
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
{
if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null))
{
if (data is LogEntry)
{
data = new LogEntryMessage(base.Formatter, (LogEntry)data);
}
Log(eventType, source, id, "{0}", data);
}
}
/// <summary>
/// Logs the given message to the Common.Logging infrastructure
/// </summary>
protected virtual void Log(TraceEventType eventType, string source, int id, string format, params object[] args)
{
if (!string.IsNullOrEmpty(source))
{
source = this.LoggerNameFormat.Replace("{listenerName}", this.Name).Replace("{sourceName}", source);
}
ILog log = LogManager.GetLogger(source);
LogLevel logLevel = MapLogLevel(eventType);
switch (logLevel)
{
case LogLevel.Trace:
log.TraceFormat(format, args);
break;
case LogLevel.Debug:
log.DebugFormat(format, args);
break;
case LogLevel.Info:
log.InfoFormat(format, args);
break;
case LogLevel.Warn:
log.WarnFormat(format, args);
break;
case LogLevel.Error:
log.ErrorFormat(format, args);
break;
case LogLevel.Fatal:
log.FatalFormat(format, args);
break;
case LogLevel.Off:
break;
default:
throw new ArgumentOutOfRangeException("eventType", eventType, "invalid TraceEventType value");
}
}
private LogLevel MapLogLevel(TraceEventType eventType)
{
switch (eventType)
{
case TraceEventType.Start:
case TraceEventType.Stop:
case TraceEventType.Suspend:
case TraceEventType.Resume:
case TraceEventType.Transfer:
return LogLevel.Trace;
case TraceEventType.Verbose:
return LogLevel.Debug;
case TraceEventType.Information:
return LogLevel.Info;
case TraceEventType.Warning:
return LogLevel.Warn;
case TraceEventType.Error:
return LogLevel.Error;
case TraceEventType.Critical:
return LogLevel.Fatal;
default:
return LogLevel.Trace;
}
}
}
}
|