You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4net-dev@logging.apache.org by ni...@apache.org on 2006/03/17 21:26:54 UTC

svn commit: r386707 - in /logging/log4net/trunk: extensions/net/1.0/log4net.Ext.Trace/cs/src/TraceLogImpl.cs log4net.build src/Core/ILogger.cs src/Core/LogImpl.cs src/Repository/Hierarchy/Logger.cs src/Util/Transform.cs

Author: nicko
Date: Fri Mar 17 12:26:53 2006
New Revision: 386707

URL: http://svn.apache.org/viewcvs?rev=386707&view=rev
Log:
Fix for LOG4NET-69.
Added new wrapped implementation of String.Format in Transform.StringFormat. This method will not throw exceptions. Added some more exception handling code to the Logger.

Modified:
    logging/log4net/trunk/extensions/net/1.0/log4net.Ext.Trace/cs/src/TraceLogImpl.cs
    logging/log4net/trunk/log4net.build
    logging/log4net/trunk/src/Core/ILogger.cs
    logging/log4net/trunk/src/Core/LogImpl.cs
    logging/log4net/trunk/src/Repository/Hierarchy/Logger.cs
    logging/log4net/trunk/src/Util/Transform.cs

Modified: logging/log4net/trunk/extensions/net/1.0/log4net.Ext.Trace/cs/src/TraceLogImpl.cs
URL: http://svn.apache.org/viewcvs/logging/log4net/trunk/extensions/net/1.0/log4net.Ext.Trace/cs/src/TraceLogImpl.cs?rev=386707&r1=386706&r2=386707&view=diff
==============================================================================
--- logging/log4net/trunk/extensions/net/1.0/log4net.Ext.Trace/cs/src/TraceLogImpl.cs (original)
+++ logging/log4net/trunk/extensions/net/1.0/log4net.Ext.Trace/cs/src/TraceLogImpl.cs Fri Mar 17 12:26:53 2006
@@ -1,6 +1,6 @@
 #region Copyright & License
 //
-// Copyright 2001-2005 The Apache Software Foundation
+// Copyright 2001-2006 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.
@@ -17,8 +17,10 @@
 #endregion
 
 using System;
+using System.Globalization;
 
 using log4net.Core;
