Skip to content

Commit 70dba2d

Browse files
committed
ongoing work on NewAsyncAppender
Signed-off-by: Ceki Gulcu <[email protected]>
1 parent 9197574 commit 70dba2d

File tree

10 files changed

+490
-111
lines changed

10 files changed

+490
-111
lines changed

src/main/java/org/apache/log4j/NewAsyncAppender.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@
2020
import org.apache.log4j.helpers.LogLog;
2121
import org.apache.log4j.spi.AppenderAttachable;
2222
import org.apache.log4j.spi.LoggingEvent;
23+
import org.apache.log4j.varia.InterruptUtil;
24+
import sun.rmi.runtime.Log;
2325

2426
import java.util.ArrayList;
2527
import java.util.Enumeration;
2628
import java.util.List;
29+
import java.util.concurrent.ArrayBlockingQueue;
2730
import java.util.concurrent.BlockingQueue;
2831
import java.util.concurrent.atomic.AtomicInteger;
2932

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

6164
public NewAsyncAppender() {
65+
}
66+
67+
@Override
68+
public void activateOptions() {
6269
if (queueSize < 1) {
6370
LogLog.error("Invalid queue size [" + queueSize + "]");
6471
return;
6572
}
73+
74+
blockingQueue = new ArrayBlockingQueue<LoggingEvent>(queueSize);
75+
if (discardingThreshold == UNDEFINED)
76+
discardingThreshold = queueSize / 5;
77+
LogLog.debug("Setting discardingThreshold to " + discardingThreshold);
6678
worker.setDaemon(true);
67-
worker.setName("AsyncSingleAppender-Worker-" + getName());
79+
worker.setName("NewAsyncSingleAppender-Worker-" + getName());
6880
worker.start();
81+
6982
}
7083

