我知道這個問題很舊,但顯然還沒有開箱即用的解決方案,所以這裏是一個自定義記錄器,適用於我(靈感來自https://github.com/ramonsmits/common-logging,但我最終改變了所有內容)。使用Common.Logging版本3.1.0進行測試。
的FactoryAdapter
/// <summary>
/// Adapter hub for Common.Logging that can send logs to multiple other adapters
/// </summary>
public class MultiLoggerFactoryAdapter : AbstractCachingLoggerFactoryAdapter
{
private readonly List<ILoggerFactoryAdapter> LoggerFactoryAdapters;
/// <summary>
/// Initializes a new instance of the <see cref="MultiFactoryLoggerFactoryAdapter"/> class.
/// </summary>
public MultiLoggerFactoryAdapter(CommonLogging.Configuration.NameValueCollection properties)
{
LoggerFactoryAdapters = new List<ILoggerFactoryAdapter>();
foreach(var factoryAdapter in properties.Where(e => e.Key.EndsWith(".factoryAdapter")))
{
string adapterName = factoryAdapter.Key.Substring(0, factoryAdapter.Key.Length - 15);
string adapterType = factoryAdapter.Value;
var adapterConfig = new CommonLogging.Configuration.NameValueCollection();
foreach(var entry in properties.Where(e1 => e1.Key.StartsWith(adapterName + ".")))
{
adapterConfig.Add(entry.Key.Substring(adapterName.Length + 1), entry.Value);
}
var adapter = (ILoggerFactoryAdapter)Activator.CreateInstance(Type.GetType(adapterType), adapterConfig);
LoggerFactoryAdapters.Add(adapter);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="MultiFactoryLoggerFactoryAdapter"/> class.
/// </summary>
/// <param name="factoryAdapters">The factory adapters.</param>
public MultiLoggerFactoryAdapter(List<ILoggerFactoryAdapter> factoryAdapters)
{
LoggerFactoryAdapters = factoryAdapters;
}
protected override ILog CreateLogger(string name)
{
var loggers = new List<ILog>(LoggerFactoryAdapters.Count);
foreach (var f in LoggerFactoryAdapters)
{
loggers.Add(f.GetLogger(name));
}
return new MultiLogger(loggers);
}
}
記錄器
/// <summary>
/// Adapter hub for Common.Logging that can send logs to multiple other adapters
/// </summary>
public class MultiLogger : AbstractLogger
{
private readonly List<ILog> Loggers;
public static readonly IDictionary<LogLevel, Action<ILog, object, Exception>> LogActions = new Dictionary<LogLevel, Action<ILog, object, Exception>>()
{
{ LogLevel.Debug, (logger, message, exception) => logger.Debug(message, exception) },
{ LogLevel.Error, (logger, message, exception) => logger.Error(message, exception) },
{ LogLevel.Fatal, (logger, message, exception) => logger.Fatal(message, exception) },
{ LogLevel.Info, (logger, message, exception) => logger.Info(message, exception) },
{ LogLevel.Trace, (logger, message, exception) => logger.Trace(message, exception) },
{ LogLevel.Warn, (logger, message, exception) => logger.Warn(message, exception) },
};
/// <summary>
/// Initializes a new instance of the <see cref="MultiLogger"/> class.
/// </summary>
/// <param name="loggers">The loggers.</param>
public MultiLogger(List<ILog> loggers)
{
Loggers = loggers;
}
public override bool IsDebugEnabled { get { return Loggers.Any(l => l.IsDebugEnabled); } }
public override bool IsErrorEnabled { get { return Loggers.Any(l => l.IsErrorEnabled); } }
public override bool IsFatalEnabled { get { return Loggers.Any(l => l.IsFatalEnabled); } }
public override bool IsInfoEnabled { get { return Loggers.Any(l => l.IsInfoEnabled); } }
public override bool IsTraceEnabled { get { return Loggers.Any(l => l.IsTraceEnabled); } }
public override bool IsWarnEnabled { get { return Loggers.Any(l => l.IsWarnEnabled); } }
protected override void WriteInternal(LogLevel level, object message, Exception exception)
{
List<Exception> exceptions = null;
foreach(var logger in Loggers)
{
try
{
LogActions[level](logger, message, exception);
}
catch(Exception e)
{
if(exceptions == null)
exceptions = new List<Exception>();
exceptions.Add(e);
}
}
if(exceptions != null)
throw new AggregateException("One or more exceptions occured while forwarding log message to multiple loggers", exceptions);
}
}
你可以這樣配置它:
<common>
<logging>
<factoryAdapter type="MultiLoggerFactoryAdapter, YourAssemblyName">
<arg key="Log4Net.factoryAdapter" value="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1213" />
<arg key="Log4Net.configType" value="INLINE" />
<arg key="Debug.factoryAdapter" value="Common.Logging.Simple.TraceLoggerFactoryAdapter, Common.Logging" />
</factoryAdapter>
</logging>
</common>
也就是說,對於每個記錄,您添加與關鍵線路LoggerName.factoryAdapter
,然後您可以通過使用相同的名稱爲t添加此記錄器的屬性他的鑰匙,如LoggerName.someProperty
。
謝謝,那正是我期待的。我確實看到有人在[GitHub repo](https://github.com/net-commons/common-logging/issues/8)中提出了這個問題,所以最終可能會將其添加到項目中。 – omockler 2012-07-06 19:19:28
@omockler那個GitHub問題早就解決了。現在有多個適配器似乎是可能的。 – 2017-02-12 14:52:26