Index: src/Appender/RemoteSyslogAppender.cs =================================================================== --- src/Appender/RemoteSyslogAppender.cs (revision 1461158) +++ src/Appender/RemoteSyslogAppender.cs (working copy) @@ -24,7 +24,7 @@ using log4net.Util; using log4net.Layout; -namespace log4net.Appender +namespace log4net.Appender { /// /// Logs events to a remote syslog daemon. @@ -66,7 +66,7 @@ /// /// Rob Lyon /// Nicko Cadell - public class RemoteSyslogAppender : UdpAppender + public class RemoteSyslogAppender : UdpAppender { /// /// Syslog port 514 @@ -268,7 +268,7 @@ /// This instance of the class is set up to write /// to a remote syslog daemon. /// - public RemoteSyslogAppender() + public RemoteSyslogAppender() { // syslog udp defaults this.RemotePort = DefaultSyslogPort; @@ -279,7 +279,7 @@ #endregion Public Instance Constructors #region Public Instance Properties - + /// /// Message identity /// @@ -310,7 +310,7 @@ get { return m_facility; } set { m_facility = value; } } - + #endregion Public Instance Properties /// @@ -341,46 +341,72 @@ /// The format of the output will depend on the appender's layout. /// /// - 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 - RenderLoggingEvent(writer, loggingEvent); + // Message. The message goes after the tag/identity + string message = RenderLoggingEvent(loggingEvent); - // Grab as a byte array - string fullMessage = writer.ToString(); - Byte [] buffer = this.Encoding.GetBytes(fullMessage.ToCharArray()); + // make sure that the message does contain only \n newlines and no variations of + // \r \n \r\n or \n\r + message = message.Replace("\r\n", "\n"); + message = message.Replace("\n\r", "\n"); + message = message.Replace("\r", "\n"); - this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint); - } - catch (Exception e) + // Split message by line + string[] lines = message.Split(new string[] { "\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); + + // Grab as a byte array + buffer = this.Encoding.GetBytes(writer.ToString()); + + 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 +451,30 @@ // 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 +531,16 @@ /// private LevelMapping m_levelMapping = new LevelMapping(); + /// + /// Initial buffer size + /// + private const int c_renderBufferSize = 256; + + /// + /// Maximum buffer size before it is recycled + /// + private const int c_renderBufferMaxCapacity = 1024; + #endregion Private Instances Fields #region LevelSeverity LevelMapping Entry