All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mule.module.launcher.log4j2.LoggerContextConfigurer Maven / Gradle / Ivy

There is a newer version: 3.9.0
Show newest version
/*
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */
package org.mule.module.launcher.log4j2;

import org.mule.api.MuleRuntimeException;
import org.mule.api.config.MuleProperties;
import org.mule.config.i18n.MessageFactory;
import org.mule.module.reboot.MuleContainerBootstrapUtils;
import org.mule.util.ClassUtils;
import org.mule.util.FileUtils;

import java.io.File;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.List;
import java.util.zip.Deflater;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.appender.RandomAccessFileAppender;
import org.apache.logging.log4j.core.appender.RollingFileAppender;
import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy;
import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
import org.apache.logging.log4j.core.config.AbstractConfiguration;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationListener;
import org.apache.logging.log4j.core.config.ConfiguratonFileWatcher;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.Reconfigurable;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.util.FileWatcher;

/**
 * This component grabs a {link MuleLoggerContext} which has just been created reading a configuration file
 * and applies configuration changes to it so that it complies with mule's logging strategy.
 * 

* Its basic functions are: *

    *
  • Disable log4j's shutdown hook so that it doesn't collide with mule's {@link org.mule.module.launcher.artifact.ShutdownListener}, * which would result in a classloader leak.
  • *
  • When using a default configuration (one which doesn't come from a config file), the console appender is removed
  • *
  • if the classloader is an {@link org.mule.module.launcher.artifact.ArtifactClassLoader}, then it adds a rolling file appender * to collect the artifact's logs
  • *
  • if the configuration did not include a monitorInterval, then one is set to a default value of 60
  • *
  • if the context is standalone, then it adds a rolling file appender associated to the artifact
  • *
  • if the context is not standalone, then it just logs to a file named mule-main.log
  • *
* * @since 3.6.0 */ final class LoggerContextConfigurer { private static final String MULE_APP_LOG_FILE_TEMPLATE = "mule-app-%s.log"; private static final String MULE_DOMAIN_LOG_FILE_TEMPLATE = "mule-domain-%s.log"; private static final String PATTERN_LAYOUT = "%-5p %d [%t] %c: %m%n"; private static final int DEFAULT_MONITOR_INTERVAL_SECS = 60; static final String FORCED_CONSOLE_APPENDER_NAME = "Forced-Console"; static final String PER_APP_FILE_APPENDER_NAME = "defaultFileAppender"; protected void configure(MuleLoggerContext context) { disableShutdownHook(context); configureMonitor(context); } protected void update(MuleLoggerContext context) { boolean forceConsoleLog = System.getProperty(MuleProperties.MULE_FORCE_CONSOLE_LOG) != null; if (context.getConfigFile() == null && !forceConsoleLog) { removeConsoleAppender(context); } if (context.isArtifactClassloader()) { addDefaultArtifactContext(context); } else if (!context.isStandlone()) { addDefaultAppender(context, "mule-main.log"); } if (forceConsoleLog && !hasAppender(context, ConsoleAppender.class)) { forceConsoleAppender(context); } } private void disableShutdownHook(LoggerContext context) { try { ClassUtils.setFieldValue(context.getConfiguration(), "isShutdownHookEnabled", false, true); } catch (Exception e) { throw new MuleRuntimeException(MessageFactory.createStaticMessage("Could not configure shutdown hook. Unexpected configuration type"), e); } } private void configureMonitor(MuleLoggerContext context) { Configuration configuration = context.getConfiguration(); File configFile = null; if (context.getConfigFile() != null) { configFile = new File(context.getConfigFile().getPath()); } else if (!StringUtils.isEmpty(configuration.getName())) { configFile = new File(configuration.getName()); } if (configFile != null && configuration instanceof Reconfigurable) { configuration.getWatchManager().setIntervalSeconds(DEFAULT_MONITOR_INTERVAL_SECS); FileWatcher watcher = new ConfiguratonFileWatcher((Reconfigurable) configuration, getListeners(configuration)); configuration.getWatchManager().watchFile(configFile, watcher); } } private List getListeners(Configuration configuration) { try { return ClassUtils.getFieldValue(configuration, "listeners", true); } catch (Exception e) { throw new MuleRuntimeException(MessageFactory.createStaticMessage("Could not get listeners. Unexpected configuration type"), e); } } private void addDefaultAppender(MuleLoggerContext context, String logFilePath) { RollingFileAppender appender = createRollingFileAppender(logFilePath, ".%d{yyyy-MM-dd}", PER_APP_FILE_APPENDER_NAME, context.getConfiguration()); doAddAppender(context, appender); } private void forceConsoleAppender(MuleLoggerContext context) { Appender appender = ConsoleAppender.createAppender(createLayout(context.getConfiguration()), null, null, FORCED_CONSOLE_APPENDER_NAME, null, null); doAddAppender(context, appender); } private void doAddAppender(LoggerContext context, Appender appender) { appender.start(); context.getConfiguration().addAppender(appender); getRootLogger(context).addAppender(appender, Level.ALL, null); } private RollingFileAppender createRollingFileAppender(String logFilePath, String filePattern, String appenderName, Configuration configuration) { TriggeringPolicy triggeringPolicy = TimeBasedTriggeringPolicy.createPolicy("1", "true"); RolloverStrategy rolloverStrategy = DefaultRolloverStrategy.createStrategy("30", "1", null, String.valueOf(Deflater.NO_COMPRESSION), null, true, configuration); return RollingFileAppender.createAppender(logFilePath, logFilePath + filePattern, "true", appenderName, "true", null, null, triggeringPolicy, rolloverStrategy, createLayout(configuration), null, null, null, null, configuration); } private Layout createLayout(Configuration configuration) { return PatternLayout.createLayout(PATTERN_LAYOUT, null, configuration, null, null, true, false, null, null); } private void addDefaultArtifactContext(MuleLoggerContext context) { String logFileNameTemplate = getFilenamePattern(context); if (logFileNameTemplate == null) { return; } String artifactName = context.getArtifactName(); String logName = String.format(logFileNameTemplate, (artifactName != null ? artifactName : "")); File logDir = new File(MuleContainerBootstrapUtils.getMuleHome(), "logs"); File logFile = new File(logDir, logName); if (context.getConfigLocation() == null) { addDefaultAppender(context, logFile.getAbsolutePath()); } else { // If the artifact logging is configured using the global config file and there is no file appender for the artifact, then configure a default one if (isUrlInsideDirectory(context.getConfigFile(), MuleContainerBootstrapUtils.getMuleConfDir())) { if (!hasFileAppender(context)) { addDefaultAppender(context, logFile.getAbsolutePath()); removeConsoleAppender(context); } } } } private void removeConsoleAppender(LoggerContext context) { for (Appender appender : getRootLogger(context).getAppenders().values()) { if (appender instanceof ConsoleAppender) { removeAppender(context, appender); getRootLogger(context).removeAppender(appender.getName()); } } } private boolean hasFileAppender(LoggerContext context) { return hasAppender(context, FileAppender.class, RollingFileAppender.class, RandomAccessFileAppender.class); } private boolean hasAppender(LoggerContext context, Class... appenderTypes) { for (Appender appender : getRootLogger(context).getAppenders().values()) { for (Class appenderType : appenderTypes) { if (appenderType.isInstance(appender)) { return true; } } } return false; } private boolean isUrlInsideDirectory(URI uri, File directory) { if (uri == null) { return false; } URL url; try { url = uri.toURL(); } catch (MalformedURLException e) { throw new MuleRuntimeException(MessageFactory.createStaticMessage("Could not locate file " + uri), e); } if (directory != null && FileUtils.isFile(url)) { File urlFile = new File(url.getFile()); return directory.equals(urlFile.getParentFile()); } return false; } private String getFilenamePattern(MuleLoggerContext context) { if (context.isArtifactClassloader()) { return context.isApplicationClassloader() ? MULE_APP_LOG_FILE_TEMPLATE : MULE_DOMAIN_LOG_FILE_TEMPLATE; } return null; } private LoggerConfig getRootLogger(LoggerContext context) { return ((AbstractConfiguration) context.getConfiguration()).getRootLogger(); } private void removeAppender(LoggerContext context, Appender appender) { ((AbstractConfiguration) context.getConfiguration()).removeAppender(appender.getName()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy