Skip to content

Commit

Permalink
Version 0.9.0 (#1)
Browse files Browse the repository at this point in the history
* Reduction of waiting time in the test

* Change implementation of await mechanism

* Add publish.gradle

* Remove typo

* Add logging

* Fix locking and test solution

* Refactor test function name

* Fix problem that StackFrames contains frames from Backtrace library

* Update README.md

* Add test for multiple await for sending report

* Add test for filtering out backtrace stack frames

* Add option to close backtrace

* Add tests for closing backtrace

* Make lock method private

* Add docs to queue methods

* Reformat code

* Remove debug code

* Make getters public

* Update library version and README.md

* Update Demo app

* Fix Travis test

* Remove one of tests

* Increase memory for Gradle in travis-ci

* Remove possibility to close a closed Backtrace-Thread

* Add JAVA_OPTS to travis.ci

* Comment closing test

* Comment cache section

* Uncomment one of closing test

* Change logging information about MAC address

* Add logging for closing test

* Print thread state

* Remove sending

* Wait 200 ms to see if thread finished

* Increase time

* Remove empty test

* Add logging to run method

* Increase time

* Check option with GC

* Add GRADLE_OPTS to travis.yml

* Add closing to BacktraceClient

* Change checking threads implementation

* Exclude BacktraceClient tests from gradle

* Fix exclude path

* Remove unused code

* Uncomment cache code

* Rename LICENSE file

* Change logging level

* Add constructor for creating BacktraceReport from message and exception

* Remove dependency to log4j12

* Retry request only if timeout or error on server side

* Add parametrized tests for retrying sending requests

* Implement mechanism to gather information from main thread or from all threads

* Add closing Backtrace to tests

* Add missing parameters to docs

* Change logging behavior during generating machine id

* Remove unused imports

* By default gather only single thread

* Set library version as 0.9.0

* Update README.md

Co-authored-by: Bartosz Litwiniuk <[email protected]>
  • Loading branch information
BartoszLitwiniuk and Bartosz Litwiniuk authored Mar 30, 2020
1 parent e628835 commit 1e2056e
Show file tree
Hide file tree
Showing 43 changed files with 1,079 additions and 317 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ before_install:
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/

cache:
directories:
- $HOME/.gradle/caches/
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Backtrace Java Release Notes

## Version 0.9.0 - 23.03.2020
- First release.
File renamed without changes.
24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# This library is currently in early access

# Backtrace Java support

[Backtrace](http://backtrace.io/)'s integration with Java applications which allows customers to capture and report handled and unhandled java exceptions to their Backtrace instance, instantly offering the ability to prioritize and debug software errors.
Expand All @@ -14,7 +16,7 @@
* Gradle
```
dependencies {
implementation 'com.github.backtrace-labs.backtrace-java:backtrace-java:1.0.0-rc.1'
implementation 'com.github.backtrace-labs.backtrace-java:backtrace-java:0.9.0'
}
```

Expand All @@ -23,7 +25,7 @@ dependencies {
<dependency>
<groupId>com.github.backtrace-labs.backtrace-java</groupId>
<artifactId>backtrace-java</artifactId>
<version>1.0.0-rc.1</version>
<version>0.9.0</version>
</dependency>
```

Expand Down Expand Up @@ -95,6 +97,13 @@ The retry limit specifies the number of times `BacktraceClient` will try to send
backtraceConfig.setDatabaseRetryLimit(retryLimit);
```

## Enabling gathering information about all threads
By default library gathering stacktrace and other information only from thread in which caused exception. If you want to change that behavior and gather information about all running threads, execute:

```java
backtraceConfig.setGatherAllThreads(false);
```

## Sending an error report <a name="using-backtrace-sending-report"></a>
Method `BacktraceClient.send` will send an error report to the Backtrace endpoint specified. There `send` method is overloaded, see examples below:

Expand Down Expand Up @@ -129,10 +138,10 @@ client.send(report, new OnServerResponseEvent() {
});
```

Method `await` of BacktraceReport allows to block current thread until report will be sent, as a parameter you can set set the maximum time you want to wait for an answer.
Method `await` of BacktraceClient allows to block current thread until all passed reports will be sent, as a parameter you can optionally set the maximum time you want to wait for an answer.

```java
report.await(5, TimeUnit.SECONDS);
backtraceClient.await(5, TimeUnit.SECONDS);
```

### Other `BacktraceReport` overloads
Expand Down Expand Up @@ -187,6 +196,13 @@ backtraceClient.enableUncaughtExceptionsHandler();

## BacktraceClient <a name="documentation-BacktraceClient"></a>
`BacktraceClient` is a class that allows you to instantiate a client instance that interacts with Backtrace. This class sets up connection to the Backtrace endpoint and manages error reporting behavior. It also prepares error report, gather device attributes and add to queue from which special thread gets report and sends to Backtrace. This class also allows to enable `UncaughtExceptionsHandler` or set custom events.

if you want to safely close all resources used by the this library, execute `close` method. This method will do this after processing last message in queue:

```java
backtraceClient.close()
```

## BacktraceData <a name="documentation-BacktraceData"></a>
**`BacktraceData`** is a serializable class that holds the data to create a diagnostic JSON to be sent to the Backtrace endpoint . You can add additional pre-processors for `BacktraceData` by attaching an event handler to the `BacktraceClient.setBeforeSendEvent(event)` event. `BacktraceData` require `BacktraceReport` and `BacktraceClient` client attributes.

Expand Down
12 changes: 8 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ plugins {
id 'jacoco'
}

apply from: 'publish.gradle'

group = 'com.github.backtrace.io'
version = '1.0.0-SNAPSHOT'
version = '0.9.0'

repositories {
jcenter()
}

test {
exclude 'backtrace/io/BacktraceClientTest.class'
}

dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
implementation 'com.google.code.gson:gson:2.8.6'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:28.0-jre'
implementation group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.29'
implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
testImplementation 'org.powermock:powermock-core:2.0.4'
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION_NAME=1.0.0-rc.1
VERSION_NAME=0.9.0

GROUP=com.github.backtrace-labs.backtrace-java

Expand Down
93 changes: 93 additions & 0 deletions publish.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
apply plugin: 'maven'
apply plugin: 'signing'

def isReleaseBuild() {
return VERSION_NAME.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
: "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}

def getSnapshotRepositoryUrl() {
return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
: "https://oss.sonatype.org/content/repositories/snapshots/"
}

def getRepositoryUsername() {
return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
}

def getRepositoryPassword() {
return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
}

afterEvaluate { project ->
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

pom.groupId = GROUP
pom.artifactId = POM_ARTIFACT_ID
pom.version = VERSION_NAME

repository(url: getReleaseRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}
snapshotRepository(url: getSnapshotRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}

pom.project {
name POM_NAME
packaging POM_PACKAGING
description POM_DESCRIPTION
url POM_URL

scm {
url POM_SCM_URL
connection POM_SCM_CONNECTION
developerConnection POM_SCM_DEV_CONNECTION
}

licenses {
license {
name POM_LICENCE_NAME
url POM_LICENCE_URL
distribution POM_LICENCE_DIST
}
}

developers {
developer {
id POM_DEVELOPER_ID
name POM_DEVELOPER_NAME
}
}
}
}
}
}

signing {
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
}

task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}

artifacts {
archives sourcesJar
archives javadocJar
}
}
9 changes: 2 additions & 7 deletions src/demo/src/app/Demo.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@
import backtrace.io.data.BacktraceReport;

public class Demo {
public static void main(String[] args) {
public static void main(String[] args) throws InterruptedException {
BacktraceReport report = new BacktraceReport("test message");
BacktraceClient client = new BacktraceClient(new BacktraceConfig("<endpoint url>", "<submission token>"));
client.send(report);
try {
report.await(); // wait for sending report
}
catch (Exception e){
e.printStackTrace();
}
client.await();
}
}
40 changes: 23 additions & 17 deletions src/main/java/backtrace/io/Backtrace.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentLinkedQueue;

class Backtrace {
private static final transient Logger LOGGER = LoggerFactory.getLogger(Backtrace.class);
private ConcurrentLinkedQueue<BacktraceMessage> queue;
private BacktraceQueue queue;
private BacktraceDatabase database;
private final BacktraceConfig config;

Expand All @@ -24,28 +22,33 @@ class Backtrace {
* @param config Library configuration
* @param queue Queue containing error reports that should be sent to the Backtrace console
*/
Backtrace(BacktraceConfig config, ConcurrentLinkedQueue<BacktraceMessage> queue) {
Backtrace(BacktraceConfig config, BacktraceQueue queue) {
this.database = BacktraceDatabase.init(config, queue);
this.config = config;
this.queue = queue;
}


/**
* Handles the queue of incoming error reports
*/
void handleBacktraceMessages() {
while (true) {
try {
BacktraceMessage message = queue.poll();
void handleBacktraceMessage() {
try {
if (queue.isEmpty()) {
return;
}

if (message == null) {
continue;
}
BacktraceMessage message = queue.poll();

if (message != null) {
processSingleBacktraceMessage(message);
} catch (Exception e) {
LOGGER.error("Exception during pipeline for message from queue..", e);
}
} catch (Exception e) {
LOGGER.error("Exception during pipeline for message from queue..", e);
}

if (queue.isEmpty()) {
this.queue.unlock();
}
}

Expand All @@ -63,8 +66,9 @@ private void processSingleBacktraceMessage(BacktraceMessage backtraceMessage) {
}

this.database.saveReport(backtraceData);

LOGGER.debug("Message from current report: " + backtraceData.getReport().getMessage());
if (config.getBeforeSendEvent() != null) {
LOGGER.debug("Custom before sending event");
backtraceData = config.getBeforeSendEvent().onEvent(backtraceData);
}

Expand All @@ -74,6 +78,7 @@ private void processSingleBacktraceMessage(BacktraceMessage backtraceMessage) {

OnServerResponseEvent callback = backtraceMessage.getCallback();
if (callback != null) {
LOGGER.debug("Custom callback");
callback.onEvent(result);
}
}
Expand All @@ -86,8 +91,10 @@ private void processSingleBacktraceMessage(BacktraceMessage backtraceMessage) {
*/
private BacktraceResult sendReport(BacktraceData backtraceData) {
if (this.config.getRequestHandler() != null) {
LOGGER.debug("Custom request handler");
return this.config.getRequestHandler().onRequest(backtraceData);
}
LOGGER.debug("Default request handler");
return ApiSender.sendReport(config.getSubmissionUrl(), backtraceData);
}

Expand All @@ -101,17 +108,16 @@ private BacktraceResult sendReport(BacktraceData backtraceData) {
*/
private void handleResponse(BacktraceResult result, BacktraceMessage backtraceMessage) {
if (result.getStatus() == BacktraceResultStatus.Ok) {
backtraceMessage.getBacktraceData().getReport().markAsSent();
if (config.getDatabaseConfig().isDatabaseEnabled()) {
database.removeReport(backtraceMessage.getBacktraceData());
}
return;
}

BacktraceReport report = backtraceMessage.getBacktraceData().getReport();
if (report.getRetryCounter() < config.getDatabaseConfig().getDatabaseRetryLimit()) {
if (result.shouldRetry() && report.getRetryCounter() < config.getDatabaseConfig().getDatabaseRetryLimit()) {
report.incrementRetryCounter();
this.queue.add(backtraceMessage);
this.queue.addWithLock(backtraceMessage);
}
}
}
34 changes: 33 additions & 1 deletion src/main/java/backtrace/io/BacktraceClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class BacktraceClient {
private BacktraceQueueHandler backtrace;
Expand Down Expand Up @@ -90,7 +91,7 @@ public void send(BacktraceReport report) {
* @param callback Event which will be executed after receiving a response
*/
public void send(BacktraceReport report, OnServerResponseEvent callback) {
this.backtrace.send(report, this.customAttributes, callback);
this.backtrace.send(report, this.customAttributes, callback, config.isGatherAllThreads());
}

/**
Expand Down Expand Up @@ -131,6 +132,37 @@ public void send(Exception exception, OnServerResponseEvent callback) {
this.send(new BacktraceReport(exception), callback);
}

/**
* Stop Backtrace Thread and wait until last message will be sent
*
* @throws InterruptedException if the current thread is interrupted while waiting
*/
public void close() throws InterruptedException {
this.backtrace.close();
}

/**
* Wait until all messages in queue will be sent
*
* @throws InterruptedException if the current thread is interrupted while waiting
*/
public void await() throws InterruptedException {
this.backtrace.await();
}

/**
* Wait until all messages in queue will be sent
*
* @param timeout the maximum time to wait
* @param unit the time unit of the {@code timeout} argument
* @return {@code true} if all messages are sent in passed time and {@code false}
* if the waiting time elapsed before all messages has been sent
* @throws InterruptedException if the current thread is interrupted while waiting
*/
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
return this.backtrace.await(timeout, unit);
}

/**
* Enable handling of uncaught exceptions, exceptions will be sent to the Backtrace Console
*/
Expand Down
Loading

0 comments on commit 1e2056e

Please sign in to comment.