org.apache.logging.log4j.LogManager Maven / Gradle / Ivy
/*
* 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.logging.log4j;
import java.net.URI;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.logging.log4j.message.MessageFactory;
import org.apache.logging.log4j.message.StringFormatterMessageFactory;
import org.apache.logging.log4j.simple.SimpleLoggerContextFactory;
import org.apache.logging.log4j.spi.LoggerContext;
import org.apache.logging.log4j.spi.LoggerContextFactory;
import org.apache.logging.log4j.spi.Provider;
import org.apache.logging.log4j.spi.Terminable;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.LoaderUtil;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.ProviderUtil;
import org.apache.logging.log4j.util.StackLocatorUtil;
import org.apache.logging.log4j.util.Strings;
/**
* The anchor point for the Log4j logging system. The most common usage of this class is to obtain a named
* {@link Logger}. The method {@link #getLogger()} is provided as the most convenient way to obtain a named Logger based
* on the calling class name. This class also provides method for obtaining named Loggers that use
* {@link String#format(String, Object...)} style messages instead of the default type of parameterized messages. These
* are obtained through the {@link #getFormatterLogger(Class)} family of methods. Other service provider methods are
* given through the {@link #getContext()} and {@link #getFactory()} family of methods; these methods are not normally
* useful for typical usage of Log4j.
*/
public class LogManager {
/**
* Log4j property to set to the fully qualified class name of a custom implementation of
* {@link org.apache.logging.log4j.spi.LoggerContextFactory}.
*/
public static final String FACTORY_PROPERTY_NAME = "log4j2.loggerContextFactory";
/**
* The name of the root Logger.
*/
public static final String ROOT_LOGGER_NAME = Strings.EMPTY;
private static final Logger LOGGER = StatusLogger.getLogger();
// for convenience
private static final String FQCN = LogManager.class.getName();
private static volatile LoggerContextFactory factory;
/**
* Scans the classpath to find all logging implementation. Currently, only one will be used but this could be
* extended to allow multiple implementations to be used.
*/
static {
// Shortcut binding to force a specific logging implementation.
final PropertiesUtil managerProps = PropertiesUtil.getProperties();
final String factoryClassName = managerProps.getStringProperty(FACTORY_PROPERTY_NAME);
if (factoryClassName != null) {
try {
factory = LoaderUtil.newCheckedInstanceOf(factoryClassName, LoggerContextFactory.class);
} catch (final ClassNotFoundException cnfe) {
LOGGER.error("Unable to locate configured LoggerContextFactory {}", factoryClassName);
} catch (final Exception ex) {
LOGGER.error("Unable to create configured LoggerContextFactory {}", factoryClassName, ex);
}
}
if (factory == null) {
final SortedMap factories = new TreeMap<>();
// note that the following initial call to ProviderUtil may block until a Provider has been installed when
// running in an OSGi environment
if (ProviderUtil.hasProviders()) {
for (final Provider provider : ProviderUtil.getProviders()) {
final Class extends LoggerContextFactory> factoryClass = provider.loadLoggerContextFactory();
if (factoryClass != null) {
try {
factories.put(provider.getPriority(), factoryClass.newInstance());
} catch (final Exception e) {
LOGGER.error("Unable to create class {} specified in provider URL {}", factoryClass.getName(), provider
.getUrl(), e);
}
}
}
if (factories.isEmpty()) {
LOGGER.error("Log4j2 could not find a logging implementation. "
+ "Please add log4j-core to the classpath. Using SimpleLogger to log to the console...");
factory = new SimpleLoggerContextFactory();
} else if (factories.size() == 1) {
factory = factories.get(factories.lastKey());
} else {
final StringBuilder sb = new StringBuilder("Multiple logging implementations found: \n");
for (final Map.Entry entry : factories.entrySet()) {
sb.append("Factory: ").append(entry.getValue().getClass().getName());
sb.append(", Weighting: ").append(entry.getKey()).append('\n');
}
factory = factories.get(factories.lastKey());
sb.append("Using factory: ").append(factory.getClass().getName());
LOGGER.warn(sb.toString());
}
} else {
LOGGER.error("Log4j2 could not find a logging implementation. "
+ "Please add log4j-core to the classpath. Using SimpleLogger to log to the console...");
factory = new SimpleLoggerContextFactory();
}
}
}
/**
* Prevents instantiation
*/
protected LogManager() {
}
/**
* Detects if a Logger with the specified name exists. This is a convenience method for porting from version 1.
*
* @param name The Logger name to search for.
* @return true if the Logger exists, false otherwise.
* @see LoggerContext#hasLogger(String)
*/
public static boolean exists(final String name) {
return getContext().hasLogger(name);
}
/**
* Returns the current LoggerContext.
*
* WARNING - The LoggerContext returned by this method may not be the LoggerContext used to create a Logger for the
* calling class.
*
*
* @return The current LoggerContext.
*/
public static LoggerContext getContext() {
try {
return factory.getContext(FQCN, null, null, true);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(FQCN, null, null, true);
}
}
/**
* Returns a LoggerContext.
*
* @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* returned and if the caller is a class in the container's classpath then a different LoggerContext may
* be returned. If true then only a single LoggerContext will be returned.
* @return a LoggerContext.
*/
public static LoggerContext getContext(final boolean currentContext) {
// TODO: would it be a terrible idea to try and find the caller ClassLoader here?
try {
return factory.getContext(FQCN, null, null, currentContext, null, null);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(FQCN, null, null, currentContext, null, null);
}
}
/**
* Returns a LoggerContext.
*
* @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate
* ClassLoader.
* @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* returned and if the caller is a class in the container's classpath then a different LoggerContext may
* be returned. If true then only a single LoggerContext will be returned.
* @return a LoggerContext.
*/
public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext) {
try {
return factory.getContext(FQCN, loader, null, currentContext);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(FQCN, loader, null, currentContext);
}
}
/**
* Returns a LoggerContext.
*
* @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate
* ClassLoader.
* @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* returned and if the caller is a class in the container's classpath then a different LoggerContext may
* be returned. If true then only a single LoggerContext will be returned.
* @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext.
* @return a LoggerContext.
*/
public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext,
final Object externalContext) {
try {
return factory.getContext(FQCN, loader, externalContext, currentContext);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(FQCN, loader, externalContext, currentContext);
}
}
/**
* Returns a LoggerContext.
*
* @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate
* ClassLoader.
* @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* returned and if the caller is a class in the container's classpath then a different LoggerContext may
* be returned. If true then only a single LoggerContext will be returned.
* @param configLocation The URI for the configuration to use.
* @return a LoggerContext.
*/
public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext,
final URI configLocation) {
try {
return factory.getContext(FQCN, loader, null, currentContext, configLocation, null);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(FQCN, loader, null, currentContext, configLocation,
null);
}
}
/**
* Returns a LoggerContext.
*
* @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate
* ClassLoader.
* @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* returned and if the caller is a class in the container's classpath then a different LoggerContext may
* be returned. If true then only a single LoggerContext will be returned.
* @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext.
* @param configLocation The URI for the configuration to use.
* @return a LoggerContext.
*/
public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext,
final Object externalContext, final URI configLocation) {
try {
return factory.getContext(FQCN, loader, externalContext, currentContext, configLocation, null);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(FQCN, loader, externalContext, currentContext,
configLocation, null);
}
}
/**
* Returns a LoggerContext.
*
* @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate
* ClassLoader.
* @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* returned and if the caller is a class in the container's classpath then a different LoggerContext may
* be returned. If true then only a single LoggerContext will be returned.
* @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext.
* @param configLocation The URI for the configuration to use.
* @param name The LoggerContext name.
* @return a LoggerContext.
*/
public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext,
final Object externalContext, final URI configLocation, final String name) {
try {
return factory.getContext(FQCN, loader, externalContext, currentContext, configLocation, name);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(FQCN, loader, externalContext, currentContext,
configLocation, name);
}
}
/**
* Returns a LoggerContext
*
* @param fqcn The fully qualified class name of the Class that this method is a member of.
* @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* returned and if the caller is a class in the container's classpath then a different LoggerContext may
* be returned. If true then only a single LoggerContext will be returned.
* @return a LoggerContext.
*/
protected static LoggerContext getContext(final String fqcn, final boolean currentContext) {
try {
return factory.getContext(fqcn, null, null, currentContext);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(fqcn, null, null, currentContext);
}
}
/**
* Returns a LoggerContext
*
* @param fqcn The fully qualified class name of the Class that this method is a member of.
* @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate
* ClassLoader.
* @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* returned and if the caller is a class in the container's classpath then a different LoggerContext may
* be returned. If true then only a single LoggerContext will be returned.
* @return a LoggerContext.
*/
protected static LoggerContext getContext(final String fqcn, final ClassLoader loader,
final boolean currentContext) {
try {
return factory.getContext(fqcn, loader, null, currentContext);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(fqcn, loader, null, currentContext);
}
}
/**
* Returns a LoggerContext
*
* @param fqcn The fully qualified class name of the Class that this method is a member of.
* @param loader The ClassLoader for the context. If null the context will attempt to determine the appropriate
* ClassLoader.
* @param currentContext if false the LoggerContext appropriate for the caller of this method is returned. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* returned and if the caller is a class in the container's classpath then a different LoggerContext may
* be returned. If true then only a single LoggerContext will be returned.
* @param configLocation The URI for the configuration to use.
* @param name The LoggerContext name.
* @return a LoggerContext.
*/
protected static LoggerContext getContext(final String fqcn, final ClassLoader loader,
final boolean currentContext, final URI configLocation, final String name) {
try {
return factory.getContext(fqcn, loader, null, currentContext, configLocation, name);
} catch (final IllegalStateException ex) {
LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
return new SimpleLoggerContextFactory().getContext(fqcn, loader, null, currentContext);
}
}
/**
* Shutdown using the LoggerContext appropriate for the caller of this method.
* This is equivalent to calling {@code LogManager.shutdown(false)}.
*
* This call is synchronous and will block until shut down is complete.
* This may include flushing pending log events over network connections.
*
* @since 2.6
*/
public static void shutdown() {
shutdown(false);
}
/**
* Shutdown the logging system if the logging system supports it.
* This is equivalent to calling {@code LogManager.shutdown(LogManager.getContext(currentContext))}.
*
* This call is synchronous and will block until shut down is complete.
* This may include flushing pending log events over network connections.
*
* @param currentContext if true a default LoggerContext (may not be the LoggerContext used to create a Logger
* for the calling class) will be used.
* If false the LoggerContext appropriate for the caller of this method is used. For
* example, in a web application if the caller is a class in WEB-INF/lib then one LoggerContext may be
* used and if the caller is a class in the container's classpath then a different LoggerContext may
* be used.
* @since 2.6
*/
public static void shutdown(final boolean currentContext) {
shutdown(getContext(currentContext));
}
/**
* Shutdown the logging system if the logging system supports it.
*
* This call is synchronous and will block until shut down is complete.
* This may include flushing pending log events over network connections.
*
* @param context the LoggerContext.
* @since 2.6
*/
public static void shutdown(final LoggerContext context) {
if (context != null && context instanceof Terminable) {
((Terminable) context).terminate();
}
}
private static String toLoggerName(final Class> cls) {
final String canonicalName = cls.getCanonicalName();
return canonicalName != null ? canonicalName : cls.getName();
}
/**
* Returns the current LoggerContextFactory.
*
* @return The LoggerContextFactory.
*/
public static LoggerContextFactory getFactory() {
return factory;
}
/**
* Sets the current LoggerContextFactory to use. Normally, the appropriate LoggerContextFactory is created at
* startup, but in certain environments, a LoggerContextFactory implementation may not be available at this point.
* Thus, an alternative LoggerContextFactory can be set at runtime.
*
*
* Note that any Logger or LoggerContext objects already created will still be valid, but they will no longer be
* accessible through LogManager. Thus, it is a bad idea to use this method without a good reason!
* Generally, this method should be used only during startup before any code starts caching Logger objects.
*
*
* @param factory the LoggerContextFactory to use.
*/
// FIXME: should we allow only one update of the factory?
public static void setFactory(final LoggerContextFactory factory) {
LogManager.factory = factory;
}
/**
* Returns a formatter Logger using the fully qualified name of the calling Class as the Logger name.
*
* This logger lets you use a {@link java.util.Formatter} string in the message to format parameters.
*
*
* @return The Logger for the calling class.
* @throws UnsupportedOperationException if the calling class cannot be determined.
* @since 2.4
*/
public static Logger getFormatterLogger() {
return getFormatterLogger(StackLocatorUtil.getCallerClass(2));
}
/**
* Returns a formatter Logger using the fully qualified name of the Class as the Logger name.
*
* This logger let you use a {@link java.util.Formatter} string in the message to format parameters.
*
*
* Short-hand for {@code getLogger(clazz, StringFormatterMessageFactory.INSTANCE)}
*
*
* @param clazz The Class whose name should be used as the Logger name.
* @return The Logger, created with a {@link StringFormatterMessageFactory}
* @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be
* determined.
* @see Logger#fatal(Marker, String, Object...)
* @see Logger#fatal(String, Object...)
* @see Logger#error(Marker, String, Object...)
* @see Logger#error(String, Object...)
* @see Logger#warn(Marker, String, Object...)
* @see Logger#warn(String, Object...)
* @see Logger#info(Marker, String, Object...)
* @see Logger#info(String, Object...)
* @see Logger#debug(Marker, String, Object...)
* @see Logger#debug(String, Object...)
* @see Logger#trace(Marker, String, Object...)
* @see Logger#trace(String, Object...)
* @see StringFormatterMessageFactory
*/
public static Logger getFormatterLogger(final Class> clazz) {
return getLogger(clazz != null ? clazz : StackLocatorUtil.getCallerClass(2),
StringFormatterMessageFactory.INSTANCE);
}
/**
* Returns a formatter Logger using the fully qualified name of the value's Class as the Logger name.
*
* This logger let you use a {@link java.util.Formatter} string in the message to format parameters.
*
*
* Short-hand for {@code getLogger(value, StringFormatterMessageFactory.INSTANCE)}
*
*
* @param value The value's whose class name should be used as the Logger name.
* @return The Logger, created with a {@link StringFormatterMessageFactory}
* @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be
* determined.
* @see Logger#fatal(Marker, String, Object...)
* @see Logger#fatal(String, Object...)
* @see Logger#error(Marker, String, Object...)
* @see Logger#error(String, Object...)
* @see Logger#warn(Marker, String, Object...)
* @see Logger#warn(String, Object...)
* @see Logger#info(Marker, String, Object...)
* @see Logger#info(String, Object...)
* @see Logger#debug(Marker, String, Object...)
* @see Logger#debug(String, Object...)
* @see Logger#trace(Marker, String, Object...)
* @see Logger#trace(String, Object...)
* @see StringFormatterMessageFactory
*/
public static Logger getFormatterLogger(final Object value) {
return getLogger(value != null ? value.getClass() : StackLocatorUtil.getCallerClass(2),
StringFormatterMessageFactory.INSTANCE);
}
/**
* Returns a formatter Logger with the specified name.
*
* This logger let you use a {@link java.util.Formatter} string in the message to format parameters.
*
*
* Short-hand for {@code getLogger(name, StringFormatterMessageFactory.INSTANCE)}
*
*
* @param name The logger name. If null it will default to the name of the calling class.
* @return The Logger, created with a {@link StringFormatterMessageFactory}
* @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined.
* @see Logger#fatal(Marker, String, Object...)
* @see Logger#fatal(String, Object...)
* @see Logger#error(Marker, String, Object...)
* @see Logger#error(String, Object...)
* @see Logger#warn(Marker, String, Object...)
* @see Logger#warn(String, Object...)
* @see Logger#info(Marker, String, Object...)
* @see Logger#info(String, Object...)
* @see Logger#debug(Marker, String, Object...)
* @see Logger#debug(String, Object...)
* @see Logger#trace(Marker, String, Object...)
* @see Logger#trace(String, Object...)
* @see StringFormatterMessageFactory
*/
public static Logger getFormatterLogger(final String name) {
return name == null ? getFormatterLogger(StackLocatorUtil.getCallerClass(2)) : getLogger(name,
StringFormatterMessageFactory.INSTANCE);
}
private static Class> callerClass(final Class> clazz) {
if (clazz != null) {
return clazz;
}
final Class> candidate = StackLocatorUtil.getCallerClass(3);
if (candidate == null) {
throw new UnsupportedOperationException("No class provided, and an appropriate one cannot be found.");
}
return candidate;
}
/**
* Returns a Logger with the name of the calling class.
*
* @return The Logger for the calling class.
* @throws UnsupportedOperationException if the calling class cannot be determined.
*/
public static Logger getLogger() {
return getLogger(StackLocatorUtil.getCallerClass(2));
}
/**
* Returns a Logger using the fully qualified name of the Class as the Logger name.
*
* @param clazz The Class whose name should be used as the Logger name. If null it will default to the calling
* class.
* @return The Logger.
* @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be
* determined.
*/
public static Logger getLogger(final Class> clazz) {
final Class> cls = callerClass(clazz);
return getContext(cls.getClassLoader(), false).getLogger(toLoggerName(cls));
}
/**
* Returns a Logger using the fully qualified name of the Class as the Logger name.
*
* @param clazz The Class whose name should be used as the Logger name. If null it will default to the calling
* class.
* @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the
* logger but will log a warning if mismatched.
* @return The Logger.
* @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be
* determined.
*/
public static Logger getLogger(final Class> clazz, final MessageFactory messageFactory) {
final Class> cls = callerClass(clazz);
return getContext(cls.getClassLoader(), false).getLogger(toLoggerName(cls), messageFactory);
}
/**
* Returns a Logger with the name of the calling class.
*
* @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the
* logger but will log a warning if mismatched.
* @return The Logger for the calling class.
* @throws UnsupportedOperationException if the calling class cannot be determined.
*/
public static Logger getLogger(final MessageFactory messageFactory) {
return getLogger(StackLocatorUtil.getCallerClass(2), messageFactory);
}
/**
* Returns a Logger using the fully qualified class name of the value as the Logger name.
*
* @param value The value whose class name should be used as the Logger name. If null the name of the calling class
* will be used as the logger name.
* @return The Logger.
* @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be
* determined.
*/
public static Logger getLogger(final Object value) {
return getLogger(value != null ? value.getClass() : StackLocatorUtil.getCallerClass(2));
}
/**
* Returns a Logger using the fully qualified class name of the value as the Logger name.
*
* @param value The value whose class name should be used as the Logger name. If null the name of the calling class
* will be used as the logger name.
* @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the
* logger but will log a warning if mismatched.
* @return The Logger.
* @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be
* determined.
*/
public static Logger getLogger(final Object value, final MessageFactory messageFactory) {
return getLogger(value != null ? value.getClass() : StackLocatorUtil.getCallerClass(2), messageFactory);
}
/**
* Returns a Logger with the specified name.
*
* @param name The logger name. If null the name of the calling class will be used.
* @return The Logger.
* @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined.
*/
public static Logger getLogger(final String name) {
return name != null ? getContext(false).getLogger(name) : getLogger(StackLocatorUtil.getCallerClass(2));
}
/**
* Returns a Logger with the specified name.
*
* @param name The logger name. If null the name of the calling class will be used.
* @param messageFactory The message factory is used only when creating a logger, subsequent use does not change the
* logger but will log a warning if mismatched.
* @return The Logger.
* @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined.
*/
public static Logger getLogger(final String name, final MessageFactory messageFactory) {
return name != null ? getContext(false).getLogger(name, messageFactory) : getLogger(
StackLocatorUtil.getCallerClass(2), messageFactory);
}
/**
* Returns a Logger with the specified name.
*
* @param fqcn The fully qualified class name of the class that this method is a member of.
* @param name The logger name.
* @return The Logger.
*/
protected static Logger getLogger(final String fqcn, final String name) {
return factory.getContext(fqcn, null, null, false).getLogger(name);
}
/**
* Returns the root logger.
*
* @return the root logger, named {@link #ROOT_LOGGER_NAME}.
*/
public static Logger getRootLogger() {
return getLogger(ROOT_LOGGER_NAME);
}
}