/*
* Lilith - a log event viewer.
* Copyright (C) 2007-2017 Joern Huxhorn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright 2007-2017 Joern Huxhorn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.huxhorn.lilith.log4j2.producer;
import de.huxhorn.lilith.data.converter.Converter;
import de.huxhorn.lilith.data.eventsource.LoggerContext;
import de.huxhorn.lilith.data.logging.ExtendedStackTraceElement;
import de.huxhorn.lilith.data.logging.LoggingEvent;
import de.huxhorn.lilith.data.logging.Marker;
import de.huxhorn.lilith.data.logging.Message;
import de.huxhorn.lilith.data.logging.ThreadInfo;
import de.huxhorn.lilith.data.logging.ThrowableInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.util.ReadOnlyStringMap;
public class Log4j2LoggingConverter
implements Converter<LoggingEvent>
{
public static final String LOG4J_LEVEL_KEY = "log4j.level";
public static final String LOG4J_LEVEL_VALUE_FATAL = "FATAL";
private static final String APPLICATION_MDC_KEY = "application";
public LoggingEvent convert(Object o)
{
if (o == null)
{
return null;
}
if (!(o instanceof org.apache.logging.log4j.core.LogEvent))
{
throw new IllegalArgumentException("" + o + " is not a " + getSourceClass() + "!");
}
org.apache.logging.log4j.core.LogEvent log4jEvent = (org.apache.logging.log4j.core.LogEvent) o;
LoggingEvent result = new LoggingEvent();
Map<String, String> mdc = new HashMap<>();
// loggerName
result.setLogger(log4jEvent.getLoggerName());
// level
{
Level log4jLevel = log4jEvent.getLevel();
if (log4jLevel == Level.TRACE)
{
result.setLevel(LoggingEvent.Level.TRACE);
}
else if (log4jLevel == Level.DEBUG)
{
result.setLevel(LoggingEvent.Level.DEBUG);
}
else if (log4jLevel == Level.INFO)
{
result.setLevel(LoggingEvent.Level.INFO);
}
else if (log4jLevel == Level.WARN)
{
result.setLevel(LoggingEvent.Level.WARN);
}
else if (log4jLevel == Level.ERROR)
{
result.setLevel(LoggingEvent.Level.ERROR);
}
else if (log4jLevel == Level.FATAL)
{
mdc.put(LOG4J_LEVEL_KEY, LOG4J_LEVEL_VALUE_FATAL);
result.setLevel(LoggingEvent.Level.ERROR);
}
}
// timeStamp
result.setTimeStamp(log4jEvent.getTimeMillis());
// Message
{
org.apache.logging.log4j.message.Message msg = log4jEvent.getMessage();
if (msg != null)
{
result.setMessage(new Message(msg.getFormattedMessage()));
}
}
// threadInfo
{
String threadName = log4jEvent.getThreadName();
if (threadName != null)
{
ThreadInfo threadInfo = new ThreadInfo();
threadInfo.setName(threadName);
threadInfo.setId(log4jEvent.getThreadId());
threadInfo.setPriority(log4jEvent.getThreadPriority());
result.setThreadInfo(threadInfo);
}
}
// MDC
{
ReadOnlyStringMap contextData = log4jEvent.getContextData();
if (!contextData.isEmpty())
{
mdc.putAll(contextData.toMap());
}
}
if (!mdc.isEmpty())
{
result.setMdc(mdc);
// application / contextName
if (mdc.containsKey(APPLICATION_MDC_KEY))
{
LoggerContext context = new LoggerContext();
context.setName(mdc.get(APPLICATION_MDC_KEY));
result.setLoggerContext(context);
}
}
// NDC
{
org.apache.logging.log4j.ThreadContext.ContextStack ndc = log4jEvent.getContextStack();
if (ndc != null)
{
List<String> list = ndc.asList();
if (list != null && !list.isEmpty())
{
Message[] ndcResult = new Message[list.size()];
for (int i = 0; i < list.size(); i++)
{
String current = list.get(i);
if (current != null)
{
ndcResult[i] = new Message(current);
}
}
result.setNdc(ndcResult);
}
}
}
// location information
{
StackTraceElement location = log4jEvent.getSource();
if (location != null)
{
ExtendedStackTraceElement ste = new ExtendedStackTraceElement();
ste.setClassName(location.getClassName());
ste.setMethodName(location.getMethodName());
ste.setFileName(location.getFileName());
ste.setLineNumber(location.getLineNumber());
result.setCallStack(new ExtendedStackTraceElement[]{ste});
}
}
// throwable information
{
result.setThrowable(convert(log4jEvent.getThrownProxy()));
}
initMarker(log4jEvent, result);
return result;
}
private void initMarker(org.apache.logging.log4j.core.LogEvent src, LoggingEvent dst)
{
org.apache.logging.log4j.Marker origMarker = src.getMarker();
if(origMarker == null)
{
return;
}
Map<String, Marker> markers = new HashMap<>();
dst.setMarker(initMarkerRecursive(origMarker, markers));
}
private Marker initMarkerRecursive(org.apache.logging.log4j.Marker origMarker, Map<String, Marker> markers)
{
if(origMarker == null)
{
return null;
}
String name = origMarker.getName();
if(markers.containsKey(name))
{
return markers.get(name);
}
Marker newMarker = new Marker(name);
markers.put(name, newMarker);
org.apache.logging.log4j.Marker[] parents = origMarker.getParents();
if(parents != null)
{
for (org.apache.logging.log4j.Marker current : parents)
{
newMarker.add(initMarkerRecursive(current, markers));
}
}
return newMarker;
}
private ThrowableInfo convert(org.apache.logging.log4j.core.impl.ThrowableProxy thrown)
{
if (thrown == null)
{
return null;
}
ThrowableInfo result = new ThrowableInfo();
result.setCause(convert(thrown.getCauseProxy()));
result.setMessage(thrown.getMessage());
result.setName(thrown.getName());
result.setStackTrace(convert(thrown.getExtendedStackTrace()));
result.setOmittedElements(thrown.getCommonElementCount());
result.setSuppressed(convert(thrown.getSuppressedProxies()));
return result;
}
private ThrowableInfo[] convert(org.apache.logging.log4j.core.impl.ThrowableProxy[] array)
{
if (array == null)
{
return null;
}
ThrowableInfo[] result = new ThrowableInfo[array.length];
for (int i=0; i<result.length; i++)
{
result[i]=convert(array[i]);
}
return result;
}
private ExtendedStackTraceElement[] convert(org.apache.logging.log4j.core.impl.ExtendedStackTraceElement[] array)
{
if(array == null)
{
return null;
}
ExtendedStackTraceElement[] result = new ExtendedStackTraceElement[array.length];
for(int i=0; i<result.length; i++)
{
result[i] = convert(array[i]);
}
return result;
}
private ExtendedStackTraceElement convert(org.apache.logging.log4j.core.impl.ExtendedStackTraceElement ste)
{
if (ste == null)
{
return null;
}
ExtendedStackTraceElement result = new ExtendedStackTraceElement(ste.getStackTraceElement());
result.setExact(ste.getExact());
result.setVersion(ste.getVersion());
result.setCodeLocation(ste.getLocation());
return result;
}
public Class getSourceClass()
{
return org.apache.logging.log4j.core.LogEvent.class;
}
}