Skip to content

Commit b65040a

Browse files
duncanjDuncan
andauthored
Add EpochConverter for milliseconds/seconds since epoch (related to issue #968) (#1000)
* Add EpochConverter and pattern "ep", "epoch" (related to issue #968) Pattern "ep" or "epoch" supports milliseconds by default and also epoch{seconds} for people who need UNIX-style epoch timestamps in their logs. Signed-off-by: Duncan Jauncey <[email protected]> * Add copyright notice to EpochConverter and EpochConverterTest Signed-off-by: Duncan Jauncey <[email protected]> --------- Signed-off-by: Duncan Jauncey <[email protected]> Co-authored-by: Duncan <[email protected]>
1 parent 0690174 commit b65040a

File tree

4 files changed

+116
-0
lines changed

4 files changed

+116
-0
lines changed

logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ public class PatternLayout extends PatternLayoutBase<ILoggingEvent> {
7070
DEFAULT_CONVERTER_SUPPLIER_MAP.put("micros", MicrosecondConverter::new);
7171
CONVERTER_CLASS_TO_KEY_MAP.put(MicrosecondConverter.class.getName(), "micros");
7272

73+
DEFAULT_CONVERTER_SUPPLIER_MAP.put("ep", EpochConverter::new);
74+
DEFAULT_CONVERTER_SUPPLIER_MAP.put("epoch", EpochConverter::new);
75+
CONVERTER_CLASS_TO_KEY_MAP.put(EpochConverter.class.getName(), "epoch");
76+
7377
DEFAULT_CONVERTER_SUPPLIER_MAP.put("r", RelativeTimeConverter::new);
7478
DEFAULT_CONVERTER_SUPPLIER_MAP.put("relative", RelativeTimeConverter::new);
7579
CONVERTER_CLASS_TO_KEY_MAP.put(RelativeTimeConverter.class.getName(), "relative");
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Logback: the reliable, generic, fast and flexible logging framework.
3+
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4+
*
5+
* This program and the accompanying materials are dual-licensed under
6+
* either the terms of the Eclipse Public License v1.0 as published by
7+
* the Eclipse Foundation
8+
*
9+
* or (per the licensee's choosing)
10+
*
11+
* under the terms of the GNU Lesser General Public License version 2.1
12+
* as published by the Free Software Foundation.
13+
*/
14+
package ch.qos.logback.classic.pattern;
15+
16+
import ch.qos.logback.classic.spi.ILoggingEvent;
17+
18+
public class EpochConverter extends ClassicConverter {
19+
@Override
20+
public String convert(ILoggingEvent event) {
21+
String millisOrSeconds = getFirstOption();
22+
if ("seconds".equals(millisOrSeconds) ) {
23+
return "" + (event.getTimeStamp() / 1000L);
24+
}
25+
26+
return "" + event.getTimeStamp();
27+
}
28+
}

logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,28 @@ void verifyMicros(int nanos, String expected) {
214214
assertEquals(expected, val);
215215
}
216216

217+
@Test
218+
public void epoch() {
219+
verifyEpoch(123, false, "2026-01-15 10:15:30.123 1768472130123 Some message");
220+
verifyEpoch(456, false, "2026-01-15 10:15:30.456 1768472130456 Some message");
221+
verifyEpoch(123, true, "2026-01-15 10:15:30.123 1768472130 Some message");
222+
verifyEpoch(456, true, "2026-01-15 10:15:30.456 1768472130 Some message");
223+
}
224+
225+
void verifyEpoch(int millis, boolean secondsNotMillis, String expected) {
226+
Instant instant = Instant.parse("2026-01-15T10:15:30Z");
227+
instant = instant.plusMillis(millis);
228+
LoggingEvent le = makeLoggingEvent(aMessage, null);
229+
le.setInstant(instant);
230+
231+
String option = secondsNotMillis ? "{seconds}" : "";
232+
pl.setPattern("%date{yyyy-MM-dd HH:mm:ss.SSS, UTC} %epoch"+option+" %message%nopex");
233+
pl.start();
234+
235+
String val = pl.doLayout(le);
236+
assertEquals(expected, val);
237+
}
238+
217239
@Override
218240
public Context getContext() {
219241
return loggerContext;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Logback: the reliable, generic, fast and flexible logging framework.
3+
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4+
*
5+
* This program and the accompanying materials are dual-licensed under
6+
* either the terms of the Eclipse Public License v1.0 as published by
7+
* the Eclipse Foundation
8+
*
9+
* or (per the licensee's choosing)
10+
*
11+
* under the terms of the GNU Lesser General Public License version 2.1
12+
* as published by the Free Software Foundation.
13+
*/
14+
package ch.qos.logback.classic.pattern;
15+
16+
import ch.qos.logback.classic.spi.LoggingEvent;
17+
import org.junit.jupiter.api.Test;
18+
19+
import java.time.Instant;
20+
import java.util.Collections;
21+
22+
import static org.junit.jupiter.api.Assertions.assertEquals;
23+
24+
public class EpochConverterTest {
25+
EpochConverter ec = new EpochConverter();
26+
27+
@Test
28+
public void withDefaultConfiguration() {
29+
ec.setOptionList(null);
30+
LoggingEvent le = new LoggingEvent();
31+
Instant instant = Instant.parse("2026-01-15T10:15:30Z");
32+
instant = instant.plusMillis(321);
33+
le.setInstant(instant);
34+
35+
String result = ec.convert(le);
36+
assertEquals("1768472130321", result); // includes millis
37+
}
38+
39+
@Test
40+
public void withSecondsConfiguration() {
41+
ec.setOptionList(Collections.singletonList("seconds"));
42+
LoggingEvent le = new LoggingEvent();
43+
Instant instant = Instant.parse("2026-01-15T10:15:30Z");
44+
instant = instant.plusMillis(321); // millis should be ignored
45+
le.setInstant(instant);
46+
47+
String result = ec.convert(le);
48+
assertEquals("1768472130", result);
49+
}
50+
51+
@Test
52+
public void withUnknownNonsenseConfiguration() {
53+
ec.setOptionList(Collections.singletonList("nonsense"));
54+
LoggingEvent le = new LoggingEvent();
55+
Instant instant = Instant.parse("2026-01-15T10:15:30Z");
56+
instant = instant.plusMillis(321);
57+
le.setInstant(instant);
58+
59+
String result = ec.convert(le);
60+
assertEquals("1768472130321", result); // includes millis, default behaviour
61+
}
62+
}

0 commit comments

Comments
 (0)