Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*/target/**
*/idea/**
.idea
*.i??
*.i??
out
2 changes: 1 addition & 1 deletion honeybadger-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>honeybadger-java</artifactId>
<groupId>com.workable.honeybadger</groupId>
<version>1.5.1</version>
<version>1.5.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion honeybadger-log4j-appender/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>honeybadger-java</artifactId>
<groupId>com.workable.honeybadger</groupId>
<version>1.5.1</version>
<version>1.5.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>honeybadger-log4j-appender</artifactId>
Expand Down
70 changes: 70 additions & 0 deletions honeybadger-log4j2-appender/README.md
Original file line number Diff line number Diff line change
@@ -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
<HoneyBadgerAppender class="com.workable.honeybadger.log4j.HoneybadgerAppender">
<param name="Threshold" value="ERROR" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%-5p] %c - %m%n%throwable{none}" />
</layout>
<param name="apiKey" value="${honeybadgerKey}" />
</HoneyBadgerAppender>
```

## 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.

49 changes: 49 additions & 0 deletions honeybadger-log4j2-appender/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>honeybadger-java</artifactId>
<groupId>com.workable.honeybadger</groupId>
<version>1.5.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>honeybadger-log4j2-appender</artifactId>
<name>Honeybadger :: Java :: Log4j2 Appender</name>
<description>Log4j2 appender allowing to send logs to Honeybadger.</description>

<properties>
<log4j.version>2.5</log4j.version>
</properties>

<dependencies>
<dependency>
<groupId>com.workable.honeybadger</groupId>
<artifactId>honeybadger-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>

<!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: com.workable.honeybadger.log4j2.HoneybadgerAppender

Original file line number Diff line number Diff line change
@@ -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);
}
}
76 changes: 76 additions & 0 deletions honeybadger-log4j2-appender/src/test/java/AppenderIT.java
Original file line number Diff line number Diff line change
@@ -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");
}
}

}
20 changes: 20 additions & 0 deletions honeybadger-log4j2-appender/src/test/resources/log4j2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" name="ripatron-config">
<Properties>
<Property name="PATTERN">[%-5p] %c - %m%n%throwable{none}</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="${PATTERN}"/>
</Console>
<HoneyBadgerAppender name="honeybadger" apiKey="2b9b6c46">
<PatternLayout pattern="${PATTERN}"/>
</HoneyBadgerAppender>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="console" level="DEBUG"/>
<AppenderRef ref="honeybadger" level="ERROR"/>
</Root>
</Loggers>
</Configuration>
2 changes: 1 addition & 1 deletion honeybadger-logback-appender/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>honeybadger-java</artifactId>
<groupId>com.workable.honeybadger</groupId>
<version>1.5.1</version>
<version>1.5.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.workable.honeybadger</groupId>
<artifactId>honeybadger-java</artifactId>
<version>1.5.1</version>
<version>1.5.2</version>
<name>Honeybadger :: Java</name>
<description>Honeybadger Java parent project.</description>
<url>https://github.com/Workable/honeybadger-java/wiki</url>
<modules>
<module>honeybadger-client</module>
<module>honeybadger-log4j-appender</module>
<module>honeybadger-log4j2-appender</module>
<module>honeybadger-logback-appender</module>
</modules>
<packaging>pom</packaging>
Expand Down