Skip to content

Commit

Permalink
ongoing work on NewAsyncAppender
Browse files Browse the repository at this point in the history
Signed-off-by: Ceki Gulcu <[email protected]>
  • Loading branch information
ceki committed Dec 2, 2024
1 parent 9197574 commit 70dba2d
Show file tree
Hide file tree
Showing 10 changed files with 490 additions and 111 deletions.
40 changes: 37 additions & 3 deletions src/main/java/org/apache/log4j/NewAsyncAppender.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.AppenderAttachable;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.varia.InterruptUtil;
import sun.rmi.runtime.Log;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

Expand Down Expand Up @@ -59,13 +62,23 @@ public class NewAsyncAppender extends AppenderSkeleton implements AppenderAttach
boolean includeCallerData = false;

public NewAsyncAppender() {
}

@Override
public void activateOptions() {
if (queueSize < 1) {
LogLog.error("Invalid queue size [" + queueSize + "]");
return;
}

blockingQueue = new ArrayBlockingQueue<LoggingEvent>(queueSize);
if (discardingThreshold == UNDEFINED)
discardingThreshold = queueSize / 5;
LogLog.debug("Setting discardingThreshold to " + discardingThreshold);
worker.setDaemon(true);
worker.setName("AsyncSingleAppender-Worker-" + getName());
worker.setName("NewAsyncSingleAppender-Worker-" + getName());
worker.start();

}

