#region Apache License // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you 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.Collections; #if !NETSTANDARD1_3 using System.Configuration; #endif using System.Diagnostics; namespace log4net.Util { /// /// /// /// /// public delegate void LogReceivedEventHandler(object source, LogReceivedEventArgs e); /// /// Outputs log statements from within the log4net assembly. /// /// /// /// Log4net components cannot make log4net logging calls. However, it is /// sometimes useful for the user to learn about what log4net is /// doing. /// /// /// All log4net internal debug calls go to the standard output stream /// whereas internal error messages are sent to the standard error output /// stream. /// /// /// Nicko Cadell /// Gert Driesen public sealed class LogLog { /// /// The event raised when an internal message has been received. /// public static event LogReceivedEventHandler LogReceived; private readonly Type source; private readonly DateTime timeStampUtc; private readonly string prefix; private readonly string message; private readonly Exception exception; /// /// The Type that generated the internal message. /// public Type Source { get { return source; } } /// /// The DateTime stamp of when the internal message was received. /// public DateTime TimeStamp { get { return timeStampUtc.ToLocalTime(); } } /// /// The UTC DateTime stamp of when the internal message was received. /// public DateTime TimeStampUtc { get { return timeStampUtc; } } /// /// A string indicating the severity of the internal message. /// /// /// "log4net: ", /// "log4net:ERROR ", /// "log4net:WARN " /// public string Prefix { get { return prefix; } } /// /// The internal log message. /// public string Message { get { return message; } } /// /// The Exception related to the message. /// /// /// Optional. Will be null if no Exception was passed. /// public Exception Exception { get { return exception; } } /// /// Formats Prefix, Source, and Message in the same format as the value /// sent to Console.Out and Trace.Write. /// /// public override string ToString() { return Prefix + Source.Name + ": " + Message; } #region Private Instance Constructors /// /// Initializes a new instance of the class. /// /// /// /// /// public LogLog(Type source, string prefix, string message, Exception exception) { timeStampUtc = DateTime.UtcNow; this.source = source; this.prefix = prefix; this.message = message; this.exception = exception; } #endregion Private Instance Constructors #region Static Constructor /// /// Static constructor that initializes logging by reading /// settings from the application configuration file. /// /// /// /// The log4net.Internal.Debug application setting /// controls internal debugging. This setting should be set /// to true to enable debugging. /// /// /// The log4net.Internal.Quiet application setting /// suppresses all internal logging including error messages. /// This setting should be set to true to enable message /// suppression. /// /// static LogLog() { #if !NETCF try { InternalDebugging = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Debug"), false); QuietMode = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Quiet"), false); EmitInternalMessages = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Emit"), true); } catch(Exception ex) { // If an exception is thrown here then it looks like the config file does not // parse correctly. // // We will leave debug OFF and print an Error message Error(typeof(LogLog), "Exception while reading ConfigurationSettings. Check your .config file is well formed XML.", ex); } #endif } #endregion Static Constructor #region Public Static Properties /// /// Gets or sets a value indicating whether log4net internal logging /// is enabled or disabled. /// /// /// true if log4net internal logging is enabled, otherwise /// false. /// /// /// /// When set to true, internal debug level logging will be /// displayed. /// /// /// This value can be set by setting the application setting /// log4net.Internal.Debug in the application configuration /// file. /// /// /// The default value is false, i.e. debugging is /// disabled. /// /// /// /// /// The following example enables internal debugging using the /// application configuration file : /// /// /// /// /// /// /// /// /// public static bool InternalDebugging { get { return s_debugEnabled; } set { s_debugEnabled = value; } } /// /// Gets or sets a value indicating whether log4net should generate no output /// from internal logging, not even for errors. /// /// /// true if log4net should generate no output at all from internal /// logging, otherwise false. /// /// /// /// When set to true will cause internal logging at all levels to be /// suppressed. This means that no warning or error reports will be logged. /// This option overrides the setting and /// disables all debug also. /// /// This value can be set by setting the application setting /// log4net.Internal.Quiet in the application configuration file. /// /// /// The default value is false, i.e. internal logging is not /// disabled. /// /// /// /// The following example disables internal logging using the /// application configuration file : /// /// /// /// /// /// /// /// public static bool QuietMode { get { return s_quietMode; } set { s_quietMode = value; } } /// /// /// public static bool EmitInternalMessages { get { return s_emitInternalMessages; } set { s_emitInternalMessages = value; } } #endregion Public Static Properties #region Public Static Methods /// /// Raises the LogReceived event when an internal messages is received. /// /// /// /// /// public static void OnLogReceived(Type source, string prefix, string message, Exception exception) { if (LogReceived != null) { LogReceived(null, new LogReceivedEventArgs(new LogLog(source, prefix, message, exception))); } } /// /// Test if LogLog.Debug is enabled for output. /// /// /// true if Debug is enabled /// /// /// /// Test if LogLog.Debug is enabled for output. /// /// public static bool IsDebugEnabled { get { return s_debugEnabled && !s_quietMode; } } /// /// Writes log4net internal debug messages to the /// standard output stream. /// /// /// The message to log. /// /// /// All internal debug messages are prepended with /// the string "log4net: ". /// /// public static void Debug(Type source, string message) { if (IsDebugEnabled) { if (EmitInternalMessages) { EmitOutLine(PREFIX + message); } OnLogReceived(source, PREFIX, message, null); } } /// /// Writes log4net internal debug messages to the /// standard output stream. /// /// The Type that generated this message. /// The message to log. /// An exception to log. /// /// /// All internal debug messages are prepended with /// the string "log4net: ". /// /// public static void Debug(Type source, string message, Exception exception) { if (IsDebugEnabled) { if (EmitInternalMessages) { EmitOutLine(PREFIX + message); if (exception != null) { EmitOutLine(exception.ToString()); } } OnLogReceived(source, PREFIX, message, exception); } } /// /// Test if LogLog.Warn is enabled for output. /// /// /// true if Warn is enabled /// /// /// /// Test if LogLog.Warn is enabled for output. /// /// public static bool IsWarnEnabled { get { return !s_quietMode; } } /// /// Writes log4net internal warning messages to the /// standard error stream. /// /// The Type that generated this message. /// The message to log. /// /// /// All internal warning messages are prepended with /// the string "log4net:WARN ". /// /// public static void Warn(Type source, string message) { if (IsWarnEnabled) { if (EmitInternalMessages) { EmitErrorLine(WARN_PREFIX + message); } OnLogReceived(source, WARN_PREFIX, message, null); } } /// /// Writes log4net internal warning messages to the /// standard error stream. /// /// The Type that generated this message. /// The message to log. /// An exception to log. /// /// /// All internal warning messages are prepended with /// the string "log4net:WARN ". /// /// public static void Warn(Type source, string message, Exception exception) { if (IsWarnEnabled) { if (EmitInternalMessages) { EmitErrorLine(WARN_PREFIX + message); if (exception != null) { EmitErrorLine(exception.ToString()); } } OnLogReceived(source, WARN_PREFIX, message, exception); } } /// /// Test if LogLog.Error is enabled for output. /// /// /// true if Error is enabled /// /// /// /// Test if LogLog.Error is enabled for output. /// /// public static bool IsErrorEnabled { get { return !s_quietMode; } } /// /// Writes log4net internal error messages to the /// standard error stream. /// /// The Type that generated this message. /// The message to log. /// /// /// All internal error messages are prepended with /// the string "log4net:ERROR ". /// /// public static void Error(Type source, string message) { if (IsErrorEnabled) { if (EmitInternalMessages) { EmitErrorLine(ERR_PREFIX + message); } OnLogReceived(source, ERR_PREFIX, message, null); } } /// /// Writes log4net internal error messages to the /// standard error stream. /// /// The Type that generated this message. /// The message to log. /// An exception to log. /// /// /// All internal debug messages are prepended with /// the string "log4net:ERROR ". /// /// public static void Error(Type source, string message, Exception exception) { if (IsErrorEnabled) { if (EmitInternalMessages) { EmitErrorLine(ERR_PREFIX + message); if (exception != null) { EmitErrorLine(exception.ToString()); } } OnLogReceived(source, ERR_PREFIX, message, exception); } } #endregion Public Static Methods /// /// Writes output to the standard output stream. /// /// The message to log. /// /// /// Writes to both Console.Out and System.Diagnostics.Trace. /// Note that the System.Diagnostics.Trace is not supported /// on the Compact Framework. /// /// /// If the AppDomain is not configured with a config file then /// the call to System.Diagnostics.Trace may fail. This is only /// an issue if you are programmatically creating your own AppDomains. /// /// private static void EmitOutLine(string message) { try { #if NETCF Console.WriteLine(message); //System.Diagnostics.Debug.WriteLine(message); #else Console.Out.WriteLine(message); Trace.WriteLine(message); #endif } catch { // Ignore exception, what else can we do? Not really a good idea to propagate back to the caller } } /// /// Writes output to the standard error stream. /// /// The message to log. /// /// /// Writes to both Console.Error and System.Diagnostics.Trace. /// Note that the System.Diagnostics.Trace is not supported /// on the Compact Framework. /// /// /// If the AppDomain is not configured with a config file then /// the call to System.Diagnostics.Trace may fail. This is only /// an issue if you are programmatically creating your own AppDomains. /// /// private static void EmitErrorLine(string message) { try { #if NETCF Console.WriteLine(message); //System.Diagnostics.Debug.WriteLine(message); #else Console.Error.WriteLine(message); Trace.WriteLine(message); #endif } catch { // Ignore exception, what else can we do? Not really a good idea to propagate back to the caller } } #region Private Static Fields /// /// Default debug level /// private static bool s_debugEnabled = false; /// /// In quietMode not even errors generate any output. /// private static bool s_quietMode = false; private static bool s_emitInternalMessages = true; private const string PREFIX = "log4net: "; private const string ERR_PREFIX = "log4net:ERROR "; private const string WARN_PREFIX = "log4net:WARN "; #endregion Private Static Fields /// /// Subscribes to the LogLog.LogReceived event and stores messages /// to the supplied IList instance. /// public class LogReceivedAdapter : IDisposable { private readonly IList items; private readonly LogReceivedEventHandler handler; /// /// /// /// public LogReceivedAdapter(IList items) { this.items = items; handler = new LogReceivedEventHandler(LogLog_LogReceived); LogReceived += handler; } void LogLog_LogReceived(object source, LogReceivedEventArgs e) { items.Add(e.LogLog); } /// /// /// public IList Items { get { return items; } } /// /// /// public void Dispose() { LogReceived -= handler; } } } /// /// /// public class LogReceivedEventArgs : EventArgs { private readonly LogLog loglog; /// /// /// /// public LogReceivedEventArgs(LogLog loglog) { this.loglog = loglog; } /// /// /// public LogLog LogLog { get { return loglog; } } } }