+using log4net.Util;
 
 namespace log4net.Ext.Trace
 {
@@ -68,7 +70,18 @@
 
 		public void TraceFormat(string format, params object[] args)
 		{
-			Logger.Log(ThisDeclaringType, m_levelTrace, String.Format(format, args), null);
+			if (IsTraceEnabled)
+			{
+				Logger.Log(ThisDeclaringType, m_levelTrace, Transform.StringFormat(CultureInfo.InvariantCulture, format, args), null);
+			}
+		}
+
+		public void TraceFormat(IFormatProvider provider, string format, params object[] args)
+		{
+			if (IsTraceEnabled)
+			{
+				Logger.Log(ThisDeclaringType, m_levelTrace, Transform.StringFormat(provider, format, args), null);
+			}
 		}
 
 		public bool IsTraceEnabled

Modified: logging/log4net/trunk/log4net.build
URL: http://svn.apache.org/viewcvs/logging/log4net/trunk/log4net.build?rev=386707&r1=386706&r2=386707&view=diff
==============================================================================
--- logging/log4net/trunk/log4net.build (original)
+++ logging/log4net/trunk/log4net.build Fri Mar 17 12:26:53 2006
@@ -399,6 +399,10 @@
         </if>
         <if test="${not temp.build.skip}">
             <csc keyfile="${path::combine(log4net.basedir, 'log4net.snk')}" nostdlib="true" noconfig="true" warnaserror="true" target="library" debug="${current.build.debug}" define="${current.build.defines.csc}" output="${current.bin.dir}/log4net.dll" doc="${current.bin.dir}/log4net.xml">
+                <nowarn>
+                    <!-- warning CS1058: A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException -->
+                    <warning number="1058" />
+                </nowarn>
                 <sources basedir="${log4net.basedir}/src">
                     <include name="**/*.cs" />
                 </sources>
@@ -437,6 +441,8 @@
                 <nowarn>
                     <!-- workaround for Mono bug #61902 -->
                     <warning number="0618" />
+                    <!-- warning CS1058: A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException -->
+                    <warning number="1058" />
                 </nowarn>
                 <sources basedir="${log4net.basedir}/src">
                     <include name="**/*.cs" />
@@ -474,6 +480,8 @@
                 <nowarn>
                     <!-- workaround for Mono bug #61902 -->
                     <warning number="0618" />
+                    <!-- warning CS1058: A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException -->
+                    <warning number="1058" />
                 </nowarn>
                 <sources basedir="${log4net.basedir}/src">
                     <include name="**/*.cs" />

Modified: logging/log4net/trunk/src/Core/ILogger.cs
URL: http://svn.apache.org/viewcvs/logging/log4net/trunk/src/Core/ILogger.cs?rev=386707&r1=386706&r2=386707&view=diff
==============================================================================
--- logging/log4net/trunk/src/Core/ILogger.cs (original)
+++ logging/log4net/trunk/src/Core/ILogger.cs Fri Mar 17 12:26:53 2006
@@ -1,6 +1,6 @@
 #region Copyright & License
 //
-// Copyright 2001-2005 The Apache Software Foundation
+// Copyright 2001-2006 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.
@@ -30,6 +30,11 @@
 	/// <para>
 	/// This interface supports logging events and testing if a level
 	/// is enabled for logging.
+	/// </para>
+	/// <para>
+	/// These methods will not throw exceptions. Note to implementor, ensure
+	/// that the implementation of these methods cannot allow an exception
+	/// to be thrown to the caller.
 	/// </para>
 	/// </remarks>
 	/// <author>Nicko Cadell</author>

Modified: logging/log4net/trunk/src/Core/LogImpl.cs
URL: http://svn.apache.org/viewcvs/logging/log4net/trunk/src/Core/LogImpl.cs?rev=386707&r1=386706&r2=386707&view=diff
==============================================================================
--- logging/log4net/trunk/src/Core/LogImpl.cs (original)
+++ logging/log4net/trunk/src/Core/LogImpl.cs Fri Mar 17 12:26:53 2006
@@ -1,6 +1,6 @@
 #region Copyright & License
 //
-// Copyright 2001-2005 The Apache Software Foundation
+// Copyright 2001-2006 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.
@@ -20,6 +20,7 @@
 using System.Globalization;
 
 using log4net.Repository;
+using log4net.Util;
 
 namespace log4net.Core
 {
@@ -215,7 +216,7 @@
 		{
 			if (IsDebugEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelDebug, String.Format(CultureInfo.InvariantCulture, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelDebug, Transform.StringFormat(CultureInfo.InvariantCulture, format, args), null);
 			}
 		}
 
@@ -241,7 +242,7 @@
 		{
 			if (IsDebugEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelDebug, String.Format(provider, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelDebug, Transform.StringFormat(provider, format, args), null);
 			}
 		}
 
@@ -320,7 +321,7 @@
 		{
 			if (IsInfoEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelInfo, String.Format(CultureInfo.InvariantCulture, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelInfo, Transform.StringFormat(CultureInfo.InvariantCulture, format, args), null);
 			}
 		}
 
@@ -346,7 +347,7 @@
 		{
 			if (IsInfoEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelInfo, String.Format(provider, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelInfo, Transform.StringFormat(provider, format, args), null);
 			}
 		}
 
@@ -425,7 +426,7 @@
 		{
 			if (IsWarnEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelWarn, String.Format(CultureInfo.InvariantCulture, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelWarn, Transform.StringFormat(CultureInfo.InvariantCulture, format, args), null);
 			}
 		}
 
@@ -451,7 +452,7 @@
 		{
 			if (IsWarnEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelWarn, String.Format(provider, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelWarn, Transform.StringFormat(provider, format, args), null);
 			}
 		}
 
@@ -530,7 +531,7 @@
 		{
 			if (IsErrorEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelError, String.Format(CultureInfo.InvariantCulture, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelError, Transform.StringFormat(CultureInfo.InvariantCulture, format, args), null);
 			}
 		}
 
@@ -556,7 +557,7 @@
 		{
 			if (IsErrorEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelError, String.Format(provider, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelError, Transform.StringFormat(provider, format, args), null);
 			}
 		}
 
@@ -635,7 +636,7 @@
 		{
 			if (IsFatalEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelFatal, String.Format(CultureInfo.InvariantCulture, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelFatal, Transform.StringFormat(CultureInfo.InvariantCulture, format, args), null);
 			}
 		}
 
@@ -661,7 +662,7 @@
 		{
 			if (IsFatalEnabled)
 			{
-				Logger.Log(ThisDeclaringType, m_levelFatal, String.Format(provider, format, args), null);
+				Logger.Log(ThisDeclaringType, m_levelFatal, Transform.StringFormat(provider, format, args), null);
 			}
 		}
 

Modified: logging/log4net/trunk/src/Repository/Hierarchy/Logger.cs
URL: http://svn.apache.org/viewcvs/logging/log4net/trunk/src/Repository/Hierarchy/Logger.cs?rev=386707&r1=386706&r2=386707&view=diff
==============================================================================
--- logging/log4net/trunk/src/Repository/Hierarchy/Logger.cs (original)
+++ logging/log4net/trunk/src/Repository/Hierarchy/Logger.cs Fri Mar 17 12:26:53 2006
@@ -1,6 +1,6 @@
 #region Copyright & License
 //
-// Copyright 2001-2005 The Apache Software Foundation
+// Copyright 2001-2006 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.
@@ -414,12 +414,26 @@
 		/// Generate a logging event for the specified <paramref name="level"/> using
 		/// the <paramref name="message"/> and <paramref name="exception"/>.
 		/// </para>
+		/// <para>
+		/// This method must not throw any exception to the caller.
+		/// </para>
 		/// </remarks>
 		virtual public void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception) 
 		{
-			if (IsEnabledFor(level))
+			try
+			{
+				if (IsEnabledFor(level))
+				{
+					ForcedLog((callerStackBoundaryDeclaringType != null) ? callerStackBoundaryDeclaringType : ThisDeclaringType, level, message, exception);
+				}
+			}
+			catch (Exception ex)
 			{
-				ForcedLog((callerStackBoundaryDeclaringType != null) ? callerStackBoundaryDeclaringType : ThisDeclaringType , level, message, exception);
+				log4net.Util.LogLog.Error("Log: Exception while logging", ex);
+			}
+			catch
+			{
+				log4net.Util.LogLog.Error("Log: Exception while logging");
 			}
 		}
 
@@ -432,17 +446,29 @@
 		/// <para>
 		/// Logs the specified logging event through this logger.
 		/// </para>
+		/// <para>
+		/// This method must not throw any exception to the caller.
+		/// </para>
 		/// </remarks>
-		virtual public void Log(LoggingEvent logEvent) 
+		virtual public void Log(LoggingEvent logEvent)
 		{
-			if (logEvent == null)
+			try
+			{
+				if (logEvent != null)
+				{
+					if (IsEnabledFor(logEvent.Level))
+					{
+						ForcedLog(logEvent);
+					}
+				}
+			}
+			catch (Exception ex)
 			{
-				throw new ArgumentNullException("logEvent");
+				log4net.Util.LogLog.Error("Log: Exception while logging", ex);
 			}
-
-			if (IsEnabledFor(logEvent.Level))
+			catch
 			{
-				ForcedLog(logEvent);
+				log4net.Util.LogLog.Error("Log: Exception while logging");
 			}
 		}
 
@@ -457,14 +483,32 @@
 		/// <para>
 		/// Test if this logger is going to log events of the specified <paramref name="level"/>.
 		/// </para>
+		/// <para>
+		/// This method must not throw any exception to the caller.
+		/// </para>
 		/// </remarks>
-		virtual public bool IsEnabledFor(Level level) 
+		virtual public bool IsEnabledFor(Level level)
 		{
-			if (m_hierarchy.IsDisabled(level))
+			try
+			{
+				if (level != null)
+				{
+					if (m_hierarchy.IsDisabled(level))
+					{
+						return false;
+					}
+					return level >= this.EffectiveLevel;
+				}
+			}
+			catch (Exception ex)
+			{
+				log4net.Util.LogLog.Error("Log: Exception while logging", ex);
+			}
+			catch
 			{
-				return false;
+				log4net.Util.LogLog.Error("Log: Exception while logging");
 			}
-			return level >= this.EffectiveLevel;
+			return false;
 		}
 
 		/// <summary>

Modified: logging/log4net/trunk/src/Util/Transform.cs
URL: http://svn.apache.org/viewcvs/logging/log4net/trunk/src/Util/Transform.cs?rev=386707&r1=386706&r2=386707&view=diff
==============================================================================
--- logging/log4net/trunk/src/Util/Transform.cs (original)
+++ logging/log4net/trunk/src/Util/Transform.cs Fri Mar 17 12:26:53 2006
@@ -1,6 +1,6 @@
 #region Copyright & License
 //
-// Copyright 2001-2005 The Apache Software Foundation
+// Copyright 2001-2006 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.
@@ -51,7 +51,7 @@
 
 		#endregion Private Instance Constructors
 
-		#region Public Static Methods
+		#region XML String Methods
 
 		/// <summary>
 		/// Write a string to an <see cref="XmlWriter"/>
@@ -137,8 +137,158 @@
 			return INVALIDCHARS.Replace(textData, mask);
 		}
 
