Apparently, JSONLayout in log4j2 doesn't have timestamp pattern support. Normally it only has JSON formatting options, but nothing as such pattern
option.
{
"configuration": {
"name": "logggg",
"packages" : "logger.savemyjob",
"appenders": {
"RollingFile": {
"name": "rollingStone",
"fileName": "async_rolled.log",
"filePattern": "async_rolled-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz",
"immediateFlush" : false,
"JSONLayout": {
"complete": true,
"compact": false,
"eventEol": true
},
"SizeBasedTriggeringPolicy": {
"size": "10 MB"
},
"DefaultRolloverStrategy": {
"max": "10"
}
}
},
"loggers": {
"root": {
"level": "debug",
"appender-ref": {
"ref": "rollingStone"
}
}
}
}
}
Log Example,
{
"timeMillis" : 1482231551081,
"thread" : "main",
"level" : "debug",
"endOfBatch" : false,
"threadId" : 1,
"threadPriority" : 5,
"message" : "log4j might suck"
}
And when I looked at their API, looks too verbose and don't see quite an easier way adding a timestamp field.
JsonLayout
plugin seems to be the one I need to override, since its final
can't even extend but otherwise I have to copy the whole dependent classes.
@Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class JsonLayout extends AbstractJacksonLayout {
protected JsonLayout(final Configuration config, final boolean locationInfo, final boolean properties,
final boolean encodeThreadContextAsList,
final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern,
final String footerPattern, final Charset charset) {
super(config, new JacksonFactory.JSON(encodeThreadContextAsList).newWriter(locationInfo, properties, compact),
charset, compact, complete, eventEol,
PatternLayout.createSerializer(config, null, headerPattern, DEFAULT_HEADER, null, false, false),
PatternLayout.createSerializer(config, null, footerPattern, DEFAULT_FOOTER, null, false, false));
}
}
The architecture looks more complicated than I expected :(, I am tracing from the Logger
.
I also considered changing the LogEvent
itself,
public interface LogEvent extends Serializable {
@Deprecated
Map<String, String> getContextMap();
ReadOnlyStringMap getContextData();
ThreadContext.ContextStack getContextStack();
String getLoggerFqcn();
Level getLevel();
String getLoggerName();
Marker getMarker();
Message getMessage();
long getTimeMillis();
StackTraceElement getSource();
String getThreadName();
long getThreadId();
int getThreadPriority();
Throwable getThrown();
ThrowableProxy getThrownProxy();
boolean isEndOfBatch();
boolean isIncludeLocation();
void setEndOfBatch(boolean endOfBatch);
void setIncludeLocation(boolean locationRequired);
long getNanoTime();
String getTimestamp();
}
and also MutableLogEvent
public class MutableLogEvent implements LogEvent, ReusableMessage {
public void initFrom(final LogEvent event) {
SimpleDateFormat standardDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
this.timestamp = standardDateFormat.format(new Date(event.getTimeMillis()));
}
}
I'm guessing it might work, though it broke few core log4j-core tests. I basically want to know the tricks to add extra json field with minimum change.
I see few other impls like JSONEventLayoutV1, which seems to be totally different impl than log4j json api which is pretty good performance wise.
Here's my failed attempt to override, LogEvent
, https://github.com/prayagupd/sell-peace/blob/custom_timestamp/supply-peace/src/main/java/org/apache/logging/log4j/core/DnLogEvent.java
The questions is getting longer, I basically want to know the important things not to miss when I override the log4j2 api.