blob: 9ad4d275c4381fdd21de721ebea82521c9c3561a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.log4j.bridge;
import java.lang.reflect.Method;
import org.apache.log4j.Category;
import org.apache.log4j.Level;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.util.Loader;
import org.apache.logging.log4j.core.util.Throwables;
import org.apache.logging.log4j.spi.StandardLevel;
import org.apache.logging.log4j.status.StatusLogger;
/**
* Converts a Log4j 2 LogEvent into the components needed by a Log4j 1.x LoggingEvent.
* This class requires Log4j 2.
*/
public class LogEventAdapter extends LoggingEvent {
private static final long JVM_START_TIME = initStartTime();
private final LogEvent event;
public LogEventAdapter(LogEvent event) {
this.event = event;
}
public LogEvent getEvent() {
return this.event;
}
/**
Set the location information for this logging event. The collected
information is cached for future use.
*/
@Override
public LocationInfo getLocationInformation() {
return new LocationInfo(event.getSource());
}
/**
* Return the level of this event. Use this form instead of directly
* accessing the <code>level</code> field. */
@Override
public Level getLevel() {
switch (StandardLevel.getStandardLevel(event.getLevel().intLevel())) {
case TRACE:
return Level.TRACE;
case DEBUG:
return Level.DEBUG;
case INFO:
return Level.INFO;
case WARN:
return Level.WARN;
case ERROR:
return Level.ERROR;
case FATAL:
return Level.FATAL;
case OFF:
return Level.OFF;
case ALL:
return Level.ALL;
default:
return Level.ERROR;
}
}
/**
* Return the name of the logger. Use this form instead of directly
* accessing the <code>categoryName</code> field.
*/
@Override
public String getLoggerName() {
return event.getLoggerName();
}
/**
* Gets the logger of the event.
*/
@Override
public Category getLogger() {
return Category.getInstance(event.getLoggerName());
}
/*
Return the message for this logging event.
*/
@Override
public
Object getMessage() {
return event.getMessage().getFormattedMessage();
}
/*
* This method returns the NDC for this event.
*/
@Override
public
String getNDC() {
return event.getContextStack().toString();
}
/*
Returns the the context corresponding to the <code>key</code> parameter.
*/
@Override
public
Object getMDC(String key) {
if (event.getContextData() != null) {
return event.getContextData().getValue(key);
} else {
return null;
}
}
/**
Obtain a copy of this thread's MDC prior to serialization or
asynchronous logging.
*/
@Override
public
void getMDCCopy() {
}
@Override
public
String getRenderedMessage() {
return event.getMessage().getFormattedMessage();
}
/**
Returns the time when the application started, in milliseconds
elapsed since 01.01.1970. */
public static long getStartTime() {
return JVM_START_TIME;
}
@Override
public
String getThreadName() {
return event.getThreadName();
}
/**
Returns the throwable information contained within this
event. May be <code>null</code> if there is no such information.
<p>Note that the {@link Throwable} object contained within a
{@link ThrowableInformation} does not survive serialization.
@since 1.1 */
@Override
public
ThrowableInformation getThrowableInformation() {
if (event.getThrown() != null) {
return new ThrowableInformation(event.getThrown());
}
return null;
}
/**
Return this event's throwable's string[] representaion.
*/
@Override
public
String[] getThrowableStrRep() {
if (event.getThrown() != null) {
return Throwables.toStringList(event.getThrown()).toArray(new String[0]);
}
return null;
}
/**
* Returns the result of {@code ManagementFactory.getRuntimeMXBean().getStartTime()},
* or the current system time if JMX is not available.
*/
private static long initStartTime() {
// We'd like to call ManagementFactory.getRuntimeMXBean().getStartTime(),
// but Google App Engine throws a java.lang.NoClassDefFoundError
// "java.lang.management.ManagementFactory is a restricted class".
// The reflection is necessary because without it, Google App Engine
// will refuse to initialize this class.
try {
final Class<?> factoryClass = Loader.loadSystemClass("java.lang.management.ManagementFactory");
final Method getRuntimeMXBean = factoryClass.getMethod("getRuntimeMXBean");
final Object runtimeMXBean = getRuntimeMXBean.invoke(null);
final Class<?> runtimeMXBeanClass = Loader.loadSystemClass("java.lang.management.RuntimeMXBean");
final Method getStartTime = runtimeMXBeanClass.getMethod("getStartTime");
return (Long) getStartTime.invoke(runtimeMXBean);
} catch (final Throwable t) {
StatusLogger.getLogger().error("Unable to call ManagementFactory.getRuntimeMXBean().getStartTime(), "
+ "using system time for OnStartupTriggeringPolicy", t);
// We have little option but to declare "now" as the beginning of time.
return System.currentTimeMillis();
}
}
}