protected void append(LoggingEvent event) {
Expand Down Expand Up @@ -100,6 +113,8 @@ protected void preprocess(LoggingEvent eventObject) {
if (includeCallerData) {
eventObject.getLocationInformation();
}
eventObject.getRenderedMessage();
eventObject.getThrowableStrRep();
}

private void put(LoggingEvent eventObject) {
Expand Down Expand Up @@ -131,11 +146,23 @@ public void close() {
return;

closed = true;

worker.interrupt();
InterruptUtil interruptUtil = new InterruptUtil();

try {
interruptUtil.maskInterruptFlag();
worker.join(maxFlushTime);
if(worker.isAlive()) {
LogLog.warn("Max queue flush timeout (" + maxFlushTime + " ms) exceeded. Approximately "
+ blockingQueue.size() + " queued events were possibly discarded.");
} else {
LogLog.debug("Queue flush finished successfully within timeout.");
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
interruptUtil.maskInterruptFlag();
}
}

Expand All @@ -149,10 +176,10 @@ public boolean requiresLayout() {

public void addAppender(Appender newAppender) {
if (appenderCount.compareAndSet(0, 1)) {
LogLog.debug("Attaching appender named [" + newAppender.getName() + "] to AsyncAppender.");
LogLog.debug("Attaching appender named [" + newAppender.getName() + "] to NewAsyncAppender.");
appenders.addAppender(newAppender);
} else {
LogLog.warn("One and only one appender may be attached to AsyncAppender.");
LogLog.warn("One and only one appender may be attached to NewAsyncAppender.");
LogLog.warn("Ignoring additional appender named [" + newAppender.getName() + "]");
}
}
Expand Down Expand Up @@ -205,6 +232,13 @@ public void setMaxFlushTime(int maxFlushTime) {
this.maxFlushTime = maxFlushTime;
}

public void setNeverBlock(boolean neverBlock) {
this.neverBlock = neverBlock;
}

public boolean isNeverBlock() {
return neverBlock;
}

public boolean isIncludeCallerData() {
return includeCallerData;
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/org/apache/log4j/varia/InterruptUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.apache.log4j.varia;

import org.apache.log4j.helpers.LogLog;

public class InterruptUtil {
final boolean previouslyInterrupted;

public InterruptUtil() {
super();
previouslyInterrupted = Thread.currentThread().isInterrupted();
}

public void maskInterruptFlag() {
if (previouslyInterrupted) {
Thread.interrupted();
}
}

public void unmaskInterruptFlag() {
if (previouslyInterrupted) {
try {
Thread.currentThread().interrupt();
} catch (SecurityException se) {
LogLog.error("Failed to interrupt current thread", se);
}
}
}
}
35 changes: 35 additions & 0 deletions src/test/input/xml/newAsyncAppender0.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<log4j:configuration debug="true"
xmlns:log4j='http://jakarta.apache.org/log4j/'>


<appender name="V1" class="org.apache.log4j.VectorAppender"/>

<appender name="ASYNC" class="org.apache.log4j.NewAsyncAppender">
<param name="QueueSize" value="500"/> <!-- Buffer size for events -->
<appender-ref ref="V1"/>
</appender>

<root>
<level value="trace" />
<appender-ref ref="ASYNC" />
</root>

</log4j:configuration>
106 changes: 0 additions & 106 deletions src/test/java/org/apache/log4j/AsyncAppenderTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,25 +100,6 @@ public void test3() {
assertTrue(vectorAppender.isClosed());
}

private static class NullPointerAppender extends AppenderSkeleton {
public NullPointerAppender() {
}

/**
* This method is called by the {@link org.apache.log4j.AppenderSkeleton#doAppend} method.
*/
public void append(org.apache.log4j.spi.LoggingEvent event) {
throw new NullPointerException();
}

public void close() {
}

public boolean requiresLayout() {
return false;
}
}

/**
* Tests that a bad appender will switch async back to sync. See bug 23021
*
Expand Down Expand Up @@ -206,95 +187,8 @@ public void testLocationInfoFalse() {
assertEquals("?:? ", discardStr.substring(0, 4));
}

/**
* Logging request runnable.
*/
private static final class Greeter implements Runnable {
/**
* Logger.
*/
private final Logger logger;

/**
* Repetitions.
*/
private final int repetitions;

/**
* Create new instance.
*
* @param logger logger, may not be null.
* @param repetitions repetitions.
*/
public Greeter(final Logger logger, final int repetitions) {
if (logger == null) {
throw new IllegalArgumentException("logger");
}

this.logger = logger;
this.repetitions = repetitions;
}

/**
* {@inheritDoc}
*/
public void run() {
try {
for (int i = 0; i < repetitions; i++) {
logger.info("Hello, World");
Thread.sleep(1);
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}

/**
* Vector appender that can be explicitly blocked.
*/
private static final class BlockableVectorAppender extends VectorAppender {
/**
* Monitor object used to block appender.
*/
private final Object monitor = new Object();

/**
* Create new instance.
*/
public BlockableVectorAppender() {
super();
}

/**
* {@inheritDoc}
*/
public void append(final LoggingEvent event) {
synchronized (monitor) {
super.append(event);
//
// if fatal, echo messages for testLoggingInDispatcher
//
if (event.getLevel() == Level.FATAL) {
Logger logger = Logger.getLogger(event.getLoggerName());
logger.error(event.getMessage().toString());
logger.warn(event.getMessage().toString());
logger.info(event.getMessage().toString());
logger.debug(event.getMessage().toString());
}
}
}

/**
* Get monitor object.
*
* @return monitor.
*/
public Object getMonitor() {
return monitor;
}

}

/**
* Test that a mutable message object is evaluated before being placed in the async queue. See bug 43559.
Expand Down
49 changes: 49 additions & 0 deletions src/test/java/org/apache/log4j/BlockableVectorAppender.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.apache.log4j;

import org.apache.log4j.spi.LoggingEvent;

/**
* Vector appender that can be explicitly blocked.
*/
final class BlockableVectorAppender extends VectorAppender {
/**
* Monitor object used to block appender.
*/
private final Object monitor = new Object();

/**
* Create new instance.
*/
public BlockableVectorAppender() {
super();
}

/**
* {@inheritDoc}
*/
public void append(final LoggingEvent event) {
synchronized (monitor) {
super.append(event);
//
// if fatal, echo messages for testLoggingInDispatcher
//
if (event.getLevel() == Level.FATAL) {
Logger logger = Logger.getLogger(event.getLoggerName());
logger.error(event.getMessage().toString());
logger.warn(event.getMessage().toString());
logger.info(event.getMessage().toString());
logger.debug(event.getMessage().toString());
}
}
}

/**
* Get monitor object.
*
* @return monitor.
*/
public Object getMonitor() {
return monitor;
}

}
45 changes: 45 additions & 0 deletions src/test/java/org/apache/log4j/Greeter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.apache.log4j;

/**
* Logging request runnable.
*/
final class Greeter implements Runnable {
/**
* Logger.
*/
private final Logger logger;

/**
* Repetitions.
*/
private final int repetitions;

/**
* Create new instance.
*
* @param logger logger, may not be null.
* @param repetitions repetitions.
*/
public Greeter(final Logger logger, final int repetitions) {
if (logger == null) {
throw new IllegalArgumentException("logger");
}

this.logger = logger;
this.repetitions = repetitions;
}

/**
* {@inheritDoc}
*/
public void run() {
try {
for (int i = 0; i < repetitions; i++) {
logger.info("Hello, World");
Thread.sleep(1);
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
Loading

0 comments on commit 70dba2d

Please sign in to comment.