You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2013/10/02 16:48:55 UTC
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/
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 @@
</properties>
<body>
<release version="2.0RC1" date="2013-MM-DD" description="Bug fixes and enhancements">
+ <action issue="LOG4J2-415" dev="ggregory" type="add">
+ Format log event time as UNIX time (seconds or milliseconds).
+ </action>
<action issue="LOG4J2-404" dev="rgoers" type="fix" due-to="Kamal Bahadur">
@EnterpriseNumber" was missing in the ID of structured data when RFC5424Layout is used
</action>
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</pre>
<td>%d{HH:mm:ss}{GMT+0}</td>
<td>18:34:02,781</td>
</tr>
+ <tr>
+ <td>%d{UNIX}</td>
+ <td>1351866842</td>
+ </tr>
+ <tr>
+ <td>%d{UNIX_MILLIS}</td>
+ <td>1351866842781</td>
+ </tr>
</table>
</p>
+ <p>
+ %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
+ (<a href="http://msdn.microsoft.com/en-us/windows/hardware/gg463266.aspx">Windows</a>).
+ 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.
+ </p>
</td>
</tr>
<tr>