/*
* 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.solr.servlet;
import java.lang.invoke.MethodHandles;
import java.util.Enumeration;
import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.solr.common.util.SuppressForbidden;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.StaticLoggerBinder;
/**
* Handles dynamic modification of during startup, before CoreContainer is created
* <p>
* WARNING: This class should only be used during startup. For modifying log levels etc
* during runtime, SLF4J and LogWatcher must be used.
* </p>
*/
final class StartupLoggingUtils {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final static StaticLoggerBinder binder = StaticLoggerBinder.getSingleton();
/**
* Checks whether mandatory log dir is given
*/
static void checkLogDir() {
if (System.getProperty("solr.log.dir") == null) {
log.error("Missing Java Option solr.log.dir. Logging may be missing or incomplete.");
}
}
/**
* Disables all log4j ConsoleAppender's by modifying log4j configuration dynamically.
* Must only be used during early startup
* @return true if ok or else false if something happened, e.g. log4j classes were not in classpath
*/
@SuppressForbidden(reason = "Legitimate log4j access")
static boolean muteConsole() {
try {
if (!isLog4jActive()) {
logNotSupported("Could not mute logging to console.");
return false;
}
org.apache.log4j.Logger rootLogger = LogManager.getRootLogger();
Enumeration appenders = rootLogger.getAllAppenders();
while (appenders.hasMoreElements()) {
Appender appender = (Appender) appenders.nextElement();
if (appender instanceof ConsoleAppender) {
log.info("Property solr.log.muteconsole given. Muting ConsoleAppender named " + appender.getName());
rootLogger.removeAppender(appender);
}
}
return true;
} catch (Exception e) {
logNotSupported("Could not mute logging to console.");
return false;
}
}
/**
* Dynamically change log4j log level through property solr.log.level
* @param logLevel String with level, should be one of the supported, e.g. TRACE, DEBUG, INFO, WARN, ERROR...
* @return true if ok or else false if something happened, e.g. log4j classes were not in classpath
*/
@SuppressForbidden(reason = "Legitimate log4j access")
static boolean changeLogLevel(String logLevel) {
try {
if (!isLog4jActive()) {
logNotSupported("Could not mute logging to console.");
return false;
}
log.info("Log level override, property solr.log.level=" + logLevel);
LogManager.getRootLogger().setLevel(Level.toLevel(logLevel, Level.INFO));
return true;
} catch (Exception e) {
logNotSupported("Could not change log level.");
return false;
}
}
private static boolean isLog4jActive() {
try {
// Make sure we have log4j LogManager in classpath
Class.forName("org.apache.log4j.LogManager");
// Make sure that log4j is really selected as logger in slf4j - we could have LogManager in the bridge class :)
return binder.getLoggerFactoryClassStr().contains("Log4jLoggerFactory");
} catch (Exception e) {
return false;
}
}
private static void logNotSupported(String msg) {
log.warn("{} Dynamic log manipulation currently only supported for Log4j. "
+ "Please consult your logging framework of choice on how to configure the appropriate logging.", msg);
}
}