logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dpsen...@apache.org
Subject svn commit: r1461433 - /logging/log4net/trunk/src/Appender/RemoteSyslogAppender.cs
Date Wed, 27 Mar 2013 07:25:11 GMT
Author: dpsenner
Date: Wed Mar 27 07:25:11 2013
New Revision: 1461433

URL: http://svn.apache.org/r1461433
Log:
LOG4NET-370 fix the RemoteSyslogAppender to properly handle log messages that contain newlines

This patch is based on the work of Jarrod Alexander. Please note that this patch also fixes
indentation issues and thus contains some portions of refactoring. Finally it is worth to
note
that the patch primarily focuses on making the syslog messages RFC3164 (http://www.ietf.org/rfc/rfc3164.txt)
compliant. The signifant parts of the RFC are:

4.1.3 MSG Part of a syslog Packet 

   The MSG part will fill the remainder of the syslog packet. This will 
   usually contain some additional information of the process that 
   generated the message, and then the text of the message. There is no 
   ending delimiter to this part. The MSG part of the syslog packet 
   MUST contain visible (printing) characters. The code set 
   traditionally and most often used has also been seven-bit ASCII in an 
   eight-bit field like that used in the PRI and HEADER parts. In this 
   code set, the only allowable characters are the ABNF VCHAR values 
   (%d33-126) and spaces (SP value %d32). However, no indication of the 
   code set used within the MSG is required, nor is it expected. Other 
   code sets MAY be used as long as the characters used in the MSG are 
   exclusively visible characters and spaces similar to those described 
   above. The selection of a code set used in the MSG part SHOULD be 
   made with thoughts of the intended receiver. A message containing 
   characters in a code set that cannot be viewed or understood by a 
   recipient will yield no information of value to an operator or 
   administrator looking at it. 

Modified:
    logging/log4net/trunk/src/Appender/RemoteSyslogAppender.cs

Modified: logging/log4net/trunk/src/Appender/RemoteSyslogAppender.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/RemoteSyslogAppender.cs?rev=1461433&r1=1461432&r2=1461433&view=diff
==============================================================================
--- logging/log4net/trunk/src/Appender/RemoteSyslogAppender.cs (original)
+++ logging/log4net/trunk/src/Appender/RemoteSyslogAppender.cs Wed Mar 27 07:25:11 2013
@@ -24,7 +24,7 @@ using log4net.Appender;
 using log4net.Util;
 using log4net.Layout;
 
-namespace log4net.Appender 
+namespace log4net.Appender
 {
 	/// <summary>
 	/// Logs events to a remote syslog daemon.
@@ -66,7 +66,7 @@ namespace log4net.Appender 
 	/// </remarks>
 	/// <author>Rob Lyon</author>
 	/// <author>Nicko Cadell</author>
-	public class RemoteSyslogAppender : UdpAppender 
+	public class RemoteSyslogAppender : UdpAppender
 	{
 		/// <summary>
 		/// Syslog port 514
@@ -268,7 +268,7 @@ namespace log4net.Appender 
 		/// This instance of the <see cref="RemoteSyslogAppender" /> class is set up to write

 		/// to a remote syslog daemon.
 		/// </remarks>
-		public RemoteSyslogAppender() 
+		public RemoteSyslogAppender()
 		{
 			// syslog udp defaults
 			this.RemotePort = DefaultSyslogPort;
@@ -279,7 +279,7 @@ namespace log4net.Appender 
 		#endregion Public Instance Constructors
 
 		#region Public Instance Properties
-		
+
 		/// <summary>
 		/// Message identity
 		/// </summary>
@@ -310,7 +310,7 @@ namespace log4net.Appender 
 			get { return m_facility; }
 			set { m_facility = value; }
 		}
-		
+
 		#endregion Public Instance Properties
 
 		/// <summary>
@@ -341,46 +341,68 @@ namespace log4net.Appender 
 		/// The format of the output will depend on the appender's layout.
 		/// </para>
 		/// </remarks>
-		protected override void Append(LoggingEvent loggingEvent) 
+		protected override void Append(LoggingEvent loggingEvent)
 		{
-			try 
+			try
 			{
-				System.IO.StringWriter writer = new System.IO.StringWriter(System.Globalization.CultureInfo.InvariantCulture);
+				using (ReusableStringWriter writer = new ReusableStringWriter(System.Globalization.CultureInfo.InvariantCulture))
+				{
+					// Priority
+					int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level));
 
-				// Priority
-				int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level));
-				writer.Write('<');
-				writer.Write(priority);
-				writer.Write('>');
+					// Identity
+					string identity;
 
-				// Identity
-				if (m_identity != null)
-				{
-					m_identity.Format(writer, loggingEvent);
-				}
-				else
-				{
-					writer.Write(loggingEvent.Domain);
-				}
-				writer.Write(": ");
+					if (m_identity != null)
+					{
+						identity = m_identity.Format(loggingEvent);
+					}
+					else
+					{
+						identity = loggingEvent.Domain;
+					}
+
+					// Message. The message goes after the tag/identity
+					string message = RenderLoggingEvent(loggingEvent);
+
+					// Split message by line to ensure that the syslog
+					// message is compliant to the RFC 
+					// http://www.ietf.org/rfc/rfc3164.txt in section 4.1.3
+					string[] lines = message.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
+
+					Byte[] buffer;
+
+					foreach (string line in lines)
+					{
+						writer.Reset(c_renderBufferMaxCapacity, c_renderBufferSize);
+
+						// Write priority
+						writer.Write('<');
+						writer.Write(priority);
+						writer.Write('>');
+
+						// Write identity
+						writer.Write(identity);
+						writer.Write(": ");
+
+						// Write message line
+						writer.Write(line);
 
-				// Message. The message goes after the tag/identity
-				RenderLoggingEvent(writer, loggingEvent);
+						// Grab as a byte array
+						buffer = this.Encoding.GetBytes(writer.ToString());
 
-				// Grab as a byte array
-				string fullMessage = writer.ToString();
-				Byte [] buffer = this.Encoding.GetBytes(fullMessage.ToCharArray());
-
-				this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint);
-			} 
-			catch (Exception e) 
+						this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint);
+					}
+				}
+			}
+			catch (Exception e)
 			{
 				ErrorHandler.Error(
-					"Unable to send logging event to remote syslog " + 
-					this.RemoteAddress.ToString() + 
-					" on port " + 
-					this.RemotePort + ".", 
-					e, 
+					"Unable to send logging event to remote syslog " +
+					this.RemoteAddress.ToString() +
+					" on port " +
+					this.RemotePort + ".",
+					e,
 					ErrorCode.WriteFailure);
 			}
 		}
