Return-Path: X-Original-To: apmail-logging-commits-archive@minotaur.apache.org Delivered-To: apmail-logging-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1DBAD1020B for ; Wed, 2 Oct 2013 14:49:27 +0000 (UTC) Received: (qmail 66168 invoked by uid 500); 2 Oct 2013 14:49:26 -0000 Delivered-To: apmail-logging-commits-archive@logging.apache.org Received: (qmail 66147 invoked by uid 500); 2 Oct 2013 14:49:22 -0000 Mailing-List: contact commits-help@logging.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@logging.apache.org Delivered-To: mailing list commits@logging.apache.org Received: (qmail 66140 invoked by uid 99); 2 Oct 2013 14:49:21 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 02 Oct 2013 14:49:21 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 02 Oct 2013 14:49:17 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 349F32388980; Wed, 2 Oct 2013 14:48:55 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1528503 - in /logging/log4j/log4j2/trunk: log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ log4j-core/src/test/java/org/apache/logging/log4j/core/layout/ src/changes/ src/site/xdoc/manual/ Date: Wed, 02 Oct 2013 14:48:55 -0000 To: commits@logging.apache.org From: ggregory@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20131002144855.349F32388980@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: ggregory Date: Wed Oct 2 14:48:54 2013 New Revision: 1528503 URL: http://svn.apache.org/r1528503 Log: [lOG4J2-415] Format log event time as UNIX time (seconds or milliseconds). Modified: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java logging/log4j/log4j2/trunk/src/changes/changes.xml logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm Modified: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java?rev=1528503&r1=1528502&r2=1528503&view=diff ============================================================================== --- logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java (original) +++ logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java Wed Oct 2 14:48:54 2013 @@ -27,9 +27,53 @@ import org.apache.logging.log4j.core.con * Convert and format the event's date in a StringBuilder. */ @Plugin(name = "DatePatternConverter", category = "Converter") -@ConverterKeys({"d", "date" }) +@ConverterKeys({ "d", "date" }) public final class DatePatternConverter extends LogEventPatternConverter implements ArrayPatternConverter { + private abstract static class Formatter { + abstract String format(long time); + + public String toPattern() { + return null; + } + } + + private static class PatternFormatter extends Formatter { + private final SimpleDateFormat simpleDateFormat; + + PatternFormatter(SimpleDateFormat simpleDateFormat) { + this.simpleDateFormat = simpleDateFormat; + } + + @Override + String format(long time) { + return simpleDateFormat.format(Long.valueOf(time)); + } + + @Override + public String toPattern() { + return simpleDateFormat.toPattern(); + } + } + + private static class UnixFormatter extends Formatter { + + @Override + String format(long time) { + return Long.toString(time / 1000); + } + + } + + private static class UnixMillisFormatter extends Formatter { + + @Override + String format(long time) { + return Long.toString(time); + } + + } + /** * ABSOLUTE string literal. */ @@ -81,9 +125,20 @@ public final class DatePatternConverter private static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; /** + * UNIX formatter in seconds (standard). + */ + private static final String UNIX_FORMAT = "UNIX"; + + /** + * UNIX formatter in milliseconds + */ + private static final String UNIX_MILLIS_FORMAT = "UNIX_MILLIS"; + + /** * Obtains an instance of pattern converter. - * - * @param options options, may be null. + * + * @param options + * options, may be null. * @return instance of pattern converter. */ public static DatePatternConverter newInstance(final String[] options) { @@ -95,29 +150,24 @@ public final class DatePatternConverter */ private String cachedDateString; - private long lastTimestamp; + private final Formatter formatter; - private final SimpleDateFormat simpleFormat; + private long lastTimestamp; /** * Private constructor. - * - * @param options options, may be null. + * + * @param options + * options, may be null. */ private DatePatternConverter(final String[] options) { super("Date", "date"); - String patternOption; + // null patternOption is OK. + final String patternOption = options != null && options.length > 0 ? options[0] : null; - if (options == null || options.length == 0) { - // the branch could be optimized, but here we are making explicit - // that null values for patternOption are allowed. - patternOption = null; - } else { - patternOption = options[0]; - } - - String pattern; + String pattern = null; + Formatter tempFormatter = null; if (patternOption == null || patternOption.equalsIgnoreCase(ISO8601_FORMAT)) { pattern = ISO8601_PATTERN; @@ -129,38 +179,47 @@ public final class DatePatternConverter pattern = DATE_AND_TIME_PATTERN; } else if (patternOption.equalsIgnoreCase(COMPACT_FORMAT)) { pattern = COMPACT_PATTERN; + } else if (patternOption.equalsIgnoreCase(UNIX_FORMAT)) { + tempFormatter = new UnixFormatter(); + } else if (patternOption.equalsIgnoreCase(UNIX_MILLIS_FORMAT)) { + tempFormatter = new UnixMillisFormatter(); } else { pattern = patternOption; } - SimpleDateFormat tempFormat; + if (pattern != null) { + SimpleDateFormat tempFormat; - try { - tempFormat = new SimpleDateFormat(pattern); - } catch (final IllegalArgumentException e) { - LOGGER.warn("Could not instantiate SimpleDateFormat with pattern " + patternOption, e); + try { + tempFormat = new SimpleDateFormat(pattern); + } catch (final IllegalArgumentException e) { + LOGGER.warn("Could not instantiate SimpleDateFormat with pattern " + patternOption, e); - // default to the ISO8601 format - tempFormat = new SimpleDateFormat(ISO8601_PATTERN); - } + // default to the ISO8601 format + tempFormat = new SimpleDateFormat(ISO8601_PATTERN); + } - // if the option list contains a TZ option, then set it. - if (options != null && options.length > 1) { - final TimeZone tz = TimeZone.getTimeZone(options[1]); - tempFormat.setTimeZone(tz); + // if the option list contains a TZ option, then set it. + if (options != null && options.length > 1) { + final TimeZone tz = TimeZone.getTimeZone(options[1]); + tempFormat.setTimeZone(tz); + } + tempFormatter = new PatternFormatter(tempFormat); } - simpleFormat = tempFormat; + formatter = tempFormatter; } /** * Append formatted date to string buffer. - * - * @param date date - * @param toAppendTo buffer to which formatted date is appended. + * + * @param date + * date + * @param toAppendTo + * buffer to which formatted date is appended. */ public void format(final Date date, final StringBuilder toAppendTo) { synchronized (this) { - toAppendTo.append(simpleFormat.format(date.getTime())); + toAppendTo.append(formatter.format(date.getTime())); } } @@ -174,7 +233,7 @@ public final class DatePatternConverter synchronized (this) { if (timestamp != lastTimestamp) { lastTimestamp = timestamp; - cachedDateString = simpleFormat.format(timestamp); + cachedDateString = formatter.format(timestamp); } } output.append(cachedDateString); @@ -201,8 +260,13 @@ public final class DatePatternConverter } } + /** + * Gets the pattern string describing this date format. + * + * @return the pattern string describing this date format. + */ public String getPattern() { - return simpleFormat.toPattern(); + return formatter.toPattern(); } } Modified: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java?rev=1528503&r1=1528502&r2=1528503&view=diff ============================================================================== --- logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java (original) +++ logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java Wed Oct 2 14:48:54 2013 @@ -17,17 +17,20 @@ package org.apache.logging.log4j.core.layout; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.core.BasicConfigurationFactory; +import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.appender.FileAppender; import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; import org.apache.logging.log4j.core.util.Compare; -import org.junit.AfterClass; +import org.apache.logging.log4j.message.SimpleMessage; import org.junit.BeforeClass; import org.junit.Test; @@ -37,13 +40,14 @@ import org.junit.Test; public class PatternLayoutTest { static ConfigurationFactory cf = new BasicConfigurationFactory(); static String msgPattern = "%m%n"; - static String OUTPUT_FILE = "target/output/PatternParser"; + static String OUTPUT_FILE = "target/output/PatternParser"; static final String regexPattern = "%replace{%logger %msg}{\\.}{/}"; - static String WITNESS_FILE = "witness/PatternParser"; + static String WITNESS_FILE = "witness/PatternParser"; public static void cleanupClass() { ConfigurationFactory.removeConfigurationFactory(cf); } + @BeforeClass public static void setupClass() { ConfigurationFactory.setConfigurationFactory(cf); @@ -54,6 +58,7 @@ public class PatternLayoutTest { LoggerContext ctx = (LoggerContext) LogManager.getContext(); Logger root = ctx.getLogger(""); + /** * Test case for MDC conversion pattern. */ @@ -68,9 +73,9 @@ public class PatternLayoutTest { // set up appender final PatternLayout layout = PatternLayout.createLayout(msgPattern, ctx.getConfiguration(), null, null, null); - //FileOutputStream fos = new FileOutputStream(OUTPUT_FILE + "_mdc"); - final FileAppender appender = FileAppender.createAppender(OUTPUT_FILE + "_mdc", "false", "false", "File", "false", - "true", "false", null, layout, null, "false", null, null); + // FileOutputStream fos = new FileOutputStream(OUTPUT_FILE + "_mdc"); + final FileAppender appender = FileAppender.createAppender(OUTPUT_FILE + "_mdc", "false", "false", "File", + "false", "true", "false", null, layout, null, "false", null, null); appender.start(); // set appender on root and set level to debug @@ -126,4 +131,64 @@ public class PatternLayoutTest { appender.stop(); } + @Test + public void testRegex() throws Exception { + final LoggerContext ctx = (LoggerContext) LogManager.getContext(); + final PatternLayout layout = PatternLayout.createLayout(regexPattern, ctx.getConfiguration(), null, null, null); + final LogEvent event = new Log4jLogEvent(this.getClass().getName(), null, + "org.apache.logging.log4j.core.Logger", Level.INFO, new SimpleMessage("Hello, world!"), null); + final byte[] result = layout.toByteArray(event); + assertEquals("org/apache/logging/log4j/core/layout/PatternLayoutTest Hello, world!", new String(result)); + } + + private void testUnixTime(String pattern) throws Exception { + final LoggerContext ctx = (LoggerContext) LogManager.getContext(); + final PatternLayout layout = PatternLayout.createLayout(pattern + " %m", ctx.getConfiguration(), null, null, + null); + final LogEvent event1 = new Log4jLogEvent(this.getClass().getName(), null, + "org.apache.logging.log4j.core.Logger", Level.INFO, new SimpleMessage("Hello, world 1!"), null); + final byte[] result1 = layout.toByteArray(event1); + assertEquals(event1.getMillis() + " Hello, world 1!", new String(result1)); + // System.out.println("event1=" + event1.getMillis()); + final LogEvent event2 = new Log4jLogEvent(this.getClass().getName(), null, + "org.apache.logging.log4j.core.Logger", Level.INFO, new SimpleMessage("Hello, world 2!"), null); + final byte[] result2 = layout.toByteArray(event2); + assertEquals(event2.getMillis() + " Hello, world 2!", new String(result2)); + // System.out.println("event2=" + event2.getMillis()); + } + + @Test + public void testUnixTime() throws Exception { + final LoggerContext ctx = (LoggerContext) LogManager.getContext(); + final PatternLayout layout = PatternLayout + .createLayout("%d{UNIX} %m", ctx.getConfiguration(), null, null, null); + final LogEvent event1 = new Log4jLogEvent(this.getClass().getName(), null, + "org.apache.logging.log4j.core.Logger", Level.INFO, new SimpleMessage("Hello, world 1!"), null); + final byte[] result1 = layout.toByteArray(event1); + assertEquals(event1.getMillis() / 1000 + " Hello, world 1!", new String(result1)); + System.out.println("event1=" + event1.getMillis() / 1000); + final LogEvent event2 = new Log4jLogEvent(this.getClass().getName(), null, + "org.apache.logging.log4j.core.Logger", Level.INFO, new SimpleMessage("Hello, world 2!"), null); + final byte[] result2 = layout.toByteArray(event2); + assertEquals(event2.getMillis() / 1000 + " Hello, world 2!", new String(result2)); + System.out.println("event2=" + event2.getMillis() / 1000); + } + + @Test + public void testUnixTimeMillis() throws Exception { + final LoggerContext ctx = (LoggerContext) LogManager.getContext(); + final PatternLayout layout = PatternLayout.createLayout("%d{UNIX_MILLIS} %m", ctx.getConfiguration(), null, + null, null); + final LogEvent event1 = new Log4jLogEvent(this.getClass().getName(), null, + "org.apache.logging.log4j.core.Logger", Level.INFO, new SimpleMessage("Hello, world 1!"), null); + final byte[] result1 = layout.toByteArray(event1); + assertEquals(event1.getMillis() + " Hello, world 1!", new String(result1)); + System.out.println("event1=" + event1.getMillis()); + final LogEvent event2 = new Log4jLogEvent(this.getClass().getName(), null, + "org.apache.logging.log4j.core.Logger", Level.INFO, new SimpleMessage("Hello, world 2!"), null); + final byte[] result2 = layout.toByteArray(event2); + assertEquals(event2.getMillis() + " Hello, world 2!", new String(result2)); + System.out.println("event2=" + event2.getMillis()); + } + } Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1528503&r1=1528502&r2=1528503&view=diff ============================================================================== --- logging/log4j/log4j2/trunk/src/changes/changes.xml (original) +++ logging/log4j/log4j2/trunk/src/changes/changes.xml Wed Oct 2 14:48:54 2013 @@ -21,6 +21,9 @@ + + Format log event time as UNIX time (seconds or milliseconds). + @EnterpriseNumber" was missing in the ID of structured data when RFC5424Layout is used Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm?rev=1528503&r1=1528502&r2=1528503&view=diff ============================================================================== --- logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm (original) +++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm Wed Oct 2 14:48:54 2013 @@ -359,8 +359,25 @@ WARN [main]: Message 2 %d{HH:mm:ss}{GMT+0} 18:34:02,781 + + %d{UNIX} + 1351866842 + + + %d{UNIX_MILLIS} + 1351866842781 +

+

+ %d{UNIX} outputs the UNIX time in seconds. %d{UNIX_MILLIS} outputs the UNIX time in milliseconds. + The UNIX time is the difference, in seconds for UNIX and in milliseconds for UNIX_MILLIS, between + the current time and midnight, January 1, 1970 UTC. While the time unit is milliseconds, the + granularity depends on the operating system + (Windows). + This is an efficient way to output the event time because only a conversion from long to String + takes place, there is no Date formatting involved. +