// ================================================================================================= // Copyright 2013 Twitter, Inc. // ------------------------------------------------------------------------------------------------- // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this work except in compliance with the License. // You may obtain a copy of the License in the LICENSE file, or 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 com.twitter.common.logging.julbridge; import java.util.logging.LogManager; import java.util.logging.Logger; import org.apache.log4j.spi.LoggerRepository; /** * A JUL LogManager which takes over the logging configuration and redirects all messages to Log4j. * * The approach is inspired by the apache-jul-log4j-bridge project from Paul Smith * (<psmith@apache.org>) and available at <a * href="http://people.apache.org/~psmith/logging.apache.org/sandbox/jul-log4j-bridge/" /> * * During initialization, it resets configuration and adds a default handler to the root logger to * perform the redirection. It also sets the root logger level to the Log4j repository threshold. * This implies that Log4j is properly configured before this manager is taking over. * * To install this log manager, simply add the following property to the java command line: * <code>-Djava.util.logging.manager=com.twitter.common.logging.julbridge.JULBridgeLogManager</code> * * It is possible to configure using extended location information (source filename and line info) * by adding the following property to the java command line: * <code>-Dcom.twitter.common.logging.julbridge.use-extended-location-info=true</code> * */ public final class JULBridgeLogManager extends LogManager { /** * System property name to control if log messages sent from JUL to log4j should contain * extended location information. * * Set @value to true to add source filename and line number to each message. */ public static final String USE_EXTENDED_LOCATION_INFO_PROPERTYNAME = "com.twitter.common.logging.julbridge.use-extended-location-info"; /* * LogManager requires a public no-arg constructor to be present so a new instance can be created * when configured using the system property. A private constructor will throw an exception. */ public JULBridgeLogManager() {} @Override public void readConfiguration() { assimilate(org.apache.log4j.LogManager.getLoggerRepository()); } /** * Assimilates an existing JUL log manager. Equivalent to calling * {@link #assimilate(LoggerRepository)} with <code>LogManager.getLoggerRepository</code>. */ public static void assimilate() { assimilate(org.apache.log4j.LogManager.getLoggerRepository()); } /** * Assimilates an existing JUL log manager. * * It resets the manager configuration, and adds a bridge handler to the root logger. Messages are * redirected to the specified Log4j logger repository. * * @param loggerRepository the Log4j logger repository to use to redirect messages */ public static void assimilate(LoggerRepository loggerRepository) { LogManager.getLogManager().reset(); boolean withExtendedLocationInfos = Boolean.getBoolean(USE_EXTENDED_LOCATION_INFO_PROPERTYNAME); Logger rootLogger = Logger.getLogger(""); rootLogger.setLevel(JULBridgeLevelConverter.fromLog4jLevel(loggerRepository.getThreshold())); rootLogger.addHandler(new JULBridgeHandler(loggerRepository, withExtendedLocationInfos)); } }