blob: d6f4b5d8c923d06eee2e60be06ce5b08d000f96d [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.qpid.server.jmx.mbeans;
import org.apache.log4j.Logger;
import org.apache.qpid.management.common.mbeans.LoggingManagement;
import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
import org.apache.qpid.server.jmx.AMQManagedObject;
import org.apache.qpid.server.jmx.ManagedObject;
import org.apache.qpid.server.jmx.ManagedObjectRegistry;
import org.apache.qpid.server.logging.log4j.LoggingManagementFacade;
import org.apache.qpid.server.logging.log4j.LoggingFacadeException;
import javax.management.JMException;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/** MBean class for LoggingManagement. It implements all the management features exposed for managing logging. */
@MBeanDescription("Logging Management Interface")
public class LoggingManagementMBean extends AMQManagedObject implements LoggingManagement
{
public static final String INHERITED_PSUEDO_LOG_LEVEL = "INHERITED";
private static final Logger LOGGER = Logger.getLogger(LoggingManagementMBean.class);
private static final TabularType LOGGER_LEVEL_TABULAR_TYE;
private static final CompositeType LOGGER_LEVEL_COMPOSITE_TYPE;
private final LoggingManagementFacade _loggingManagementFacade;
private final String[] _allAvailableLogLevels;
static
{
try
{
OpenType[] loggerLevelItemTypes = new OpenType[]{SimpleType.STRING, SimpleType.STRING};
LOGGER_LEVEL_COMPOSITE_TYPE = new CompositeType("LoggerLevelList", "Logger Level Data",
COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]),
COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]),
loggerLevelItemTypes);
LOGGER_LEVEL_TABULAR_TYE = new TabularType("LoggerLevel", "List of loggers with levels",
LOGGER_LEVEL_COMPOSITE_TYPE,
TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]));
}
catch (OpenDataException e)
{
throw new ExceptionInInitializerError(e);
}
}
public LoggingManagementMBean(LoggingManagementFacade loggingManagementFacade, ManagedObjectRegistry registry) throws JMException
{
super(LoggingManagement.class, LoggingManagement.TYPE, registry);
register();
_loggingManagementFacade = loggingManagementFacade;
_allAvailableLogLevels = buildAllAvailableLoggerLevelsWithInheritedPsuedoLogLevel(_loggingManagementFacade);
}
@Override
public String getObjectInstanceName()
{
return LoggingManagement.TYPE;
}
@Override
public ManagedObject getParentObject()
{
return null;
}
@Override
public Integer getLog4jLogWatchInterval()
{
return _loggingManagementFacade.getLog4jLogWatchInterval();
}
@Override
public String[] getAvailableLoggerLevels()
{
return _allAvailableLogLevels;
}
@Override
public TabularData viewEffectiveRuntimeLoggerLevels()
{
Map<String, String> levels = _loggingManagementFacade.retrieveRuntimeLoggersLevels();
return createTabularDataFromLevelsMap(levels);
}
@Override
public String getRuntimeRootLoggerLevel()
{
return _loggingManagementFacade.retrieveRuntimeRootLoggerLevel();
}
@Override
public boolean setRuntimeRootLoggerLevel(String level)
{
try
{
validateLevelNotAllowingInherited(level);
}
catch (IllegalArgumentException iae)
{
LOGGER.warn(level + " is not a known level");
return false;
}
_loggingManagementFacade.setRuntimeRootLoggerLevel(level);
return true;
}
@Override
public boolean setRuntimeLoggerLevel(String logger, String level)
{
String validatedLevel;
try
{
validatedLevel = getValidateLevelAllowingInherited(level);
}
catch (IllegalArgumentException iae)
{
LOGGER.warn(level + " is not a known level");
return false;
}
try
{
_loggingManagementFacade.setRuntimeLoggerLevel(logger, validatedLevel);
}
catch (LoggingFacadeException e)
{
LOGGER.error("Cannot set runtime logging level", e);
return false;
}
return true;
}
@Override
public TabularData viewConfigFileLoggerLevels()
{
Map<String,String> levels;
try
{
levels = _loggingManagementFacade.retrieveConfigFileLoggersLevels();
}
catch (LoggingFacadeException e)
{
LOGGER.error("Cannot determine logging levels", e);
return null;
}
return createTabularDataFromLevelsMap(levels);
}
@Override
public String getConfigFileRootLoggerLevel()throws IOException
{
try
{
return _loggingManagementFacade.retrieveConfigFileRootLoggerLevel().toUpperCase();
}
catch (LoggingFacadeException e)
{
LOGGER.warn("The log4j configuration get config request was aborted: ", e);
throw new IOException("The log4j configuration get config request was aborted: " + e.getMessage());
}
}
@Override
public boolean setConfigFileLoggerLevel(String logger, String level)
{
String validatedLevel;
try
{
validatedLevel = getValidateLevelAllowingInherited(level);
}
catch (IllegalArgumentException iae)
{
LOGGER.warn(level + " is not a known level");
return false;
}
try
{
_loggingManagementFacade.setConfigFileLoggerLevel(logger, validatedLevel);
}
catch (LoggingFacadeException e)
{
LOGGER.warn("The log4j configuration set config request was aborted: ", e);
return false;
}
return true;
}
@Override
public boolean setConfigFileRootLoggerLevel(String level)
{
try
{
validateLevelNotAllowingInherited(level);
}
catch (IllegalArgumentException iae)
{
LOGGER.warn(level + " is not a known level");
return false;
}
try
{
_loggingManagementFacade.setConfigFileRootLoggerLevel(level);
return true;
}
catch (LoggingFacadeException e)
{
LOGGER.warn("The log4j configuration set config request was aborted: ", e);
return false;
}
}
@Override
public void reloadConfigFile() throws IOException
{
try
{
_loggingManagementFacade.reload();
}
catch (LoggingFacadeException e)
{
LOGGER.warn("The log4j configuration reload request was aborted: ", e);
throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage());
}
}
private String getValidateLevelAllowingInherited(String level)
{
if(level == null
|| "null".equalsIgnoreCase(level)
|| INHERITED_PSUEDO_LOG_LEVEL.equalsIgnoreCase(level))
{
//the string "null" or "inherited" signals to inherit from a parent logger,
//using a null Level reference for the logger.
return null;
}
validateLevelNotAllowingInherited(level);
return level;
}
private void validateLevelNotAllowingInherited(String level)
{
final List<String> availableLoggerLevels = _loggingManagementFacade.getAvailableLoggerLevels();
if (level == null || !availableLoggerLevels.contains(level.toUpperCase()))
{
throw new IllegalArgumentException(level + " not known");
}
}
private TabularData createTabularDataFromLevelsMap(Map<String, String> levels)
{
TabularData loggerLevelList = new TabularDataSupport(LOGGER_LEVEL_TABULAR_TYE);
for (Map.Entry<String,String> entry : levels.entrySet())
{
String loggerName = entry.getKey();
String level = entry.getValue();
CompositeData loggerData = createRow(loggerName, level);
loggerLevelList.put(loggerData);
}
return loggerLevelList;
}
private CompositeData createRow(String loggerName, String level)
{
Object[] itemData = {loggerName, level.toUpperCase()};
try
{
CompositeData loggerData = new CompositeDataSupport(LOGGER_LEVEL_COMPOSITE_TYPE,
COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData);
return loggerData;
}
catch (OpenDataException ode)
{
// Should not happen
throw new RuntimeException(ode);
}
}
private String[] buildAllAvailableLoggerLevelsWithInheritedPsuedoLogLevel(LoggingManagementFacade loggingManagementFacade)
{
List<String> levels = loggingManagementFacade.getAvailableLoggerLevels();
List<String> mbeanLevels = new ArrayList<String>(levels);
mbeanLevels.add(INHERITED_PSUEDO_LOG_LEVEL);
return mbeanLevels.toArray(new String[mbeanLevels.size()]);
}
}