7184
protected void append(LoggingEvent event) {
@@ -100,6 +113,8 @@ protected void preprocess(LoggingEvent eventObject) {
100113
if (includeCallerData) {
101114
eventObject.getLocationInformation();
102115
}
116+
eventObject.getRenderedMessage();
117+
eventObject.getThrowableStrRep();
103118
}
104119

105120
private void put(LoggingEvent eventObject) {
@@ -131,11 +146,23 @@ public void close() {
131146
return;
132147

133148
closed = true;
149+
134150
worker.interrupt();
151+
InterruptUtil interruptUtil = new InterruptUtil();
152+
135153
try {
154+
interruptUtil.maskInterruptFlag();
136155
worker.join(maxFlushTime);
156+
if(worker.isAlive()) {
157+
LogLog.warn("Max queue flush timeout (" + maxFlushTime + " ms) exceeded. Approximately "
158+
+ blockingQueue.size() + " queued events were possibly discarded.");
159+
} else {
160+
LogLog.debug("Queue flush finished successfully within timeout.");
161+
}
137162
} catch (InterruptedException e) {
138163
throw new RuntimeException(e);
164+
} finally {
165+
interruptUtil.maskInterruptFlag();
139166
}
140167
}
141168

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

150177
public void addAppender(Appender newAppender) {
151178
if (appenderCount.compareAndSet(0, 1)) {
152-
LogLog.debug("Attaching appender named [" + newAppender.getName() + "] to AsyncAppender.");
179+
LogLog.debug("Attaching appender named [" + newAppender.getName() + "] to NewAsyncAppender.");
153180
appenders.addAppender(newAppender);
154181
} else {
155-
LogLog.warn("One and only one appender may be attached to AsyncAppender.");
182+
LogLog.warn("One and only one appender may be attached to NewAsyncAppender.");
156183
LogLog.warn("Ignoring additional appender named [" + newAppender.getName() + "]");
157184
}
158185
}
@@ -205,6 +232,13 @@ public void setMaxFlushTime(int maxFlushTime) {
205232
this.maxFlushTime = maxFlushTime;
206233
}
207234

235+
public void setNeverBlock(boolean neverBlock) {
236+
this.neverBlock = neverBlock;
237+
}
238+
239+
public boolean isNeverBlock() {
240+
return neverBlock;
241+
}
208242

209243
public boolean isIncludeCallerData() {
210244
return includeCallerData;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.apache.log4j.varia;
2+
3+
import org.apache.log4j.helpers.LogLog;
4+
5+
public class InterruptUtil {
6+
final boolean previouslyInterrupted;
7+
8+
public InterruptUtil() {
9+
super();
10+
previouslyInterrupted = Thread.currentThread().isInterrupted();
11+
}
12+
13+
public void maskInterruptFlag() {
14+
if (previouslyInterrupted) {
15+
Thread.interrupted();
16+
}
17+
}
18+
19+
public void unmaskInterruptFlag() {
20+
if (previouslyInterrupted) {
21+
try {
22+
Thread.currentThread().interrupt();
23+
} catch (SecurityException se) {
24+
LogLog.error("Failed to interrupt current thread", se);
25+
}
26+
}
27+
}
28+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
3+
<!--
4+
Licensed to the Apache Software Foundation (ASF) under one or more
5+
contributor license agreements. See the NOTICE file distributed with
6+
this work for additional information regarding copyright ownership.
7+
The ASF licenses this file to You under the Apache License, Version 2.0
8+
(the "License"); you may not use this file except in compliance with
9+
the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
-->
19+
<log4j:configuration debug="true"
20+
xmlns:log4j='http://jakarta.apache.org/log4j/'>
21+
22+
23+
<appender name="V1" class="org.apache.log4j.VectorAppender"/>
24+
25+
<appender name="ASYNC" class="org.apache.log4j.NewAsyncAppender">
26+
<param name="QueueSize" value="500"/> <!-- Buffer size for events -->
27+
<appender-ref ref="V1"/>
28+
</appender>
29+
30+
<root>
31+
<level value="trace" />
32+
<appender-ref ref="ASYNC" />
33+
</root>
34+
35+
</log4j:configuration>

src/test/java/org/apache/log4j/AsyncAppenderTestCase.java

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -100,25 +100,6 @@ public void test3() {
100100
assertTrue(vectorAppender.isClosed());
101101
}
102102

103-
private static class NullPointerAppender extends AppenderSkeleton {
104-
public NullPointerAppender() {
105-
}
106-
107-
/**
108-
* This method is called by the {@link org.apache.log4j.AppenderSkeleton#doAppend} method.
109-
*/
110-
public void append(org.apache.log4j.spi.LoggingEvent event) {
111-
throw new NullPointerException();
112-
}
113-
114-
public void close() {
115-
}
116-
117-
public boolean requiresLayout() {
118-
return false;
119-
}
120-
}
121-
122103
/**
123104
* Tests that a bad appender will switch async back to sync. See bug 23021
124105
*
@@ -206,95 +187,8 @@ public void testLocationInfoFalse() {
206187
assertEquals("?:? ", discardStr.substring(0, 4));
207188
}
208189

209-
/**
210-
* Logging request runnable.
211-
*/
212-
private static final class Greeter implements Runnable {
213-
/**
214-
* Logger.
215-
*/
216-
private final Logger logger;
217190

218-
/**
219-
* Repetitions.
220-
*/
221-
private final int repetitions;
222-
223-
/**
224-
* Create new instance.
225-
*
226-
* @param logger logger, may not be null.
227-
* @param repetitions repetitions.
228-
*/
229-
public Greeter(final Logger logger, final int repetitions) {
230-
if (logger == null) {
231-
throw new IllegalArgumentException("logger");
232-
}
233-
234-
this.logger = logger;
235-
this.repetitions = repetitions;
236-
}
237191

238-
/**
239-
* {@inheritDoc}
240-
*/
241-
public void run() {
242-
try {
243-
for (int i = 0; i < repetitions; i++) {
244-
logger.info("Hello, World");
245-
Thread.sleep(1);
246-
}
247-
} catch (InterruptedException ex) {
248-
Thread.currentThread().interrupt();
249-
}
250-
}
251-
}
252-
253-
/**
254-
* Vector appender that can be explicitly blocked.
255-
*/
256-
private static final class BlockableVectorAppender extends VectorAppender {
257-
/**
258-
* Monitor object used to block appender.
259-
*/
260-
private final Object monitor = new Object();
261-
262-
/**
263-
* Create new instance.
264-
*/
265-
public BlockableVectorAppender() {
266-
super();
267-
}
268-
269-
/**
270-
* {@inheritDoc}
271-
*/
272-
public void append(final LoggingEvent event) {
273-
synchronized (monitor) {
274-
super.append(event);
275-
//
276-
// if fatal, echo messages for testLoggingInDispatcher
277-
//
278-
if (event.getLevel() == Level.FATAL) {
279-
Logger logger = Logger.getLogger(event.getLoggerName());
280-
logger.error(event.getMessage().toString());
281-
logger.warn(event.getMessage().toString());
282-
logger.info(event.getMessage().toString());
283-
logger.debug(event.getMessage().toString());
284-
}
285-
}
286-
}
287-
288-
/**
289-
* Get monitor object.
290-
*
291-
* @return monitor.
292-
*/
293-
public Object getMonitor() {
294-
return monitor;
295-
}
296-
297-
}
298192

299193
/**
300194
* Test that a mutable message object is evaluated before being placed in the async queue. See bug 43559.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.apache.log4j;
2+
3+
import org.apache.log4j.spi.LoggingEvent;
4+
5+
/**
6+
* Vector appender that can be explicitly blocked.
7+
*/
8+
final class BlockableVectorAppender extends VectorAppender {
9+
/**
10+
* Monitor object used to block appender.
11+
*/
12+
private final Object monitor = new Object();
13+
14+
/**
15+
* Create new instance.
16+
*/
17+
public BlockableVectorAppender() {
18+
super();
19+
}
20+
21+
/**
22+
* {@inheritDoc}
23+
*/
24+
public void append(final LoggingEvent event) {
25+
synchronized (monitor) {
26+
super.append(event);
27+
//
28+
// if fatal, echo messages for testLoggingInDispatcher
29+
//
30+
if (event.getLevel() == Level.FATAL) {
31+
Logger logger = Logger.getLogger(event.getLoggerName());
32+
logger.error(event.getMessage().toString());
33+
logger.warn(event.getMessage().toString());
34+
logger.info(event.getMessage().toString());
35+
logger.debug(event.getMessage().toString());
36+
}
37+
}
38+
}
39+
40+
/**
41+
* Get monitor object.
42+
*
43+
* @return monitor.
44+
*/
45+
public Object getMonitor() {
46+
return monitor;
47+
}
48+
49+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.apache.log4j;
2+
3+
/**
4+
* Logging request runnable.
5+
*/
6+
final class Greeter implements Runnable {
7+
/**
8+
* Logger.
9+
*/
10+
private final Logger logger;
11+
12+
/**
13+
* Repetitions.
14+
*/
15+
private final int repetitions;
16+
17+
/**
18+
* Create new instance.
19+
*
20+
* @param logger logger, may not be null.
21+
* @param repetitions repetitions.
22+
*/
23+
public Greeter(final Logger logger, final int repetitions) {
24+
if (logger == null) {
25+
throw new IllegalArgumentException("logger");
26+
}
27+
28+
this.logger = logger;
29+
this.repetitions = repetitions;
30+
}
31+
32+
/**
33+
* {@inheritDoc}
34+
*/
35+
public void run() {
36+
try {
37+
for (int i = 0; i < repetitions; i++) {
38+
logger.info("Hello, World");
39+
Thread.sleep(1);
40+
}
41+
} catch (InterruptedException ex) {
42+
Thread.currentThread().interrupt();
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)