Created
June 2, 2011 05:13
-
-
Save actsasflinn/1003970 to your computer and use it in GitHub Desktop.
Web Service Log4j Appender, loosely based on SMTPAppender
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package client; | |
import org.apache.log4j.AppenderSkeleton; | |
import org.apache.log4j.Layout; | |
import org.apache.log4j.Level; | |
import org.apache.log4j.helpers.CyclicBuffer; | |
import org.apache.log4j.helpers.LogLog; | |
import org.apache.log4j.helpers.OptionConverter; | |
import org.apache.log4j.spi.ErrorCode; | |
import org.apache.log4j.spi.LoggingEvent; | |
import org.apache.log4j.spi.OptionHandler; | |
import org.apache.log4j.spi.TriggeringEventEvaluator; | |
/** | |
* | |
* @author fmueller | |
*/ | |
public class WSAppender extends AppenderSkeleton { | |
private int bufferSize = 512; | |
private boolean locationInfo = false; | |
private boolean sendOnClose = true; | |
protected CyclicBuffer cb = new CyclicBuffer(bufferSize); | |
protected TriggeringEventEvaluator evaluator; | |
/** | |
The default constructor will instantiate the appender with a | |
{@link TriggeringEventEvaluator} that will trigger on events with | |
level ERROR or higher.*/ | |
public | |
WSAppender() { | |
this(new DefaultEvaluator()); | |
} | |
/** | |
Use <code>evaluator</code> passed as parameter as the {@link | |
TriggeringEventEvaluator} for this WSAppender. */ | |
public | |
WSAppender(TriggeringEventEvaluator evaluator) { | |
this.evaluator = evaluator; | |
} | |
/** | |
Activate the specified options, such as the smtp host, the | |
recipient, from, etc. */ | |
public | |
void activateOptions() { | |
if (evaluator instanceof OptionHandler) { | |
((OptionHandler) evaluator).activateOptions(); | |
} | |
} | |
/** | |
Perform WSAppender specific appending actions, mainly adding | |
the event to a cyclic buffer and checking if the event triggers | |
an e-mail to be sent. */ | |
public | |
void append(LoggingEvent event) { | |
if(!checkEntryConditions()) { | |
return; | |
} | |
event.getThreadName(); | |
event.getNDC(); | |
event.getMDCCopy(); | |
if(locationInfo) { | |
event.getLocationInformation(); | |
} | |
event.getRenderedMessage(); | |
event.getThrowableStrRep(); | |
cb.add(event); | |
if(evaluator.isTriggeringEvent(event)) { | |
sendBuffer(); | |
} | |
} | |
/** | |
The <code>WSAppender</code> requires a {@link | |
org.apache.log4j.Layout layout}. */ | |
public | |
boolean requiresLayout() { | |
return true; | |
} | |
/** | |
This method determines if there is a sense in attempting to append. | |
<p>It checks whether there is a set output target and also if | |
there is a set layout. If these checks fail, then the boolean | |
value <code>false</code> is returned. */ | |
protected | |
boolean checkEntryConditions() { | |
if(this.evaluator == null) { | |
errorHandler.error("No TriggeringEventEvaluator is set for appender ["+ | |
name+"]."); | |
return false; | |
} | |
if(this.layout == null) { | |
errorHandler.error("No layout set for appender named ["+name+"]."); | |
return false; | |
} | |
return true; | |
} | |
synchronized | |
public | |
void close() { | |
this.closed = true; | |
if (sendOnClose && cb.length() > 0) { | |
sendBuffer(); | |
} | |
} | |
/** | |
* Layout body of email message. | |
* @since 1.2.16 | |
*/ | |
protected String formatBody() { | |
// Note: this code already owns the monitor for this | |
// appender. This frees us from needing to synchronize on 'cb'. | |
StringBuffer sbuf = new StringBuffer(); | |
String t = layout.getHeader(); | |
if(t != null) | |
sbuf.append(t); | |
int len = cb.length(); | |
for(int i = 0; i < len; i++) { | |
//sbuf.append(MimeUtility.encodeText(layout.format(cb.get()))); | |
LoggingEvent event = cb.get(); | |
sbuf.append(layout.format(event)); | |
if(layout.ignoresThrowable()) { | |
String[] s = event.getThrowableStrRep(); | |
if (s != null) { | |
for(int j = 0; j < s.length; j++) { | |
sbuf.append(s[j]); | |
sbuf.append(Layout.LINE_SEP); | |
} | |
} | |
} | |
} | |
t = layout.getFooter(); | |
if(t != null) { | |
sbuf.append(t); | |
} | |
return sbuf.toString(); | |
} | |
/** | |
Send the contents of the cyclic buffer as an e-mail message. | |
*/ | |
protected | |
void sendBuffer() { | |
try { | |
client.Hello_Service service = | |
new client.Hello_Service(); | |
client.Hello port = service.getHelloPort(); | |
// TODO initialize WS operation arguments here | |
String arg0 = formatBody(); | |
// TODO process result here | |
String result = port.hello(arg0); | |
//System.out.println("Result = "+result); | |
} catch(RuntimeException e) { | |
LogLog.error("Error occured.", e); | |
} | |
} | |
/** | |
The <b>BufferSize</b> option takes a positive integer | |
representing the maximum number of logging events to collect in a | |
cyclic buffer. When the <code>BufferSize</code> is reached, | |
oldest events are deleted as new events are added to the | |
buffer. By default the size of the cyclic buffer is 512 events. | |
*/ | |
public | |
void setBufferSize(int bufferSize) { | |
this.bufferSize = bufferSize; | |
cb.resize(bufferSize); | |
} | |
/** | |
Returns value of the <b>BufferSize</b> option. | |
*/ | |
public | |
int getBufferSize() { | |
return bufferSize; | |
} | |
/** | |
The <b>EvaluatorClass</b> option takes a string value | |
representing the name of the class implementing the {@link | |
TriggeringEventEvaluator} interface. A corresponding object will | |
be instantiated and assigned as the triggering event evaluator | |
for the WSAppender. | |
*/ | |
public | |
void setEvaluatorClass(String value) { | |
evaluator = (TriggeringEventEvaluator) | |
OptionConverter.instantiateByClassName(value, | |
TriggeringEventEvaluator.class, | |
evaluator); | |
} | |
/** | |
* Sets triggering evaluator. | |
* @param trigger triggering event evaluator. | |
* @since 1.2.15 | |
*/ | |
public final void setEvaluator(final TriggeringEventEvaluator trigger) { | |
if (trigger == null) { | |
throw new NullPointerException("trigger"); | |
} | |
this.evaluator = trigger; | |
} | |
/** | |
* Get triggering evaluator. | |
* @return triggering event evaluator. | |
* @since 1.2.15 | |
*/ | |
public final TriggeringEventEvaluator getEvaluator() { | |
return evaluator; | |
} | |
/** | |
The <b>LocationInfo</b> option takes a boolean value. By | |
default, it is set to false which means there will be no effort | |
to extract the location information related to the event. As a | |
result, the layout that formats the events as they are sent out | |
in an e-mail is likely to place the wrong location information | |
(if present in the format). | |
<p>Location information extraction is comparatively very slow and | |
should be avoided unless performance is not a concern. | |
*/ | |
public | |
void setLocationInfo(boolean locationInfo) { | |
this.locationInfo = locationInfo; | |
} | |
/** | |
Returns value of the <b>LocationInfo</b> option. | |
*/ | |
public | |
boolean getLocationInfo() { | |
return locationInfo; | |
} | |
/** | |
Returns value of the <b>EvaluatorClass</b> option. | |
*/ | |
public | |
String getEvaluatorClass() { | |
return evaluator == null ? null : evaluator.getClass().getName(); | |
} | |
/** | |
* Set sendOnClose. | |
* | |
* @param val if true all buffered logging events will be sent when appender is closed. | |
* @since 1.2.16 | |
*/ | |
public final void setSendOnClose(final boolean val) { | |
sendOnClose = val; | |
} | |
} | |
class DefaultEvaluator implements TriggeringEventEvaluator { | |
/** | |
Is this <code>event</code> the e-mail triggering event? | |
<p>This method returns <code>true</code>, if the event level | |
has ERROR level or higher. Otherwise it returns | |
<code>false</code>. */ | |
public | |
boolean isTriggeringEvent(LoggingEvent event) { | |
return event.getLevel().isGreaterOrEqual(Level.ERROR); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi dude!
I need to send all the error msg from log4j 1.2 to a web service :(
Could you help me giving me some clues about how this work?