@Test public void testContextNameIsAsyncLoggerContextWithClassHashCode() { final AsyncLoggerContextSelector selector = new AsyncLoggerContextSelector(); final LoggerContext context = selector.getContext(FQCN, null, false); final int hash = getClass().getClassLoader().hashCode(); final String expectedContextName = "AsyncContext@" + Integer.toHexString(hash); assertEquals(expectedContextName, context.getName()); }
@Override public void evaluate() throws Throwable { if (contextSelectorClass != null) { System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, contextSelectorClass.getName()); } // TODO Consider instead of the above: // LogManager.setFactory(new Log4jContextFactory(LoaderUtil.newInstanceOf(contextSelectorClass))); System.setProperty(SYS_PROP_KEY_CLASS_NAME, description.getClassName()); System.setProperty(SYS_PROP_KEY_DISPLAY_NAME, description.getDisplayName()); loggerContext = Configurator.initialize(description.getDisplayName(), description.getTestClass().getClassLoader(), configLocation); try { base.evaluate(); } finally { if (!Configurator.shutdown(loggerContext, shutdownTimeout, shutdownTimeUnit)) { StatusLogger.getLogger().error("Logger context {} did not shutdown completely after {} {}.", loggerContext.getName(), shutdownTimeout, shutdownTimeUnit); } loggerContext = null; contextSelectorClass = null; StatusLogger.getLogger().reset(); System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR); System.clearProperty(SYS_PROP_KEY_CLASS_NAME); System.clearProperty(SYS_PROP_KEY_DISPLAY_NAME); } } };
@Override public String toString() { return "Shutdown callback for LoggerContext[name=" + LoggerContext.this.getName() + ']'; } });
@Override public String getName() { return loggerContext.getName(); }
@Override public void run() { @SuppressWarnings("resource") final LoggerContext context = LoggerContext.this; LOGGER.debug(SHUTDOWN_HOOK_MARKER, "Stopping LoggerContext[name={}, {}]", context.getName(), context); context.stop(shutdownTimeoutMillis, TimeUnit.MILLISECONDS); }
private ObjectName createJmxBeanName() { String beanName = firstNonNull( config.getJmxBeanName(), String.format( "org.apache.logging.log4j2:type=%s,component=Appenders,name=%s,subtype=RedisThrottler", appender.getConfig().getLoggerContext().getName(), appender.getName())); try { return new ObjectName(beanName); } catch (MalformedObjectNameException error) { String message = String.format("malformed JMX bean name (beanName=%s)", beanName); throw new RuntimeException(message, error); } }
/** * Constructs a new {@code LoggerContextAdmin} with the {@code Executor} to be used for sending {@code Notification} * s asynchronously to listeners. * * @param executor used to send notifications asynchronously * @param loggerContext the instrumented object */ public LoggerContextAdmin(final LoggerContext loggerContext, final Executor executor) { super(executor, createNotificationInfo()); this.loggerContext = Objects.requireNonNull(loggerContext, "loggerContext"); try { final String ctxName = Server.escape(loggerContext.getName()); final String name = String.format(PATTERN, ctxName); objectName = new ObjectName(name); } catch (final Exception e) { throw new IllegalStateException(e); } loggerContext.addPropertyChangeListener(this); }
/** * Constructs a new {@code LoggerConfigAdmin} with the specified LoggerContext * and logger config. * * @param loggerContext used in the {@code ObjectName} for this mbean * @param loggerConfig the instrumented object */ public LoggerConfigAdmin(final LoggerContext loggerContext, final LoggerConfig loggerConfig) { // super(executor); // no notifications for now this.loggerContext = Objects.requireNonNull(loggerContext, "loggerContext"); this.loggerConfig = Objects.requireNonNull(loggerConfig, "loggerConfig"); try { final String ctxName = Server.escape(loggerContext.getName()); final String configName = Server.escape(loggerConfig.getName()); final String name = String.format(PATTERN, ctxName, configName); objectName = new ObjectName(name); } catch (final Exception e) { throw new IllegalStateException(e); } }
/** * Returns a String representation of this instance in the form {@code "name:level[ in context_name]"}. * * @return A String describing this Logger instance. */ @Override public String toString() { final String nameLevel = Strings.EMPTY + getName() + ':' + getLevel(); if (context == null) { return nameLevel; } final String contextName = context.getName(); return contextName == null ? nameLevel : nameLevel + " in " + contextName; }
/** * Starts with a specific configuration. * * @param config The new Configuration. */ public void start(final Configuration config) { LOGGER.debug("Starting LoggerContext[name={}, {}] with configuration {}...", getName(), this, config); if (configLock.tryLock()) { try { if (this.isInitialized() || this.isStopped()) { if (this.configuration.isShutdownHookEnabled()) { setUpShutdownHook(); } this.setStarted(); } } finally { configLock.unlock(); } } setConfiguration(config); LOGGER.debug("LoggerContext[name={}, {}] started OK with configuration {}.", getName(), this, config); }
private static void registerAppenders(final LoggerContext ctx, final MBeanServer mbs, final Executor executor) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { final Map<String, Appender> map = ctx.getConfiguration().getAppenders(); for (final String name : map.keySet()) { final Appender appender = map.get(name); if (appender instanceof AsyncAppender) { final AsyncAppender async = ((AsyncAppender) appender); final AsyncAppenderAdmin mbean = new AsyncAppenderAdmin(ctx.getName(), async); register(mbs, mbean, mbean.getObjectName()); } else { final AppenderAdmin mbean = new AppenderAdmin(ctx.getName(), appender); register(mbs, mbean, mbean.getObjectName()); } } }
@Override public void start() { LOGGER.debug("Starting LoggerContext[name={}, {}]...", getName(), this); if (PropertiesUtil.getProperties().getBooleanProperty("log4j.LoggerContext.stacktrace.on.start", false)) { LOGGER.debug("Stack trace to locate invoker", new Exception("Not a real error, showing stack trace to locate invoker")); } if (configLock.tryLock()) { try { if (this.isInitialized() || this.isStopped()) { this.setStarting(); reconfigure(); if (this.configuration.isShutdownHookEnabled()) { setUpShutdownHook(); } this.setStarted(); } } finally { configLock.unlock(); } } LOGGER.debug("LoggerContext[name={}, {}] started OK.", getName(), this); }
LOGGER.debug("Stopping LoggerContext[name={}, {}]...", getName(), this); configLock.lock(); try { Server.unregisterLoggerContext(getName()); // LOG4J2-406, LOG4J2-500 } catch (final LinkageError | Exception e) { this.setStopped(); LOGGER.debug("Stopped LoggerContext[name={}, {}] with status {}", getName(), this, true); return true;
private static void registerLoggerConfigs(final LoggerContext ctx, final MBeanServer mbs, final Executor executor) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { final Map<String, LoggerConfig> map = ctx.getConfiguration().getLoggers(); for (final String name : map.keySet()) { final LoggerConfig cfg = map.get(name); final LoggerConfigAdmin mbean = new LoggerConfigAdmin(ctx, cfg); register(mbs, mbean, mbean.getObjectName()); if (cfg instanceof AsyncLoggerConfig) { final AsyncLoggerConfig async = (AsyncLoggerConfig) cfg; final RingBufferAdmin rbmbean = async.createRingBufferAdmin(ctx.getName()); register(mbs, rbmbean, rbmbean.getObjectName()); } } }
LOGGER.debug("Starting LoggerContext[name={}] from configurations at {}", ctx.getName(), configLocations); ctx.start(compositeConfiguration);
@Override public LoggerContext getContext(String fqcn, ClassLoader loader, Object externalContext, boolean currentContext, URI configLocation, String name) { final LoggerContext ctx = customLoggerContext; if (externalContext != null && ctx.getExternalContext() == null) { ctx.setExternalContext(externalContext); } if (name != null) { ctx.setName(name); } if (ctx.getState() == LifeCycle.State.INITIALIZED) { if (configLocation != null || name != null) { THREAD_CONTEXT.set(ctx); final Configuration config = ConfigurationFactory.getInstance().getConfiguration(name, configLocation); StatusLogger.getLogger().debug("Starting LoggerContext[name={}] from configuration at {}", ctx.getName(), configLocation); ctx.start(config); THREAD_CONTEXT.remove(); } else { ctx.start(); } } return ctx; } }
/** * Loads the LoggerContext using the ContextSelector. * @param fqcn The fully qualified class name of the caller. * @param loader The ClassLoader to use or null. * @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext. * @param currentContext If true returns the current Context, if false returns the Context appropriate * for the caller if a more appropriate Context can be determined. * @param source The configuration source. * @return The LoggerContext. */ public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext, final boolean currentContext, final ConfigurationSource source) { final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, null); if (externalContext != null && ctx.getExternalContext() == null) { ctx.setExternalContext(externalContext); } if (ctx.getState() == LifeCycle.State.INITIALIZED) { if (source != null) { ContextAnchor.THREAD_CONTEXT.set(ctx); final Configuration config = ConfigurationFactory.getInstance().getConfiguration(ctx, source); LOGGER.debug("Starting LoggerContext[name={}] from configuration {}", ctx.getName(), source); ctx.start(config); ContextAnchor.THREAD_CONTEXT.remove(); } else { ctx.start(); } } return ctx; }
int i = 0; for (final LoggerContext ctx : contexts) { LOGGER.trace("Reregistering context ({}/{}): '{}' {}", ++i, contexts.size(), ctx.getName(), ctx); unregisterLoggerContext(ctx.getName(), mbs); registerStatusLogger(ctx.getName(), mbs, executor); registerContextSelector(ctx.getName(), selector, mbs, executor);
ContextAnchor.THREAD_CONTEXT.set(ctx); final Configuration config = ConfigurationFactory.getInstance().getConfiguration(ctx, name, configLocation); LOGGER.debug("Starting LoggerContext[name={}] from configuration at {}", ctx.getName(), configLocation); ctx.start(config); ContextAnchor.THREAD_CONTEXT.remove();