?? appenderskeleton.cs
字號:
#region Copyright & License
//
// Copyright 2001-2005 The Apache Software Foundation
//
// 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.IO;
using System.Collections;
using log4net.Filter;
using log4net.Util;
using log4net.Layout;
using log4net.Core;
namespace log4net.Appender
{
/// <summary>
/// Abstract base class implementation of <see cref="IAppender"/>.
/// </summary>
/// <remarks>
/// <para>
/// This class provides the code for common functionality, such
/// as support for threshold filtering and support for general filters.
/// </para>
/// <para>
/// Appenders can also implement the <see cref="IOptionHandler"/> interface. Therefore
/// they would require that the <see cref="IOptionHandler.ActivateOptions()"/> method
/// be called after the appenders properties have been configured.
/// </para>
/// </remarks>
/// <author>Nicko Cadell</author>
/// <author>Gert Driesen</author>
public abstract class AppenderSkeleton : IAppender, IBulkAppender, IOptionHandler
{
#region Protected Instance Constructors
/// <summary>
/// Default constructor
/// </summary>
/// <remarks>
/// <para>Empty default constructor</para>
/// </remarks>
protected AppenderSkeleton()
{
m_errorHandler = new OnlyOnceErrorHandler(this.GetType().Name);
}
#endregion Protected Instance Constructors
#region Finalizer
/// <summary>
/// Finalizes this appender by calling the implementation's
/// <see cref="Close"/> method.
/// </summary>
/// <remarks>
/// <para>
/// If this appender has not been closed then the <c>Finalize</c> method
/// will call <see cref="Close"/>.
/// </para>
/// </remarks>
~AppenderSkeleton()
{
// An appender might be closed then garbage collected.
// There is no point in closing twice.
if (!m_closed)
{
LogLog.Debug("AppenderSkeleton: Finalizing appender named ["+m_name+"].");
Close();
}
}
#endregion Finalizer
#region Public Instance Properties
/// <summary>
/// Gets or sets the threshold <see cref="Level"/> of this appender.
/// </summary>
/// <value>
/// The threshold <see cref="Level"/> of the appender.
/// </value>
/// <remarks>
/// <para>
/// All log events with lower level than the threshold level are ignored
/// by the appender.
/// </para>
/// <para>
/// In configuration files this option is specified by setting the
/// value of the <see cref="Threshold"/> option to a level
/// string, such as "DEBUG", "INFO" and so on.
/// </para>
/// </remarks>
public Level Threshold
{
get { return m_threshold; }
set { m_threshold = value; }
}
/// <summary>
/// Gets or sets the <see cref="IErrorHandler"/> for this appender.
/// </summary>
/// <value>The <see cref="IErrorHandler"/> of the appender</value>
/// <remarks>
/// <para>
/// The <see cref="AppenderSkeleton"/> provides a default
/// implementation for the <see cref="ErrorHandler"/> property.
/// </para>
/// </remarks>
virtual public IErrorHandler ErrorHandler
{
get { return this.m_errorHandler; }
set
{
lock(this)
{
if (value == null)
{
// We do not throw exception here since the cause is probably a
// bad config file.
LogLog.Warn("AppenderSkeleton: You have tried to set a null error-handler.");
}
else
{
m_errorHandler = value;
}
}
}
}
/// <summary>
/// The filter chain.
/// </summary>
/// <value>The head of the filter chain filter chain.</value>
/// <remarks>
/// <para>
/// Returns the head Filter. The Filters are organized in a linked list
/// and so all Filters on this Appender are available through the result.
/// </para>
/// </remarks>
virtual public IFilter FilterHead
{
get { return m_headFilter; }
}
/// <summary>
/// Gets or sets the <see cref="ILayout"/> for this appender.
/// </summary>
/// <value>The layout of the appender.</value>
/// <remarks>
/// <para>
/// See <see cref="RequiresLayout"/> for more information.
/// </para>
/// </remarks>
/// <seealso cref="RequiresLayout"/>
virtual public ILayout Layout
{
get { return m_layout; }
set { m_layout = value; }
}
#endregion
#region Implementation of IOptionHandler
/// <summary>
/// Initialize the appender based on the options set
/// </summary>
/// <remarks>
/// <para>
/// This is part of the <see cref="IOptionHandler"/> delayed object
/// activation scheme. The <see cref="ActivateOptions"/> method must
/// be called on this object after the configuration properties have
/// been set. Until <see cref="ActivateOptions"/> is called this
/// object is in an undefined state and must not be used.
/// </para>
/// <para>
/// If any of the configuration properties are modified then
/// <see cref="ActivateOptions"/> must be called again.
/// </para>
/// </remarks>
virtual public void ActivateOptions()
{
}
#endregion Implementation of IOptionHandler
#region Implementation of IAppender
/// <summary>
/// Gets or sets the name of this appender.
/// </summary>
/// <value>The name of the appender.</value>
/// <remarks>
/// <para>
/// The name uniquely identifies the appender.
/// </para>
/// </remarks>
public string Name
{
get { return m_name; }
set { m_name = value; }
}
/// <summary>
/// Closes the appender and release resources.
/// </summary>
/// <remarks>
/// <para>
/// Release any resources allocated within the appender such as file handles,
/// network connections, etc.
/// </para>
/// <para>
/// It is a programming error to append to a closed appender.
/// </para>
/// <para>
/// This method cannot be overridden by subclasses. This method
/// delegates the closing of the appender to the <see cref="OnClose"/>
/// method which must be overridden in the subclass.
/// </para>
/// </remarks>
public void Close()
{
// This lock prevents the appender being closed while it is still appending
lock(this)
{
if (!m_closed)
{
OnClose();
m_closed = true;
}
}
}
/// <summary>
/// Performs threshold checks and invokes filters before
/// delegating actual logging to the subclasses specific
/// <see cref="Append(LoggingEvent)"/> method.
/// </summary>
/// <param name="loggingEvent">The event to log.</param>
/// <remarks>
/// <para>
/// This method cannot be overridden by derived classes. A
/// derived class should override the <see cref="Append(LoggingEvent)"/> method
/// which is called by this method.
/// </para>
/// <para>
/// The implementation of this method is as follows:
/// </para>
/// <para>
/// <list type="bullet">
/// <item>
/// <description>
/// Checks that the severity of the <paramref name="loggingEvent"/>
/// is greater than or equal to the <see cref="Threshold"/> of this
/// appender.</description>
/// </item>
/// <item>
/// <description>
/// Checks that the <see cref="IFilter"/> chain accepts the
/// <paramref name="loggingEvent"/>.
/// </description>
/// </item>
/// <item>
/// <description>
/// Calls <see cref="PreAppendCheck()"/> and checks that
/// it returns <c>true</c>.</description>
/// </item>
/// </list>
/// </para>
/// <para>
/// If all of the above steps succeed then the <paramref name="loggingEvent"/>
/// will be passed to the abstract <see cref="Append(LoggingEvent)"/> method.
/// </para>
/// </remarks>
public void DoAppend(LoggingEvent loggingEvent)
{
// This lock is absolutely critical for correct formatting
// of the message in a multi-threaded environment. Without
// this, the message may be broken up into elements from
// multiple thread contexts (like get the wrong thread ID).
lock(this)
{
if (m_closed)
{
ErrorHandler.Error("Attempted to append to closed appender named ["+m_name+"].");
return;
}
// prevent re-entry
if (m_recursiveGuard)
{
return;
}
try
{
m_recursiveGuard = true;
if (FilterEvent(loggingEvent) && PreAppendCheck())
{
this.Append(loggingEvent);
}
}
catch(Exception ex)
{
ErrorHandler.Error("Failed in DoAppend", ex);
}
#if !MONO && !NET_2_0
// on .NET 2.0 (and higher) and Mono (all profiles),
// exceptions that do not derive from System.Exception will be
// wrapped in a RuntimeWrappedException by the runtime, and as
// such will be catched by the catch clause above
catch
{
// Catch handler for non System.Exception types
ErrorHandler.Error("Failed in DoAppend (unknown exception)");
}
#endif
finally
{
m_recursiveGuard = false;
}
}
}
#endregion Implementation of IAppender
#region Implementation of IBulkAppender
/// <summary>
/// Performs threshold checks and invokes filters before
/// delegating actual logging to the subclasses specific
/// <see cref="Append(LoggingEvent[])"/> method.
/// </summary>
/// <param name="loggingEvents">The array of events to log.</param>
/// <remarks>
/// <para>
/// This method cannot be overridden by derived classes. A
/// derived class should override the <see cref="Append(LoggingEvent[])"/> method
/// which is called by this method.
/// </para>
/// <para>
/// The implementation of this method is as follows:
/// </para>
/// <para>
/// <list type="bullet">
/// <item>
/// <description>
/// Checks that the severity of the <paramref name="loggingEvent"/>
/// is greater than or equal to the <see cref="Threshold"/> of this
/// appender.</description>
/// </item>
/// <item>
/// <description>
/// Checks that the <see cref="IFilter"/> chain accepts the
/// <paramref name="loggingEvent"/>.
/// </description>
/// </item>
/// <item>
/// <description>
/// Calls <see cref="PreAppendCheck()"/> and checks that
/// it returns <c>true</c>.</description>
/// </item>
/// </list>
/// </para>
/// <para>
/// If all of the above steps succeed then the <paramref name="loggingEvents"/>
/// will be passed to the <see cref="Append(LoggingEvent[])"/> method.
/// </para>
/// </remarks>
public void DoAppend(LoggingEvent[] loggingEvents)
{
// This lock is absolutely critical for correct formatting
// of the message in a multi-threaded environment. Without
// this, the message may be broken up into elements from
// multiple thread contexts (like get the wrong thread ID).
lock(this)
{
if (m_closed)
{
ErrorHandler.Error("Attempted to append to closed appender named ["+m_name+"].");
return;
}
// prevent re-entry
if (m_recursiveGuard)
{
return;
}
try
{
m_recursiveGuard = true;
ArrayList filteredEvents = new ArrayList(loggingEvents.Length);
foreach(LoggingEvent loggingEvent in loggingEvents)
{
if (FilterEvent(loggingEvent))
{
filteredEvents.Add(loggingEvent);
}
}
if (filteredEvents.Count > 0 && PreAppendCheck())
{
this.Append((LoggingEvent[])filteredEvents.ToArray(typeof(LoggingEvent)));
}
}
catch(Exception ex)
{
ErrorHandler.Error("Failed in Bulk DoAppend", ex);
}
#if !MONO && !NET_2_0
// on .NET 2.0 (and higher) and Mono (all profiles),
// exceptions that do not derive from System.Exception will be
// wrapped in a RuntimeWrappedException by the runtime, and as
// such will be catched by the catch clause above
catch
{
// Catch handler for non System.Exception types
ErrorHandler.Error("Failed in Bulk DoAppend (unknown exception)");
}
#endif
finally
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -