diff --git a/.gitignore b/.gitignore
index b320ea0..ee1b0da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*/target/**
*/idea/**
.idea
-*.i??
\ No newline at end of file
+*.i??
+out
\ No newline at end of file
diff --git a/honeybadger-client/pom.xml b/honeybadger-client/pom.xml
index f018256..d7dce70 100644
--- a/honeybadger-client/pom.xml
+++ b/honeybadger-client/pom.xml
@@ -5,7 +5,7 @@
honeybadger-java
com.workable.honeybadger
- 1.5.1
+ 1.5.2
4.0.0
diff --git a/honeybadger-log4j-appender/pom.xml b/honeybadger-log4j-appender/pom.xml
index 7c33bd3..f38c4ad 100644
--- a/honeybadger-log4j-appender/pom.xml
+++ b/honeybadger-log4j-appender/pom.xml
@@ -5,7 +5,7 @@
honeybadger-java
com.workable.honeybadger
- 1.5.1
+ 1.5.2
4.0.0
honeybadger-log4j-appender
diff --git a/honeybadger-log4j2-appender/README.md b/honeybadger-log4j2-appender/README.md
new file mode 100644
index 0000000..5ba7634
--- /dev/null
+++ b/honeybadger-log4j2-appender/README.md
@@ -0,0 +1,70 @@
+# honeybadger-log4j-appender
+[log4j2](https://logging.apache.org/log4j/2.5/) support for honeybadger.
+It provides an [`Appender`](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Appender.html)
+for log4j to send the logged events to honeybadger.
+
+## Usage
+### Configuration
+In the `log4j2.xml` file configure an appender named `HoneybadgerAppender`:
+
+```properties
+
+
+
+
+
+
+
+```
+
+## Additional Options
+
+### Async mode
+The error dispatching to honebadger.io is performed asynchronously via http in order to avoid performance impact.
+
+To disable the async mode simply set the `async` option to `false`:
+
+```properties
+log4j.appender.HoneybadgerAppender.async=false
+```
+
+### Max Threads
+By default the thread pool used for async dispatching contains one thread per
+processor available to the JVM.
+
+It's possible to manually set the number of threads (for example if you want
+only one thread) with the option `maxThreads`:
+
+```properties
+log4j.appender.HoneybadgerAppender.maxThreads=1
+```
+
+### Queue Size
+The default queue used to store the not yet processed events doesn't have a
+limit.
+Depending on the environment (if the memory is sparse) it is important to be
+able to control the size of that queue to avoid memory issues.
+
+It is possible to set a maximum with the option `queuesize`:
+
+```properties
+log4j.appender.HoneybadgerAppender.queueSize=50000
+```
+
+### Thread Priority
+As in most cases sending error to Honebadger isn't as important as an application
+running smoothly, the threads have a
+[minimal priority](http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#MIN_PRIORITY).
+
+It is possible to customise this value to increase the priority of those threads
+with the option `priority`:
+
+```properties
+log4j.appender.HoneybadgerAppender.priority=1
+```
+
+### Additional data and information
+It's possible to add extra details to events captured by the Log4j module
+thanks to [the MDC](https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html)
+systems provided by Log4j are usable, allowing to attach extras information to the event.
+
diff --git a/honeybadger-log4j2-appender/pom.xml b/honeybadger-log4j2-appender/pom.xml
new file mode 100644
index 0000000..da27128
--- /dev/null
+++ b/honeybadger-log4j2-appender/pom.xml
@@ -0,0 +1,49 @@
+
+
+
+ honeybadger-java
+ com.workable.honeybadger
+ 1.5.2
+
+ 4.0.0
+ honeybadger-log4j2-appender
+ Honeybadger :: Java :: Log4j2 Appender
+ Log4j2 appender allowing to send logs to Honeybadger.
+
+
+ 2.5
+
+
+
+
+ com.workable.honeybadger
+ honeybadger-client
+ ${project.version}
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-core
+ ${log4j.version}
+
+
+ org.slf4j
+ slf4j-log4j12
+ 1.7.7
+
+
+
+
+ junit
+ junit
+ 4.11
+
+
+
+
\ No newline at end of file
diff --git a/honeybadger-log4j2-appender/src/main/java/META-INF/MANIFEST.MF b/honeybadger-log4j2-appender/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..be31cb1
--- /dev/null
+++ b/honeybadger-log4j2-appender/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.workable.honeybadger.log4j2.HoneybadgerAppender
+
diff --git a/honeybadger-log4j2-appender/src/main/java/com/workable/honeybadger/log4j2/HoneybadgerAppender.java b/honeybadger-log4j2-appender/src/main/java/com/workable/honeybadger/log4j2/HoneybadgerAppender.java
new file mode 100644
index 0000000..55d422d
--- /dev/null
+++ b/honeybadger-log4j2-appender/src/main/java/com/workable/honeybadger/log4j2/HoneybadgerAppender.java
@@ -0,0 +1,85 @@
+package com.workable.honeybadger.log4j2;
+
+import com.workable.honeybadger.*;
+import com.workable.honeybadger.Error;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.appender.AppenderLoggingException;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+
+import java.io.Serializable;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Appender for log4j responsible to send events carrying exceptions to Honeybadger
+ */
+@Plugin(name="HoneybadgerAppender", category="Core", elementType="appender", printObject=true)
+public class HoneybadgerAppender extends AbstractAppender {
+
+ private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
+ private final Lock readLock = rwLock.readLock();
+
+ /**
+ * The client to send errors to Honeybadger
+ */
+ private static HoneybadgerClient client;
+
+ protected HoneybadgerAppender(HoneybadgerClient client, String name, Filter filter,
+ Layout extends Serializable> layout, final boolean ignoreExceptions) {
+ super(name, filter, layout, ignoreExceptions);
+ this.client = client;
+ }
+
+ @Override
+ public void append(LogEvent event) {
+ readLock.lock();
+ try {
+ Error error = new Error(getLayout().toByteArray(event).toString(), event.getThrown());
+ error.setReporter(event.getLoggerName());
+ client.reportError(error);
+ } catch (Exception ex) {
+ if (!ignoreExceptions()) {
+ throw new AppenderLoggingException(ex);
+ }
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @PluginFactory
+ public static HoneybadgerAppender createAppender(
+ @PluginAttribute("name") String name,
+ @PluginElement("Layout") Layout extends Serializable> layout,
+ @PluginElement("Filter") final Filter filter,
+ @PluginAttribute("apiKey") String apiKey,
+ @PluginAttribute("ignoredSystemProperties") String ignoredSystemProperties,
+ @PluginAttribute("ignoredExceptions") String ignoredExceptions,
+ @PluginAttribute("async") boolean async,
+ @PluginAttribute("maxThreads") int maxThreads,
+ @PluginAttribute("priority") int priority,
+ @PluginAttribute("queueSize") int queueSize) {
+ if (name == null) {
+ LOGGER.error("No name provided for HoneybadgerAppender");
+ return null;
+ }
+ if (layout == null) {
+ layout = PatternLayout.createDefaultLayout();
+ }
+ if (client == null) {
+ client = new HoneybadgerClient(apiKey, ignoredSystemProperties, ignoredExceptions);
+ client.setAsync(async);
+ client.setMaxThreads(maxThreads);
+ client.setPriority(priority);
+ client.setQueueSize(queueSize);
+ }
+ return new HoneybadgerAppender(client, name, filter, layout, true);
+ }
+}
diff --git a/honeybadger-log4j2-appender/src/test/java/AppenderIT.java b/honeybadger-log4j2-appender/src/test/java/AppenderIT.java
new file mode 100644
index 0000000..3f2be46
--- /dev/null
+++ b/honeybadger-log4j2-appender/src/test/java/AppenderIT.java
@@ -0,0 +1,76 @@
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.Test;
+
+/**
+ * Created by kostas on 12/4/14.
+ */
+public class AppenderIT {
+
+ public static final Logger log = LogManager.getLogger(AppenderIT.class);
+
+ @Test
+ public void shouldLogErrorFromBuggy() throws Exception {
+ Buggy buggy = new Buggy();
+ buggy.fail();
+ }
+
+
+ @Test
+ public void testNestedException() throws Exception {
+
+ try {
+ Delegate delegate = new Delegate();
+ delegate.run();
+ }
+ catch(Exception e){
+ log.error("Exception while running", e);
+ }
+
+
+ }
+
+ @Test
+ public void shouldLogError2() throws Exception {
+
+ for (int i = 0; i < 25; i++){
+ log.error("This is an error" + i, new IllegalStateException("Oups" + i));
+ }
+ }
+
+// @Test
+// public void shouldLogErrorWithMDC() throws Exception {
+// MDC.put("MDC Entry", "MDC Value");
+//
+// log.error("This is an error with MDC", new UnsupportedOperationException("Something went wrong...", new NullPointerException()));
+// }
+
+ private class Buggy {
+
+ public final Logger log = LogManager.getLogger(Buggy.class);
+
+ public void fail(){
+ log.error("Error from buggy", new IllegalStateException("From buggy"));
+ }
+ }
+
+ private class Delegate{
+
+ public void run(){
+ try {
+ Failer failer = new Failer();
+ failer.fail();
+ }
+ catch (Exception e){
+ throw new IllegalStateException("Error while running", e);
+ }
+ }
+ }
+ private class Failer {
+
+ public void fail(){
+ throw new NullPointerException("Point to null");
+ }
+ }
+
+}
diff --git a/honeybadger-log4j2-appender/src/test/resources/log4j2.xml b/honeybadger-log4j2-appender/src/test/resources/log4j2.xml
new file mode 100644
index 0000000..9b431d7
--- /dev/null
+++ b/honeybadger-log4j2-appender/src/test/resources/log4j2.xml
@@ -0,0 +1,20 @@
+
+
+
+ [%-5p] %c - %m%n%throwable{none}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/honeybadger-logback-appender/pom.xml b/honeybadger-logback-appender/pom.xml
index d8ad573..326a119 100644
--- a/honeybadger-logback-appender/pom.xml
+++ b/honeybadger-logback-appender/pom.xml
@@ -5,7 +5,7 @@
honeybadger-java
com.workable.honeybadger
- 1.5.1
+ 1.5.2
4.0.0
diff --git a/pom.xml b/pom.xml
index 8f1ca99..43b1577 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,13 +5,14 @@
4.0.0
com.workable.honeybadger
honeybadger-java
- 1.5.1
+ 1.5.2
Honeybadger :: Java
Honeybadger Java parent project.
https://github.com/Workable/honeybadger-java/wiki
honeybadger-client
honeybadger-log4j-appender
+ honeybadger-log4j2-appender
honeybadger-logback-appender
pom