Author: carnold Date: Thu Feb 22 13:43:36 2007 New Revision: 510660 URL: http://svn.apache.org/viewvc?view=rev&rev=510660 Log: Bug 41040: SyslogAppender should prefix message with TIMESTAMP and local hostname
Modified: logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/helpers/SyslogWriter.java logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/net/SyslogAppender.java logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/net/SyslogAppenderTest.java Modified: logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/helpers/SyslogWriter.java URL: http://svn.apache.org/viewvc/logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/helpers/SyslogWriter.java?view=diff&rev=510660&r1=510659&r2=510660 ============================================================================== --- logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/helpers/SyslogWriter.java (original) +++ logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/helpers/SyslogWriter.java Thu Feb 22 13:43:36 2007 @@ -56,7 +56,7 @@ */ public SyslogWriter(final String syslogHost) { - this.syslogHost = syslogHost; + SyslogWriter.syslogHost = syslogHost; if (syslogHost == null) { throw new NullPointerException("syslogHost"); } Modified: logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/net/SyslogAppender.java URL: http://svn.apache.org/viewvc/logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/net/SyslogAppender.java?view=diff&rev=510660&r1=510659&r2=510660 ============================================================================== --- logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/net/SyslogAppender.java (original) +++ logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/net/SyslogAppender.java Thu Feb 22 13:43:36 2007 @@ -17,10 +17,16 @@ package org.apache.log4j.net; import org.apache.log4j.AppenderSkeleton; -import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.Layout; -import org.apache.log4j.helpers.SyslogWriter; import org.apache.log4j.helpers.SyslogQuietWriter; +import org.apache.log4j.helpers.SyslogWriter; +import org.apache.log4j.spi.LoggingEvent; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.net.InetAddress; +import java.net.UnknownHostException; // Contributors: Yves Bossel <[EMAIL PROTECTED]> // Christopher Taylor <[EMAIL PROTECTED]> @@ -94,6 +100,23 @@ SyslogQuietWriter sqw; String syslogHost; + /** + * If true, the appender will generate the HEADER (timestamp and host name) + * part of the syslog packet. + * @since 1.2.15 + */ + private boolean header = false; + /** + * Date format used if header = true. + * @since 1.2.15 + */ + private final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd HH:mm:ss ", Locale.ENGLISH); + /** + * Host name used to identify messages from this appender. + * @since 1.2.15 + */ + private String localHostname; + public SyslogAppender() { this.initSyslogFacilityStr(); @@ -252,20 +275,28 @@ return; } - String buffer = (facilityPrinting? facilityStr : "") + - layout.format(event); + String hdr = getPacketHeader(event.timeStamp); + String packet = layout.format(event); + if(facilityPrinting || hdr.length() > 0) { + StringBuffer buf = new StringBuffer(hdr); + if(facilityPrinting) { + buf.append(facilityStr); + } + buf.append(packet); + packet = buf.toString(); + } sqw.setLevel(event.getLevel().getSyslogEquivalent()); - sqw.write(buffer); + sqw.write(packet); if (layout.ignoresThrowable()) { String[] s = event.getThrowableStrRep(); if (s != null) { for(int i = 0; i < s.length; i++) { if (s[i].startsWith("\t")) { - sqw.write(TAB+s[i].substring(1)); + sqw.write(hdr+TAB+s[i].substring(1)); } else { - sqw.write(s[i]); + sqw.write(hdr+s[i]); } } } @@ -278,6 +309,9 @@ */ public void activateOptions() { + if (header) { + getLocalHostname(); + } } /** @@ -368,5 +402,61 @@ public boolean getFacilityPrinting() { return facilityPrinting; + } + + /** + * If true, the appender will generate the HEADER part (that is, timestamp and host name) + * of the syslog packet. Default value is false for compatibility with existing behavior, + * however should be true unless there is a specific justification. + * @since 1.2.15 + */ + public final boolean getHeader() { + return header; + } + + /** + * Returns whether the appender produces the HEADER part (that is, timestamp and host name) + * of the syslog packet. + * @since 1.2.15 + */ + public final void setHeader(final boolean val) { + header = val; + } + + /** + * Get the host name used to identify this appender. + * @return local host name + * @since 1.2.15 + */ + private String getLocalHostname() { + if (localHostname == null) { + try { + InetAddress addr = InetAddress.getLocalHost(); + localHostname = addr.getHostName(); + } catch (UnknownHostException uhe) { + localHostname = "UNKNOWN_HOST"; + } + } + return localHostname; + } + + /** + * Gets HEADER portion of packet. + * @param timeStamp number of milliseconds after the standard base time. + * @return HEADER portion of packet, will be zero-length string if header is false. + * @since 1.2.15 + */ + private String getPacketHeader(final long timeStamp) { + if (header) { + StringBuffer buf = new StringBuffer(dateFormat.format(new Date(timeStamp))); + // RFC 3164 says leading space, not leading zero on days 1-9 + if (buf.charAt(4) == '0') { + buf.setCharAt(4, ' '); + } + buf.append(getLocalHostname()); + buf.append(' '); + return buf.toString(); + } + return ""; } } Modified: logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/net/SyslogAppenderTest.java URL: http://svn.apache.org/viewvc/logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/net/SyslogAppenderTest.java?view=diff&rev=510660&r1=510659&r2=510660 ============================================================================== --- logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/net/SyslogAppenderTest.java (original) +++ logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/net/SyslogAppenderTest.java Thu Feb 22 13:43:36 2007 @@ -29,13 +29,17 @@ import java.util.StringTokenizer; import java.net.DatagramSocket; import java.net.DatagramPacket; +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.Date; +import java.util.Calendar; /** * Tests for SyslogAppender * - * @author Curt Arnold - **/ + * + * */ public class SyslogAppenderTest extends TestCase { /** * Create new instance of SyslogAppenderTest. @@ -387,7 +391,8 @@ appender.setSyslogHost("127.0.0.1:1514"); } - private static String[] log(final String msg, + private static String[] log(final boolean header, + final String msg, final Exception ex, final int packets) throws Exception { DatagramSocket ds = new DatagramSocket(); @@ -397,6 +402,7 @@ SyslogAppender appender = new SyslogAppender(); appender.setSyslogHost("localhost:" + ds.getLocalPort()); appender.setName("name"); + appender.setHeader(header); PatternLayout pl = new PatternLayout("%m"); appender.setLayout(pl); appender.activateOptions(); @@ -419,7 +425,7 @@ } public void testActualLogging() throws Exception { - String s = log("greetings", null, 1)[0]; + String s = log(false, "greetings", null, 1)[0]; StringTokenizer st = new StringTokenizer(s, "<>() "); assertEquals("14", st.nextToken()); assertEquals("greetings", st.nextToken()); @@ -444,6 +450,7 @@ w.println(""); w.println("No tab here"); w.println("\ttab here"); + w.println("\t"); } } @@ -452,7 +459,7 @@ * @throws Exception on IOException. */ public void testBadTabbing() throws Exception { - String[] s = log("greetings", new MishandledException(), 5); + String[] s = log(false, "greetings", new MishandledException(), 6); StringTokenizer st = new StringTokenizer(s[0], "<>() "); assertEquals("11", st.nextToken()); assertEquals("greetings", st.nextToken()); @@ -460,6 +467,46 @@ assertEquals("<11>", s[2]); assertEquals("<11>No tab here", s[3]); assertEquals("<11>" + SyslogAppender.TAB + "tab here", s[4]); + assertEquals("<11>" + SyslogAppender.TAB, s[5]); + } + + /** + * Tests presence of timestamp if header = true. + * + * @throws Exception if IOException. + */ + public void testHeaderLogging() throws Exception { + Date preDate = new Date(); + String s = log(true, "greetings", null, 1)[0]; + Date postDate = new Date(); + assertEquals("<14>", s.substring(0, 4)); + + String syslogDateStr = s.substring(4, 20); + SimpleDateFormat fmt = new SimpleDateFormat("MMM dd HH:mm:ss ", Locale.ENGLISH); + Date syslogDate = fmt.parse(syslogDateStr); + Calendar cal = Calendar.getInstance(Locale.ENGLISH); + cal.setTime(syslogDate); + int syslogMonth = cal.get(Calendar.MONTH); + int syslogDay = cal.get(Calendar.DATE); + if (syslogDay < 10) { + assertEquals(' ', syslogDateStr.charAt(4)); + } + cal.setTime(preDate); + int preMonth = cal.get(Calendar.MONTH); + cal.set(Calendar.MILLISECOND, 0); + preDate = cal.getTime(); + int syslogYear; + if (preMonth == syslogMonth) { + syslogYear = cal.get(Calendar.YEAR); + } else { + cal.setTime(postDate); + syslogYear = cal.get(Calendar.YEAR); + } + cal.setTime(syslogDate); + cal.set(Calendar.YEAR, syslogYear); + syslogDate = cal.getTime(); + assertTrue(syslogDate.compareTo(preDate) >= 0); + assertTrue(syslogDate.compareTo(postDate) <= 0); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]