static long asyncRemainingCapacity(Logger logger) { if (logger instanceof AsyncLogger) { try { Field f = field(AsyncLogger.class, "loggerDisruptor"); return ((AsyncLoggerDisruptor) f.get(logger)).getDisruptor().getRingBuffer().remainingCapacity(); } catch (Exception ex) { throw new RuntimeException(ex); } } else { LoggerConfig loggerConfig = ((org.apache.logging.log4j.core.Logger) logger).get(); if (loggerConfig instanceof AsyncLoggerConfig) { try { Object delegate = field(AsyncLoggerConfig.class, "delegate").get(loggerConfig); return ((Disruptor) field(AsyncLoggerConfigDisruptor.class, "disruptor").get(delegate)).getRingBuffer().remainingCapacity(); } catch (Exception ex) { throw new RuntimeException(ex); } } else { Appender async = loggerConfig.getAppenders().get("async"); if (async instanceof AsyncAppender) { return ((AsyncAppender) async).getQueueCapacity(); } } } throw new IllegalStateException("Neither Async Loggers nor AsyncAppender are configured"); } private static Field field(Class<?> c, String name) throws NoSuchFieldException {
final Disruptor<RingBufferLogEvent> temp = getDisruptor(); if (temp == null) { LOGGER.trace("[{}] AsyncLoggerDisruptor: disruptor for this context already shut down.", contextName);
/** * Enqueues the specified log event data for logging in a background thread. * <p> * This creates a new varargs Object array for each invocation, but does not store any non-JDK classes in a * {@code ThreadLocal} to avoid memory leaks in web applications (see LOG4J2-1172). * * @param fqcn fully qualified name of the caller * @param level level at which the caller wants to log the message * @param marker message marker * @param message the log message * @param thrown a {@code Throwable} or {@code null} */ private void logWithVarargTranslator(final String fqcn, final Level level, final Marker marker, final Message message, final Throwable thrown) { // Implementation note: candidate for optimization: exceeds 35 bytecodes. final Disruptor<RingBufferLogEvent> disruptor = loggerDisruptor.getDisruptor(); if (disruptor == null) { LOGGER.error("Ignoring log event after Log4j has been shut down."); return; } // if the Message instance is reused, there is no point in freezing its message here if (!isReused(message)) { InternalAsyncUtil.makeMessageImmutable(message); } // calls the translateTo method on this AsyncLogger disruptor.getRingBuffer().publishEvent(this, this, calcLocationIfRequested(fqcn), fqcn, level, marker, message, thrown); }