-		#endregion Public Static Methods
+		#endregion XML String Methods
 
+		#region StringFormat
+
+		/// <summary>
+		/// Replaces the format item in a specified <see cref="System.String"/> with the text equivalent 
+		/// of the value of a corresponding <see cref="System.Object"/> instance in a specified array.
+		/// A specified parameter supplies culture-specific formatting information.
+		/// </summary>
+		/// <param name="provider">An <see cref="System.IFormatProvider"/> that supplies culture-specific formatting information.</param>
+		/// <param name="format">A <see cref="System.String"/> containing zero or more format items.</param>
+		/// <param name="args">An <see cref="System.Object"/> array containing zero or more objects to format.</param>
+		/// <returns>
+		/// A copy of format in which the format items have been replaced by the <see cref="System.String"/> 
+		/// equivalent of the corresponding instances of <see cref="System.Object"/> in args.
+		/// </returns>
+		/// <remarks>
+		/// <para>
+		/// This method does not throw exceptions. If an exception thrown while formatting the result the
+		/// exception and arguments are returned in the result string.
+		/// </para>
+		/// </remarks>
+		public static string StringFormat(IFormatProvider provider, string format, params object[] args)
+		{
+			try
+			{
+				// The format is missing, log null value
+				if (format == null)
+				{
+					return null;
+				}
+
+				// The args are missing - should not happen unless we are called explicitly with a null array
+				if (args == null)
+				{
+					return format;
+				}
+
+				// Try to format the string
+				return String.Format(provider, format, args);
+			}
+			catch(Exception ex)
+			{
+				log4net.Util.LogLog.Error("StringFormat: Exception while rendering format ["+format+"]", ex);
+				return StringFormatError(ex, format, args);
+			}
+			catch
+			{
+				log4net.Util.LogLog.Error("StringFormat: Exception while rendering format ["+format+"]");
+				return StringFormatError(null, format, args);
+			}
+		}
+
+		/// <summary>
+		/// Process an error during StringFormat
+		/// </summary>
+		private static string StringFormatError(Exception formatException, string format, object[] args)
+		{
+			try
+			{
+				StringBuilder buf = new StringBuilder("<log4net.Error>");
+
+				if (formatException != null)
+				{
+					buf.Append("Exception during StringFormat: ").Append(formatException.Message);
+				}
+				else
+				{
+					buf.Append("Exception during StringFormat");
+				}
+				buf.Append(" <format>").Append(format).Append("</format>");
+				buf.Append("<args>");
+				RenderArray(args, buf);
+				buf.Append("</args>");
+				buf.Append("</log4net.Error>");
+
+				return buf.ToString();
+			}
+			catch(Exception ex)
+			{
+				log4net.Util.LogLog.Error("StringFormat: INTERNAL ERROR during StringFormat error handling", ex);
+				return "<log4net.Error>Exception during StringFormat. See Internal Log.</log4net.Error>";
+			}
+			catch
+			{
+				log4net.Util.LogLog.Error("StringFormat: INTERNAL ERROR during StringFormat error handling");
+				return "<log4net.Error>Exception during StringFormat. See Internal Log.</log4net.Error>";
+			}
+		}
+
+		/// <summary>
+		/// Dump the contents of an array into a string builder
+		/// </summary>
+		private static void RenderArray(Array array, StringBuilder buffer)
+		{
+			if (array == null)
+			{
+				buffer.Append(SystemInfo.NullText);
+			}
+			else
+			{
+				if (array.Rank != 1)
+				{
+					buffer.Append(array.ToString());
+				}
+				else
+				{
+					buffer.Append("{");
+					int len = array.Length;
+
+					if (len > 0)
+					{
+						RenderObject(array.GetValue(0), buffer);
+						for (int i = 1; i < len; i++)
+						{
+							buffer.Append(", ");
+							RenderObject(array.GetValue(i), buffer);
+						}
+					}
+					buffer.Append("}");
+				}
+			}
+		}
+
+		/// <summary>
+		/// Dump an object to a string
+		/// </summary>
+		private static void RenderObject(Object obj, StringBuilder buffer)
+		{
+			if (obj == null)
+			{
+				buffer.Append(SystemInfo.NullText);
+			}
+			else
+			{
+				try
+				{
+					buffer.Append(obj);
+				}
+				catch(Exception ex)
+				{
+					buffer.Append("<Exception: ").Append(ex.Message).Append(">");
+				}
+				catch
+				{
+					buffer.Append("<Exception>");
+				}
+			}
+		}
+
+		#endregion StringFormat
+		
 		#region Private Helper Methods
 
 		/// <summary>