@Override public void stop() { LOGGER.debug("Stopping LoggerContext[name={}, {}]...", getName(), this); configLock.lock(); try { if (this.isStopped()) { return; } this.setStopping(); try { Server.unregisterLoggerContext(getName()); // LOG4J2-406, LOG4J2-500 } catch (final Exception ex) { LOGGER.error("Unable to unregister MBeans", ex); } if (shutdownCallback != null) { shutdownCallback.cancel(); shutdownCallback = null; } final Configuration prev = configuration; configuration = NULL_CONFIGURATION; updateLoggers(); prev.stop(); externalContext = null; LogManager.getFactory().removeContext(this); this.setStopped(); } finally { configLock.unlock(); } LOGGER.debug("Stopped LoggerContext[name={}, {}]...", getName(), this); }
static void updateLoggers(final Appender appender, final Configuration config) { final Level level = null; final Filter filter = null; for (final LoggerConfig loggerConfig : config.getLoggers().values()) { loggerConfig.addAppender(appender, level, filter); } config.getRootLogger().addAppender(appender, level, filter); }
@BeforeClass public void configure() { LoggerContext ctx = (LoggerContext) LogManager.getContext(false); Configuration config = ctx.getConfiguration(); config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).setLevel(Level.INFO); ctx.updateLoggers(); // This causes all Loggers to refetch information from their LoggerConfig. dao = new ScriptDao(); }
private void initializeLogging(final Level logLevel) { final LoggerContext context = (LoggerContext) LogManager.getContext(false); final org.apache.logging.log4j.core.config.Configuration config = context.getConfiguration(); config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).setLevel(logLevel); config.getLoggerConfig(Main.class.getPackage().getName()).setLevel(logLevel); context.updateLoggers(config); }
private void addInstrumentedAppender(final MetricRegistry metrics, final Level level) { final InstrumentedAppender appender = new InstrumentedAppender(metrics, null, null, false); appender.start(); final LoggerContext context = (LoggerContext) LogManager.getContext(false); final org.apache.logging.log4j.core.config.Configuration config = context.getConfiguration(); config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).addAppender(appender, level, null); context.updateLoggers(config); }
private void initOperationLogCapture(String loggingMode) { // Register another Appender (with the same layout) that talks to us. Appender ap = LogDivertAppender.createInstance(this, OperationLog.getLoggingLevel(loggingMode)); LoggerContext context = (LoggerContext) LogManager.getContext(false); Configuration configuration = context.getConfiguration(); LoggerConfig loggerConfig = configuration.getLoggerConfig(LoggerFactory.getLogger(getClass()).getName()); loggerConfig.addAppender(ap, null, null); context.updateLoggers(); ap.start(); }
/** * Create a PatternParser. * * @param config The Configuration. * @param filterClass Filter the returned plugins after calling the plugin manager. * @return The PatternParser. */ private static PatternParser createPatternParser( final Configuration config, final Class<? extends PatternConverter> filterClass) { if (config == null) { return new PatternParser( config, PatternLayout.KEY, LogEventPatternConverter.class, filterClass); } PatternParser parser = config.getComponent(COMPONENT_KEY); if (parser == null) { parser = new PatternParser(config, PatternLayout.KEY, ThrowablePatternConverter.class); config.addComponent(COMPONENT_KEY, parser); parser = (PatternParser) config.getComponent(COMPONENT_KEY); } return parser; }
@Test public void testNanoPatternShortChangesConfigurationNanoClock() { final Configuration config = new NullConfiguration(); assertTrue(config.getNanoClock() instanceof DummyNanoClock); final PatternParser pp = new PatternParser(config, KEY, null); assertTrue(config.getNanoClock() instanceof DummyNanoClock); pp.parse("%m"); assertTrue(config.getNanoClock() instanceof DummyNanoClock); pp.parse("%nano"); // this changes the config clock assertTrue(config.getNanoClock() instanceof SystemNanoClock); }
@Test public void testNanoPatternLongChangesNanoClockFactoryMode() { final Configuration config = new NullConfiguration(); assertTrue(config.getNanoClock() instanceof DummyNanoClock); final PatternParser pp = new PatternParser(config, KEY, null); assertTrue(config.getNanoClock() instanceof DummyNanoClock); pp.parse("%m"); assertTrue(config.getNanoClock() instanceof DummyNanoClock); pp.parse("%N"); assertTrue(config.getNanoClock() instanceof SystemNanoClock); }
/** Reconfigures the context. */ private void reconfigure(final URI configURI) { final ClassLoader cl = ClassLoader.class.isInstance(externalContext) ? (ClassLoader) externalContext : null; LOGGER.debug( "Reconfiguration started for context[name={}] at URI {} ({}) with optional ClassLoader: {}", contextName, configURI, this, cl); final Configuration instance = ConfigurationFactory.getInstance().getConfiguration(contextName, configURI, cl); setConfiguration(instance); /* * instance.start(); Configuration old = setConfiguration(instance); updateLoggers(); if (old != null) { * old.stop(); } */ final String location = configuration == null ? "?" : String.valueOf(configuration.getConfigurationSource()); LOGGER.debug( "Reconfiguration complete for context[name={}] at URI {} ({}) with optional ClassLoader: {}", contextName, location, this, cl); }
@Test public void test() throws Exception { // To ensure our custom plugin is NOT included in the log4j plugin metadata file, // we make sure the class does not exist until after the build is finished. // So we don't create the custom plugin class until this test is run. final File orig = new File("target/test-classes/customplugin/FixedStringLayout.java.source"); final File f = new File(orig.getParentFile(), "FixedStringLayout.java"); assertTrue("renamed source file OK", orig.renameTo(f)); compile(f); assertTrue("reverted source file OK", f.renameTo(orig)); // load the compiled class Class.forName("customplugin.FixedStringLayout"); // now that the custom plugin class exists, we load the config // with the packages element pointing to our custom plugin ctx = Configurator.initialize("Test1", "customplugin/log4j2-741.xml"); config = ctx.getConfiguration(); listAppender = (ListAppender) config.getAppender("List"); final Logger logger = LogManager.getLogger(PluginManagerPackagesTest.class); logger.info("this message is ignored"); final List<String> messages = listAppender.getMessages(); assertEquals(messages.toString(), 1, messages.size()); assertEquals("abc123XYZ", messages.get(0)); }
@Override public void start() { final Map<String, Appender> map = config.getAppenders(); final List<AppenderControl> appenders = new ArrayList<>(); for (final AppenderRef appenderRef : appenderRefs) { if (map.containsKey(appenderRef.getRef())) { appenders.add( new AppenderControl( map.get(appenderRef.getRef()), appenderRef.getLevel(), appenderRef.getFilter())); } else { LOGGER.error("No appender named {} was configured", appenderRef); } } if (errorRef != null) { if (map.containsKey(errorRef)) { errorAppender = new AppenderControl(map.get(errorRef), null, null); } else { LOGGER.error( "Unable to set up error Appender. No appender named {} was configured", errorRef); } } if (appenders.size() > 0) { thread = new AsyncThread(appenders, queue); thread.setName("AsyncAppender-" + getName()); } else if (errorRef == null) { throw new ConfigurationException("No appenders are available for AsyncAppender " + getName()); } thread.start(); super.start(); }
/** * Sets the Configuration to be used. * * @param config The new Configuration. * @return The previous Configuration. */ private Configuration setConfiguration(final Configuration config) { Objects.requireNonNull(config, "No Configuration was provided"); configLock.lock(); try { final Configuration prev = this.configuration; config.addListener(this); final ConcurrentMap<String, String> map = config.getComponent(Configuration.CONTEXT_PROPERTIES); try { // LOG4J2-719 network access may throw android.os.NetworkOnMainThreadException map.putIfAbsent("hostName", NetUtils.getLocalHostname()); } catch (final Exception ex) { LOGGER.debug("Ignoring {}, setting hostName to 'unknown'", ex.toString()); map.putIfAbsent("hostName", "unknown"); } map.putIfAbsent("contextName", contextName); config.start(); this.configuration = config; updateLoggers(); if (prev != null) { prev.removeListener(this); prev.stop(); } firePropertyChangeEvent(new PropertyChangeEvent(this, PROPERTY_CONFIG, prev, config)); try { Server.reregisterMBeansAfterReconfigure(); } catch (final Throwable t) { // LOG4J2-716: Android has no java.lang.management LOGGER.error("Could not reconfigure JMX", t); } Log4jLogEvent.setNanoClock(NanoClockFactory.createNanoClock()); AsyncLogger.setNanoClock(NanoClockFactory.createNanoClock()); return prev; } finally { configLock.unlock(); } }
private Rfc5424Layout( final Configuration config, final Facility facility, final String id, final int ein, final boolean includeMDC, final boolean includeNL, final String escapeNL, final String mdcId, final String mdcPrefix, final String eventPrefix, final String appName, final String messageId, final String excludes, final String includes, final String required, final Charset charset, final String exceptionPattern, final boolean useTLSMessageFormat, final LoggerFields[] loggerFields) { super(charset); final PatternParser exceptionParser = createPatternParser(config, ThrowablePatternConverter.class); exceptionFormatters = exceptionPattern == null ? null : exceptionParser.parse(exceptionPattern, false, false); this.facility = facility; this.defaultId = id == null ? DEFAULT_ID : id; this.enterpriseNumber = ein; this.includeMdc = includeMDC; this.includeNewLine = includeNL; this.escapeNewLine = escapeNL == null ? null : Matcher.quoteReplacement(escapeNL); this.mdcId = mdcId; this.mdcSdId = new StructuredDataId(mdcId, enterpriseNumber, null, null); this.mdcPrefix = mdcPrefix; this.eventPrefix = eventPrefix; this.appName = appName; this.messageId = messageId; this.useTlsMessageFormat = useTLSMessageFormat; this.localHostName = NetUtils.getLocalHostname(); ListChecker c = null; if (excludes != null) { final String[] array = excludes.split(Patterns.COMMA_SEPARATOR); if (array.length > 0) { c = new ExcludeChecker(); mdcExcludes = new ArrayList<String>(array.length); for (final String str : array) { mdcExcludes.add(str.trim()); } } else { mdcExcludes = null; } } else { mdcExcludes = null; } if (includes != null) { final String[] array = includes.split(Patterns.COMMA_SEPARATOR); if (array.length > 0) { c = new IncludeChecker(); mdcIncludes = new ArrayList<String>(array.length); for (final String str : array) { mdcIncludes.add(str.trim()); } } else { mdcIncludes = null; } } else { mdcIncludes = null; } if (required != null) { final String[] array = required.split(Patterns.COMMA_SEPARATOR); if (array.length > 0) { mdcRequired = new ArrayList<String>(array.length); for (final String str : array) { mdcRequired.add(str.trim()); } } else { mdcRequired = null; } } else { mdcRequired = null; } this.checker = c != null ? c : noopChecker; final String name = config == null ? null : config.getName(); configName = name != null && name.length() > 0 ? name : null; this.fieldFormatters = createFieldFormatters(loggerFields, config); }
/** * Adds a Filter to the Configuration. Filters that are added through the API will be lost when a * reconfigure occurs. * * @param filter The Filter to add. */ public void addFilter(final Filter filter) { configuration.addFilter(filter); }
/** * Create a RollingRandomAccessFileAppender. * * @param fileName The name of the file that is actively written to. (required). * @param filePattern The pattern of the file name to use on rollover. (required). * @param append If true, events are appended to the file. If false, the file is overwritten when * opened. Defaults to "true" * @param name The name of the Appender (required). * @param immediateFlush When true, events are immediately flushed. Defaults to "true". * @param bufferSizeStr The buffer size, defaults to {@value * RollingRandomAccessFileManager#DEFAULT_BUFFER_SIZE}. * @param policy The triggering policy. (required). * @param strategy The rollover strategy. Defaults to DefaultRolloverStrategy. * @param layout The layout to use (defaults to the default PatternLayout). * @param filter The Filter or null. * @param ignore If {@code "true"} (default) exceptions encountered when appending events are * logged; otherwise they are propagated to the caller. * @param advertise "true" if the appender configuration should be advertised, "false" otherwise. * @param advertiseURI The advertised URI which can be used to retrieve the file contents. * @param config The Configuration. * @return A RollingRandomAccessFileAppender. */ @PluginFactory public static RollingRandomAccessFileAppender createAppender( @PluginAttribute("fileName") final String fileName, @PluginAttribute("filePattern") final String filePattern, @PluginAttribute("append") final String append, @PluginAttribute("name") final String name, @PluginAttribute("immediateFlush") final String immediateFlush, @PluginAttribute("bufferSize") final String bufferSizeStr, @PluginElement("Policy") final TriggeringPolicy policy, @PluginElement("Strategy") RolloverStrategy strategy, @PluginElement("Layout") Layout<? extends Serializable> layout, @PluginElement("Filter") final Filter filter, @PluginAttribute("ignoreExceptions") final String ignore, @PluginAttribute("advertise") final String advertise, @PluginAttribute("advertiseURI") final String advertiseURI, @PluginConfiguration final Configuration config) { final boolean isAppend = Booleans.parseBoolean(append, true); final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true); final boolean isFlush = Booleans.parseBoolean(immediateFlush, true); final boolean isAdvertise = Boolean.parseBoolean(advertise); final int bufferSize = Integers.parseInt(bufferSizeStr, RollingRandomAccessFileManager.DEFAULT_BUFFER_SIZE); if (name == null) { LOGGER.error("No name provided for FileAppender"); return null; } if (fileName == null) { LOGGER.error("No filename was provided for FileAppender with name " + name); return null; } if (filePattern == null) { LOGGER.error("No filename pattern provided for FileAppender with name " + name); return null; } if (policy == null) { LOGGER.error("A TriggeringPolicy must be provided"); return null; } if (strategy == null) { strategy = DefaultRolloverStrategy.createStrategy( null, null, null, String.valueOf(Deflater.DEFAULT_COMPRESSION), config); } if (layout == null) { layout = PatternLayout.createDefaultLayout(); } final RollingRandomAccessFileManager manager = RollingRandomAccessFileManager.getRollingRandomAccessFileManager( fileName, filePattern, isAppend, isFlush, bufferSize, policy, strategy, advertiseURI, layout); if (manager == null) { return null; } return new RollingRandomAccessFileAppender( name, layout, filter, manager, fileName, filePattern, ignoreExceptions, isFlush, bufferSize, isAdvertise ? config.getAdvertiser() : null); }
@PluginFactory public static SyslogAppender createAppender( @PluginAttribute("host") String host, @PluginAttribute("port") String portNum, @PluginAttribute("protocol") String protocol, @PluginAttribute("reconnectionDelay") String delay, @PluginAttribute("immediateFail") String immediateFail, @PluginAttribute("name") String name, @PluginAttribute("immediateFlush") String immediateFlush, @PluginAttribute("ignoreExceptions") String ignore, @PluginAttribute("facility") String facility, @PluginAttribute("id") String id, @PluginAttribute("enterpriseNumber") String ein, @PluginAttribute("includeMDC") String includeMDC, @PluginAttribute("mdcId") String mdcId, @PluginAttribute("mdcPrefix") String mdcPrefix, @PluginAttribute("eventPrefix") String eventPrefix, @PluginAttribute("newLine") String includeNL, @PluginAttribute("newLineEscape") String escapeNL, @PluginAttribute("appName") String appName, @PluginAttribute("messageId") String msgId, @PluginAttribute("mdcExcludes") String excludes, @PluginAttribute("mdcIncludes") String includes, @PluginAttribute("mdcRequired") String required, @PluginAttribute("format") String format, @PluginElement("Filters") Filter filter, @PluginConfiguration Configuration config, @PluginAttribute("charset") String charsetName, @PluginAttribute("exceptionPattern") String exceptionPattern, @PluginElement("LoggerFields") LoggerFields[] loggerFields, @PluginAttribute("advertise") String advertise) { boolean isFlush = Booleans.parseBoolean(immediateFlush, true); boolean ignoreExceptions = Booleans.parseBoolean(ignore, true); int reconnectDelay = AbstractAppender.parseInt(delay, 0); boolean fail = Booleans.parseBoolean(immediateFail, true); int port = AbstractAppender.parseInt(portNum, 0); boolean isAdvertise = Boolean.parseBoolean(advertise); Layout<? extends Serializable> layout = "RFC5424".equalsIgnoreCase(format) ? RFC5424Layout.createLayout( facility, id, ein, includeMDC, mdcId, mdcPrefix, eventPrefix, includeNL, escapeNL, appName, msgId, excludes, includes, required, exceptionPattern, "false", loggerFields, config) : SyslogLayout.createLayout(facility, includeNL, escapeNL, charsetName); if (name == null) { LOGGER.error("No name provided for SyslogAppender"); return null; } Protocol p = (Protocol) EnglishEnums.valueOf(Protocol.class, protocol); AbstractSocketManager manager = createSocketManager(p, host, port, reconnectDelay, fail, layout); if (manager == null) { return null; } return new SyslogAppender( name, layout, filter, ignoreExceptions, isFlush, manager, isAdvertise ? config.getAdvertiser() : null); }
/** * Removes a Filter from the current Configuration. * * @param filter The Filter to remove. */ public void removeFilter(final Filter filter) { configuration.removeFilter(filter); }