📄 hierarchy.cs
字号:
/// <para>
/// Shutting down a hierarchy will <i>safely</i> close and remove
/// all appenders in all loggers including the root logger.
/// </para>
/// <para>
/// Some appenders need to be closed before the
/// application exists. Otherwise, pending logging events might be
/// lost.
/// </para>
/// <para>
/// The <c>Shutdown</c> method is careful to close nested
/// appenders before closing regular appenders. This is allows
/// configurations where a regular appender is attached to a logger
/// and again to a nested appender.
/// </para>
/// </remarks>
override public void Shutdown()
{
LogLog.Debug("Hierarchy: Shutdown called on Hierarchy ["+this.Name+"]");
// begin by closing nested appenders
Root.CloseNestedAppenders();
lock(m_ht)
{
ILogger[] currentLoggers = this.GetCurrentLoggers();
foreach(Logger logger in currentLoggers)
{
logger.CloseNestedAppenders();
}
// then, remove all appenders
Root.RemoveAllAppenders();
foreach(Logger logger in currentLoggers)
{
logger.RemoveAllAppenders();
}
}
base.Shutdown();
}
/// <summary>
/// Reset all values contained in this hierarchy instance to their default.
/// </summary>
/// <remarks>
/// <para>
/// Reset all values contained in this hierarchy instance to their
/// default. This removes all appenders from all loggers, sets
/// the level of all non-root loggers to <c>null</c>,
/// sets their additivity flag to <c>true</c> and sets the level
/// of the root logger to <see cref="Level.Debug"/>. Moreover,
/// message disabling is set its default "off" value.
/// </para>
/// <para>
/// Existing loggers are not removed. They are just reset.
/// </para>
/// <para>
/// This method should be used sparingly and with care as it will
/// block all logging until it is completed.
/// </para>
/// </remarks>
override public void ResetConfiguration()
{
Root.Level = Level.Debug;
Threshold = Level.All;
// the synchronization is needed to prevent hashtable surprises
lock(m_ht)
{
Shutdown(); // nested locks are OK
foreach(Logger l in this.GetCurrentLoggers())
{
l.Level = null;
l.Additivity = true;
}
}
base.ResetConfiguration();
// Notify listeners
OnConfigurationChanged(null);
}
/// <summary>
/// Log the logEvent through this hierarchy.
/// </summary>
/// <param name="logEvent">the event to log</param>
/// <remarks>
/// <para>
/// This method should not normally be used to log.
/// The <see cref="ILog"/> interface should be used
/// for routine logging. This interface can be obtained
/// using the <see cref="log4net.LogManager.GetLogger(string)"/> method.
/// </para>
/// <para>
/// The <c>logEvent</c> is delivered to the appropriate logger and
/// that logger is then responsible for logging the event.
/// </para>
/// </remarks>
override public void Log(LoggingEvent logEvent)
{
if (logEvent == null)
{
throw new ArgumentNullException("logEvent");
}
this.GetLogger(logEvent.LoggerName, m_defaultFactory).Log(logEvent);
}
/// <summary>
/// Returns all the Appenders that are currently configured
/// </summary>
/// <returns>An array containing all the currently configured appenders</returns>
/// <remarks>
/// <para>
/// Returns all the <see cref="log4net.Appender.IAppender"/> instances that are currently configured.
/// All the loggers are searched for appenders. The appenders may also be containers
/// for appenders and these are also searched for additional loggers.
/// </para>
/// <para>
/// The list returned is unordered but does not contain duplicates.
/// </para>
/// </remarks>
override public log4net.Appender.IAppender[] GetAppenders()
{
System.Collections.ArrayList appenderList = new System.Collections.ArrayList();
CollectAppenders(appenderList, Root);
foreach(Logger logger in GetCurrentLoggers())
{
CollectAppenders(appenderList, logger);
}
return (log4net.Appender.IAppender[])appenderList.ToArray(typeof(log4net.Appender.IAppender));
}
#endregion Override Implementation of LoggerRepositorySkeleton
/// <summary>
/// Collect the appenders from an <see cref="IAppenderAttachable"/>.
/// The appender may also be a container.
/// </summary>
/// <param name="appenderList"></param>
/// <param name="appender"></param>
private static void CollectAppender(System.Collections.ArrayList appenderList, log4net.Appender.IAppender appender)
{
if (!appenderList.Contains(appender))
{
appenderList.Add(appender);
IAppenderAttachable container = appender as IAppenderAttachable;
if (container != null)
{
CollectAppenders(appenderList, container);
}
}
}
/// <summary>
/// Collect the appenders from an <see cref="IAppenderAttachable"/> container
/// </summary>
/// <param name="appenderList"></param>
/// <param name="container"></param>
private static void CollectAppenders(System.Collections.ArrayList appenderList, IAppenderAttachable container)
{
foreach(log4net.Appender.IAppender appender in container.Appenders)
{
CollectAppender(appenderList, appender);
}
}
#region Implementation of IBasicRepositoryConfigurator
/// <summary>
/// Initialize the log4net system using the specified appender
/// </summary>
/// <param name="appender">the appender to use to log all logging events</param>
void IBasicRepositoryConfigurator.Configure(log4net.Appender.IAppender appender)
{
BasicRepositoryConfigure(appender);
}
/// <summary>
/// Initialize the log4net system using the specified appender
/// </summary>
/// <param name="appender">the appender to use to log all logging events</param>
/// <remarks>
/// <para>
/// This method provides the same functionality as the
/// <see cref="IBasicRepositoryConfigurator.Configure"/> method implemented
/// on this object, but it is protected and therefore can be called by subclasses.
/// </para>
/// </remarks>
protected void BasicRepositoryConfigure(log4net.Appender.IAppender appender)
{
Root.AddAppender(appender);
Configured = true;
// Notify listeners
OnConfigurationChanged(null);
}
#endregion Implementation of IBasicRepositoryConfigurator
#region Implementation of IXmlRepositoryConfigurator
/// <summary>
/// Initialize the log4net system using the specified config
/// </summary>
/// <param name="element">the element containing the root of the config</param>
void IXmlRepositoryConfigurator.Configure(System.Xml.XmlElement element)
{
XmlRepositoryConfigure(element);
}
/// <summary>
/// Initialize the log4net system using the specified config
/// </summary>
/// <param name="element">the element containing the root of the config</param>
/// <remarks>
/// <para>
/// This method provides the same functionality as the
/// <see cref="IBasicRepositoryConfigurator.Configure"/> method implemented
/// on this object, but it is protected and therefore can be called by subclasses.
/// </para>
/// </remarks>
protected void XmlRepositoryConfigure(System.Xml.XmlElement element)
{
XmlHierarchyConfigurator config = new XmlHierarchyConfigurator(this);
config.Configure(element);
Configured = true;
// Notify listeners
OnConfigurationChanged(null);
}
#endregion Implementation of IXmlRepositoryConfigurator
#region Public Instance Methods
/// <summary>
/// Test if this hierarchy is disabled for the specified <see cref="Level"/>.
/// </summary>
/// <param name="level">The level to check against.</param>
/// <returns>
/// <c>true</c> if the repository is disabled for the level argument, <c>false</c> otherwise.
/// </returns>
/// <remarks>
/// <para>
/// If this hierarchy has not been configured then this method will
/// always return <c>true</c>.
/// </para>
/// <para>
/// This method will return <c>true</c> if this repository is
/// disabled for <c>level</c> object passed as parameter and
/// <c>false</c> otherwise.
/// </para>
/// <para>
/// See also the <see cref="ILoggerRepository.Threshold"/> property.
/// </para>
/// </remarks>
public bool IsDisabled(Level level)
{
// Cast level to object for performance
if ((object)level == null)
{
throw new ArgumentNullException("level");
}
if (Configured)
{
return Threshold > level;
}
else
{
// If not configured the hierarchy is effectively disabled
return true;
}
}
/// <summary>
/// Clear all logger definitions from the internal hashtable
/// </summary>
/// <remarks>
/// <para>
/// This call will clear all logger definitions from the internal
/// hashtable. Invoking this method will irrevocably mess up the
/// logger hierarchy.
/// </para>
/// <para>
/// You should <b>really</b> know what you are doing before
/// invoking this method.
/// </para>
/// </remarks>
public void Clear()
{
m_ht.Clear();
}
/// <summary>
/// Return a new logger instance named as the first parameter using
/// <paramref name="factory"/>.
/// </summary>
/// <param name="name">The name of the logger to retrieve</param>
/// <param name="factory">The factory that will make the new logger instance</param>
/// <returns>The logger object with the name specified</returns>
/// <remarks>
/// <para>
/// If a logger of that name already exists, then it will be
/// returned. Otherwise, a new logger will be instantiated by the
/// <paramref name="factory"/> parameter and linked with its existing
/// ancestors as well as children.
/// </para>
/// </remarks>
public Logger GetLogger(string name, ILoggerFactory factory)
{
if (name == null)
{
throw new ArgumentNullException("name");
}
if (factory == null)
{
throw new ArgumentNullException("factory");
}
LoggerKey key = new LoggerKey(name);
// Synchronize to prevent write conflicts. Read conflicts (in
// GetEffectiveLevel() method) are possible only if variable
// assignments are non-atomic.
Logger logger;
lock(m_ht)
{
Object node = m_ht[key];
if (node == null)
{
logger = factory.CreateLogger(name);
logger.Hierarchy = this;
m_ht[key] = logger;
UpdateParents(logger);
OnLoggerCreationEvent(logger);
return logger;
}
Logger nodeLogger = node as Logger;
if (nodeLogger != null)
{
return nodeLogger;
}
ProvisionNode nodeProvisionNode = node as ProvisionNode;
if (nodeProvisionNode != null)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -