下面列出了怎么用org.apache.logging.log4j.core.config.AbstractConfiguration的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public Configuration reconfigure() {
final Configuration refreshedParent = super.reconfigure();
if (refreshedParent != null
&& AbstractConfiguration.class.isAssignableFrom(refreshedParent.getClass())) {
try {
final AdditionalProgrammaticConfiguration refreshed =
new AdditionalProgrammaticConfiguration(
refreshedParent.getLoggerContext(),
refreshedParent.getConfigurationSource().resetInputStream());
LoggingConfigurator.addLoggersProgrammatically(refreshed);
return refreshed;
} catch (final IOException e) {
StatusLogger.getLogger().error("Failed to reload the Log4j2 Xml configuration file", e);
}
}
StatusLogger.getLogger().warn("Cannot programmatically reconfigure loggers");
return refreshedParent;
}
@Test
public void testCustomExceptionHandlerIsPassedToEvent() {
AbstractConfiguration config = setUpFailingAppender();
MutableBoolean exceptionHandled = new MutableBoolean(false);
LogEventFactory.setDefaultHandler((message, ex) -> {
assertThat(ex, instanceOf(LoggingException.class));
exceptionHandled.setTrue();
});
Transfer transfer = setUpMinimumEvent();
transfer.logEvent();
assertTrue("Exception was not handled through the custom handler", exceptionHandled.isTrue());
config.removeAppender(failingAppenderName);
}
@Override
public Configuration reconfigure() {
LOGGER.debug("Reconfiguring composite configuration");
final List<AbstractConfiguration> configs = new ArrayList<>();
final ConfigurationFactory factory = ConfigurationFactory.getInstance();
for (final AbstractConfiguration config : configurations) {
final ConfigurationSource source = config.getConfigurationSource();
final URI sourceURI = source.getURI();
Configuration currentConfig = config;
if (sourceURI == null) {
LOGGER.warn("Unable to determine URI for configuration {}, changes to it will be ignored",
config.getName());
} else {
currentConfig = factory.getConfiguration(getLoggerContext(), config.getName(), sourceURI);
if (currentConfig == null) {
LOGGER.warn("Unable to reload configuration {}, changes to it will be ignored", config.getName());
}
}
configs.add((AbstractConfiguration) currentConfig);
}
return new CompositeConfiguration(configs);
}
public static synchronized void update(final LoggingConfiguration configuration) {
COLOR.set(configuration.isColorEnabled());
DESTINATION = configuration.getDestination();
INCLUDE_EVENTS = configuration.isIncludeEventsEnabled();
INCLUDE_VALIDATOR_DUTIES = configuration.isIncludeValidatorDutiesEnabled();
FILE = configuration.getFile();
FILE_PATTERN = configuration.getFileNamePattern();
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
addLoggers((AbstractConfiguration) ctx.getConfiguration());
ctx.updateLoggers();
}
public ConsolePatternSelector(
final AbstractConfiguration configuration, final boolean omitStackTraces) {
this.omitStackTraces = omitStackTraces;
final PatternParser patternParser = PatternLayout.createPatternParser(configuration);
omitStackTraceFormat =
patternParser.parse(CONSOLE_EXCEPTION_FORMAT, false, true).toArray(PatternFormatter[]::new);
defaultFormat =
patternParser.parse(CONSOLE_FORMAT, true, true).toArray(PatternFormatter[]::new);
}
private AbstractConfiguration setUpFailingAppender() {
Logger auditLogger = (Logger) LogManager.getContext(false).getLogger("AuditLogger");
AbstractConfiguration config = (AbstractConfiguration) ctx.getConfiguration();
Appender appender = AlwaysFailAppender.createAppender(failingAppenderName);
appender.start();
config.addLoggerAppender(auditLogger, appender);
return config;
}
@Test
public void testDefaultExceptionHandlerIsInvokedOnEventLogFailure() {
AbstractConfiguration config = setUpFailingAppender();
exception.expect(AuditException.class);
exception.expectCause(isA(LoggingException.class));
exception.expectMessage("Error logging event transfer");
Transfer transfer = setUpMinimumEvent();
try {
transfer.logEvent();
} finally {
config.removeAppender(failingAppenderName);
}
}
void register() {
if (LogManager.getContext(false) instanceof LoggerContext) {
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
if (ctx.getConfiguration() instanceof AbstractConfiguration) {
final AbstractConfiguration config = (AbstractConfiguration) ctx.getConfiguration();
final Appender appender = getSingleton();
appender.start();
config.addAppender(appender);
final Logger rootLogger = LogManager.getRootLogger();
final LoggerConfig loggerConfig = config.getLoggerConfig(rootLogger.getName());
loggerConfig.addAppender(appender, null, null);
ctx.updateLoggers();
}
}
}
void deregister() {
if (LogManager.getContext(false) instanceof LoggerContext) {
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
if (ctx.getConfiguration() instanceof AbstractConfiguration) {
final AbstractConfiguration config = (AbstractConfiguration) ctx.getConfiguration();
final Appender appender = getSingleton();
appender.stop();
config.removeAppender(appender.getName());
final Logger rootLogger = LogManager.getRootLogger();
final LoggerConfig loggerConfig = config.getLoggerConfig(rootLogger.getName());
loggerConfig.removeAppender(appender.getName());
ctx.updateLoggers();
}
}
}
/**
* Construct the CompositeConfiguration.
*
* @param configurations The List of Configurations to merge.
*/
public CompositeConfiguration(final List<? extends AbstractConfiguration> configurations) {
super(configurations.get(0).getLoggerContext(), ConfigurationSource.COMPOSITE_SOURCE);
rootNode = configurations.get(0).getRootNode();
this.configurations = configurations;
final String mergeStrategyClassName = PropertiesUtil.getProperties().getStringProperty(MERGE_STRATEGY_PROPERTY,
DefaultMergeStrategy.class.getName());
try {
mergeStrategy = Loader.newInstanceOf(mergeStrategyClassName);
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException |
InstantiationException ex) {
mergeStrategy = new DefaultMergeStrategy();
}
for (final AbstractConfiguration config : configurations) {
mergeStrategy.mergeRootProperties(rootNode, config);
}
final StatusConfiguration statusConfig = new StatusConfiguration().setVerboseClasses(VERBOSE_CLASSES)
.setStatus(getDefaultStatus());
for (final Map.Entry<String, String> entry : rootNode.getAttributes().entrySet()) {
final String key = entry.getKey();
final String value = getStrSubstitutor().replace(entry.getValue());
if ("status".equalsIgnoreCase(key)) {
statusConfig.setStatus(value.toUpperCase());
} else if ("dest".equalsIgnoreCase(key)) {
statusConfig.setDestination(value);
} else if ("shutdownHook".equalsIgnoreCase(key)) {
isShutdownHookEnabled = !"disable".equalsIgnoreCase(value);
} else if ("shutdownTimeout".equalsIgnoreCase(key)) {
shutdownTimeoutMillis = Long.parseLong(value);
} else if ("verbose".equalsIgnoreCase(key)) {
statusConfig.setVerbosity(value);
} else if ("packages".equalsIgnoreCase(key)) {
pluginPackages.addAll(Arrays.asList(value.split(Patterns.COMMA_SEPARATOR)));
} else if ("name".equalsIgnoreCase(key)) {
setName(value);
}
}
statusConfig.initialize();
}
/**
* Merge the root properties.
* @param rootNode The composite root node.
* @param configuration The configuration to merge.
*/
@Override
public void mergeRootProperties(final Node rootNode, final AbstractConfiguration configuration) {
for (final Map.Entry<String, String> attribute : configuration.getRootNode().getAttributes().entrySet()) {
boolean isFound = false;
for (final Map.Entry<String, String> targetAttribute : rootNode.getAttributes().entrySet()) {
if (targetAttribute.getKey().equalsIgnoreCase(attribute.getKey())) {
if (attribute.getKey().equalsIgnoreCase(STATUS)) {
final Level targetLevel = Level.getLevel(targetAttribute.getValue().toUpperCase());
final Level sourceLevel = Level.getLevel(attribute.getValue().toUpperCase());
if (targetLevel != null && sourceLevel != null) {
if (sourceLevel.isLessSpecificThan(targetLevel)) {
targetAttribute.setValue(attribute.getValue());
}
} else
if (sourceLevel != null) {
targetAttribute.setValue(attribute.getValue());
}
} else {
if (attribute.getKey().equalsIgnoreCase("monitorInterval")) {
final int sourceInterval = Integer.parseInt(attribute.getValue());
final int targetInterval = Integer.parseInt(targetAttribute.getValue());
if (targetInterval == 0 || sourceInterval < targetInterval) {
targetAttribute.setValue(attribute.getValue());
}
} else {
targetAttribute.setValue(attribute.getValue());
}
}
isFound = true;
}
}
if (!isFound) {
rootNode.getAttributes().put(attribute.getKey(), attribute.getValue());
}
}
}
public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
final boolean currentContext, final List<URI> configLocations, final String name) {
final LoggerContext ctx = selector
.getContext(fqcn, loader, currentContext, null/*this probably needs to change*/);
if (externalContext != null && ctx.getExternalContext() == null) {
ctx.setExternalContext(externalContext);
}
if (name != null) {
ctx.setName(name);
}
if (ctx.getState() == LifeCycle.State.INITIALIZED) {
if ((configLocations != null && !configLocations.isEmpty())) {
ContextAnchor.THREAD_CONTEXT.set(ctx);
final List<AbstractConfiguration> configurations = new ArrayList<>(configLocations.size());
for (final URI configLocation : configLocations) {
final Configuration currentReadConfiguration = ConfigurationFactory.getInstance()
.getConfiguration(ctx, name, configLocation);
if (currentReadConfiguration instanceof AbstractConfiguration) {
configurations.add((AbstractConfiguration) currentReadConfiguration);
} else {
LOGGER.error(
"Found configuration {}, which is not an AbstractConfiguration and can't be handled by CompositeConfiguration",
configLocation);
}
}
final CompositeConfiguration compositeConfiguration = new CompositeConfiguration(configurations);
LOGGER.debug("Starting LoggerContext[name={}] from configurations at {}", ctx.getName(),
configLocations);
ctx.start(compositeConfiguration);
ContextAnchor.THREAD_CONTEXT.remove();
} else {
ctx.start();
}
}
return ctx;
}
public static synchronized void addLoggersProgrammatically(
final AbstractConfiguration configuration) {
addLoggers(configuration);
}
private static void addLoggers(final AbstractConfiguration configuration) {
if (isUninitialized()) {
return;
}
if (isProgrammaticLoggingRedundant()) {
displayCustomLog4jConfigUsed();
return;
}
displayProgrammaticLoggingConfiguration();
Appender consoleAppender;
Appender fileAppender;
switch (DESTINATION) {
case CONSOLE:
consoleAppender = consoleAppender(configuration, false);
setUpStatusLogger(consoleAppender);
setUpEventsLogger(consoleAppender);
setUpValidatorLogger(consoleAppender);
addAppenderToRootLogger(configuration, consoleAppender);
break;
case FILE:
fileAppender = fileAppender(configuration);
setUpStatusLogger(fileAppender);
setUpEventsLogger(fileAppender);
setUpValidatorLogger(fileAppender);
addAppenderToRootLogger(configuration, fileAppender);
break;
default:
displayUnknownDestinationConfigured();
// fall through
case DEFAULT_BOTH:
// fall through
case BOTH:
consoleAppender = consoleAppender(configuration, true);
final LoggerConfig eventsLogger = setUpEventsLogger(consoleAppender);
final LoggerConfig statusLogger = setUpStatusLogger(consoleAppender);
final LoggerConfig validatorLogger = setUpValidatorLogger(consoleAppender);
configuration.addLogger(eventsLogger.getName(), eventsLogger);
configuration.addLogger(statusLogger.getName(), statusLogger);
configuration.addLogger(validatorLogger.getName(), validatorLogger);
fileAppender = fileAppender(configuration);
setUpStatusLogger(consoleAppender);
addAppenderToRootLogger(configuration, fileAppender);
break;
}
configuration.getLoggerContext().updateLoggers();
}
private static void addAppenderToRootLogger(
final AbstractConfiguration configuration, final Appender appender) {
configuration.getRootLogger().addAppender(appender, null, null);
}
protected boolean processCommands() throws IOException {
final LoggerContext logCtx = (LoggerContext) LogManager.getContext(false);
final AbstractConfiguration logConf = (AbstractConfiguration) logCtx.getConfiguration();
LinkedList<String> failedQueue = new LinkedList<>();
logGrabber.grabCurrentThread();
// start grabbing logs of this thread
logConf.getRootLogger().addAppender(logGrabber, logConf.getRootLogger().getLevel(), null);
// register session to MCRSessionMgr
MCRSessionMgr.setCurrentSession(session);
Optional<HttpSession> httpSession = Optional
.ofNullable((HttpSession) webSocketSession.getUserProperties()
.get(MCRWebsocketDefaultConfigurator.HTTP_SESSION));
int sessionTime = httpSession.map(HttpSession::getMaxInactiveInterval).orElse(-1);
httpSession.ifPresent(s -> s.setMaxInactiveInterval(-1));
try {
while (!commands.isEmpty()) {
String command = commands.remove(0);
cmdListPublisher.submit(commands);
if (!processCommand(command)) {
if (!continueIfOneFails) {
return false;
}
failedQueue.add(command);
}
}
if (failedQueue.isEmpty()) {
setCurrentCommand("");
return true;
} else {
saveQueue(null, failedQueue);
return false;
}
} finally {
// stop grabbing logs of this thread
logGrabber.stop();
logConf.removeAppender(logGrabber.getName());
try {
if (webSocketSession.isOpen()) {
LogManager.getLogger().info("Close session {}", webSocketSession::getId);
webSocketSession.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "Done"));
}
} finally {
httpSession.ifPresent(s -> s.setMaxInactiveInterval(sessionTime));
// release session
MCRSessionMgr.releaseCurrentSession();
}
}
}
private static void configure(final Settings settings, final Path configsPath, final Path logsPath) throws IOException, UserException {
Objects.requireNonNull(settings);
Objects.requireNonNull(configsPath);
Objects.requireNonNull(logsPath);
loadLog4jPlugins();
setLogConfigurationSystemProperty(logsPath, settings);
// we initialize the status logger immediately otherwise Log4j will complain when we try to get the context
configureStatusLogger();
final LoggerContext context = (LoggerContext) LogManager.getContext(false);
final Set<String> locationsWithDeprecatedPatterns = Collections.synchronizedSet(new HashSet<>());
final List<AbstractConfiguration> configurations = new ArrayList<>();
/*
* Subclass the properties configurator to hack the new pattern in
* place so users don't have to change log4j2.properties in
* a minor release. In 7.0 we'll remove this and force users to
* change log4j2.properties. If they don't customize log4j2.properties
* then they won't have to do anything anyway.
*
* Everything in this subclass that isn't marked as a hack is copied
* from log4j2's source.
*/
final PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory() {
@Override
public PropertiesConfiguration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
final Properties properties = new Properties();
try (InputStream configStream = source.getInputStream()) {
properties.load(configStream);
} catch (final IOException ioe) {
throw new ConfigurationException("Unable to load " + source.toString(), ioe);
}
// Hack the new pattern into place
for (String name : properties.stringPropertyNames()) {
if (false == name.endsWith(".pattern")) continue;
// Null is weird here but we can't do anything with it so ignore it
String value = properties.getProperty(name);
if (value == null) continue;
// Tests don't need to be changed
if (value.contains("%test_thread_info")) continue;
/*
* Patterns without a marker are sufficiently customized
* that we don't have an opinion about them.
*/
if (false == value.contains("%marker")) continue;
if (false == value.contains("%node_name")) {
locationsWithDeprecatedPatterns.add(source.getLocation());
properties.setProperty(name, value.replace("%marker", "[%node_name]%marker "));
}
}
// end hack
return new PropertiesConfigurationBuilder()
.setConfigurationSource(source)
.setRootProperties(properties)
.setLoggerContext(loggerContext)
.build();
}
};
final Set<FileVisitOption> options = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
Files.walkFileTree(configsPath, options, Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
if (file.getFileName().toString().equals("log4j2.properties")) {
configurations.add((PropertiesConfiguration) factory.getConfiguration(context, file.toString(), file.toUri()));
}
return FileVisitResult.CONTINUE;
}
});
if (configurations.isEmpty()) {
throw new UserException(
ExitCodes.CONFIG,
"no log4j2.properties found; tried [" + configsPath + "] and its subdirectories");
}
context.start(new CompositeConfiguration(configurations));
configureLoggerLevels(settings);
final String deprecatedLocationsString = String.join("\n ", locationsWithDeprecatedPatterns);
if (deprecatedLocationsString.length() > 0) {
LogManager.getLogger(LogConfigurator.class).warn("Some logging configurations have %marker but don't have %node_name. "
+ "We will automatically add %node_name to the pattern to ease the migration for users who customize "
+ "log4j2.properties but will stop this behavior in 7.0. You should manually replace `%node_name` with "
+ "`[%node_name]%marker ` in these locations:\n {}", deprecatedLocationsString);
}
}
private void staffChildConfiguration(final AbstractConfiguration childConfiguration) {
childConfiguration.setPluginManager(pluginManager);
childConfiguration.setScriptManager(scriptManager);
childConfiguration.setup();
}
/**
* Merge the root node properties into the configuration.
* @param rootNode The composite root node.
* @param configuration The configuration to merge.
*/
void mergeRootProperties(Node rootNode, AbstractConfiguration configuration);