@@ -425,30 +447,30 @@ namespace log4net.Appender 
 			// Fallback to sensible default values
 			//
 
-			if (level >= Level.Alert) 
+			if (level >= Level.Alert)
 			{
 				return SyslogSeverity.Alert;
-			} 
-			else if (level >= Level.Critical) 
+			}
+			else if (level >= Level.Critical)
 			{
 				return SyslogSeverity.Critical;
-			} 
-			else if (level >= Level.Error) 
+			}
+			else if (level >= Level.Error)
 			{
 				return SyslogSeverity.Error;
-			} 
-			else if (level >= Level.Warn) 
+			}
+			else if (level >= Level.Warn)
 			{
 				return SyslogSeverity.Warning;
-			} 
-			else if (level >= Level.Notice) 
+			}
+			else if (level >= Level.Notice)
 			{
 				return SyslogSeverity.Notice;
-			} 
-			else if (level >= Level.Info) 
+			}
+			else if (level >= Level.Info)
 			{
 				return SyslogSeverity.Informational;
-			} 
+			}
 			// Default setting
 			return SyslogSeverity.Debug;
 		}
@@ -505,6 +527,16 @@ namespace log4net.Appender 
 		/// </summary>
 		private LevelMapping m_levelMapping = new LevelMapping();
 
+		/// <summary>
+		/// Initial buffer size
+		/// </summary>
+		private const int c_renderBufferSize = 256;
+
+		/// <summary>
+		/// Maximum buffer size before it is recycled
+		/// </summary>
+		private const int c_renderBufferMaxCapacity = 1024;
+
 		#endregion Private Instances Fields
 
 		#region LevelSeverity LevelMapping Entry



Mime
View raw message