In order to quickly reproduce and fix errors, it is often helpful to send additional application-specific diagnostic data to your BugSnag dashboard to provide rich context that is also available for searching and filtering.
You can also amend the events captured by BugSnag to adjust the information shown on the dashboard and even choose not to send the event at all.
If you’d like to add diagnostic data to events, or adjust event data conditionally, you can use an OnErrorCallback, which will be run before each error event is sent.
Callbacks are usually configured on the Bugsnag client (for example during application startup) and give you access to a BugsnagEvent object that you can inspect and modify before it is delivered to BugSnag.
bugsnag.addOnError((event) -> {
event.addMetadata("account", "name", "Acme Co.");
event.addMetadata("account", "paying_customer", true);
// Return false to prevent this event from being sent
return true;
});
Or without using lambda syntax:
bugsnag.addOnError(new OnErrorCallback() {
@Override
public boolean onError(BugsnagEvent event) {
event.addMetadata("account", "name", "Acme Co.");
event.addMetadata("account", "paying_customer", true);
// Return false to prevent this event from being sent
return true;
}
});
The BugsnagEvent methods support chaining, for example:
event.setSeverity(Severity.ERROR)
.setContext("Processing");
BugSnag will automatically add diagnostic information on the JVM runtime, O/S, and locale. For javax.servlet API apps (including Spring MVC), information about the request will be collected automatically.
If you want to prevent an event from being sent to BugSnag, you can return false from an OnErrorCallback. This would allow users to opt out of sending error reports, for example:
bugsnag.addOnError((event) -> {
return !userHasOptedOut();
});
You can also discard events for specific exception types:
bugsnag.addOnError((event) -> {
if (event.getExceptionName().equals("com.example.IgnoredException")) {
return false;
}
return true;
});
Alternatively, you can use discardClasses to prevent specific exception types from being reported at all.
If you have metadata that is applicable to all captured events, it can be set globally using addOnError and will be attached to all subsequently generated events:
bugsnag.addOnError((event) -> {
event.addMetadata("company", "name", "Acme Co.");
return true;
});
If you have data that is relevant to the work a thread is doing (such as the current message being processed), it is possible to add metadata to any errors reported on that thread:
Bugsnag.addThreadMetadata("message", "id", "12345");
bugsnag.notify(new RuntimeException("Message ID will be included here"), Severity.ERROR);
bugsnag.notify(new RuntimeException("and also here"), Severity.INFO);
If your threads are reused to run multiple tasks, such as in a ThreadPoolExecutor, then you should ensure that metadata is cleared at the end of each task. Thread metadata will be automatically cleared at the end of an HTTP request when using the Servlet API.
Bugsnag.clearThreadMetadata(); // clear all metadata for the current thread
You can also remove a particular section from the thread metadata, or a particular key within a section:
Bugsnag.clearThreadMetadata("sectionToClear"); // clear thread metadata section
Bugsnag.clearThreadMetadata("sectionToClear", "keyToClear"); // clear thread metadata key
Thread metadata uses ThreadLocal storage, so it is only available on the thread where it was set. Each thread has its own separate metadata storage.
Information about the user affected by errors can be set using an OnErrorCallback:
bugsnag.addOnError((event) -> {
event.setUser("12345", "user@example.com", "User Name");
return true;
});
User details can also be set individually:
bugsnag.addOnError((event) -> {
event.setUserId("12345");
event.setUserEmail("user@example.com");
event.setUserName("User Name");
return true;
});
BugSnag uses the concept of “contexts” to help display and group your errors. The context represents what was happening in your application at the time an error occurs and is given high visual prominence in the dashboard.
By default, the context is set as the request method and URI for the current HTTP request if using the Servlet API. The context can be amended for each event using an OnErrorCallback:
bugsnag.addOnError((event) -> {
event.setContext("PaymentProcessing");
return true;
});
Monitor errors as you roll out features or run experiments and A/B tests by declaring your feature flag and experiment usage. Feature flags can be added at the client level or per-event:
// Add feature flags at the client level (attached to all subsequent events)
bugsnag.addFeatureFlag("Checkout button color", "Blue");
bugsnag.addFeatureFlag("New checkout flow");
// Add feature flags to a specific event
bugsnag.addOnError((event) -> {
event.addFeatureFlag("Checkout button color", "Blue");
event.addFeatureFlag("New checkout flow");
return true;
});
BugsnagEvent classA BugsnagEvent object represents an error captured by BugSnag and is available as a parameter on an OnErrorCallback. The following properties and methods are available on a BugsnagEvent for you to query and update the captured data.
Declare a single feature flag or experiment with variant as an optional second parameter.
event.addFeatureFlag("Checkout button color", "Blue");
event.addFeatureFlag("New checkout flow");
Declare multiple feature flags or experiments.
event.addFeatureFlags(Arrays.asList(
new FeatureFlag("Checkout button color", "Blue"),
new FeatureFlag("Special offer", "Free Coffee"),
new FeatureFlag("New checkout flow")
));
Adds the specified key and value in the specified section, which is shown as a tab on the BugSnag dashboard.
event.addMetadata("account", "name", "Acme Co.");
event.addMetadata("account", "paying_customer", true);
If you are using the logback appender then you can add metadata to every event by adding the following in your logback.xml file:
<appender name="BUGSNAG" class="com.bugsnag.BugsnagAppender">
...
<metaData>
<tab>
<name>system resources</name>
<key>
<name>memory</name>
<value>10MB</value>
</key>
</tab>
</metaData>
</appender>
It is also possible to add metadata to all events on the current thread, see Thread metadata.
The API key used for events sent to BugSnag. Even though the API key is set when BugSnag is initialized, you may choose to send certain events to a different BugSnag project:
event.setApiKey("your-other-api-key-here");
Information set by the notifier about your app can be found via the getApp() method:
| property | type | description |
|---|---|---|
| App type | String |
The application type, set via App Type |
| App version | String |
The application version, set via App Version |
| Release stage | String |
The release stage, defaults to production |
These values can be accessed and amended if necessary:
Map<String, Object> app = event.getApp();
String appVersion = (String) app.get("version");
Remove a single feature flag or experiment.
event.clearFeatureFlag("Checkout button color");
Remove all feature flags and experiments.
event.clearFeatureFlags();
Clears a section of metadata so it will not be sent to BugSnag. Also see Add Metadata.
event.clearMetadata("system resources");
The context represents what was happening in your application at the time an error occurs.
event.setContext("User settings");
Information set by the notifier about the device can be found via the getDevice() method:
| property | type | description |
|---|---|---|
| Hostname | String |
The name of the localhost |
| Locale | String |
The default locale for the JVM instance |
| OS architecture | String |
The value of the os.arch system property |
| OS name | String |
The value of the os.name system property |
| OS version | String |
The value of the os.version system property |
| Runtime name | String |
The value of the java.runtime.name system property |
| Runtime version | String |
The value of the java.runtime.version system property |
These values can be accessed and amended if necessary:
Map<String, Object> device = event.getDevice();
String hostname = (String) device.get("hostname");
Returns the Throwable that triggered this error event.
Throwable throwable = event.getException();
if (throwable instanceof SpecificException) {
// Handle specific exception type
}
Returns the message from the exception that is being reported.
String message = event.getExceptionMessage();
Returns the fully-qualified class name of the exception that is being reported.
String className = event.getExceptionName();
Sets the groupingHash used by BugSnag to manually override the default grouping technique. This is an advanced option, and should be used with care.
Any errors that are sent to BugSnag that have the same groupingHash will be grouped as one.
String groupingHash = "f8803769f3e293dfcabdb6dec5100b8c52c6ae6b";
event.setGroupingHash(groupingHash);
For more information, see our Error Grouping guide.
Sets the class name of the exception that is being reported. This allows you to customize how the error appears in the BugSnag dashboard.
event.setExceptionName("CustomErrorType");
Overrides the severity of the error. Valid severities are ERROR, WARNING and INFO.
event.setSeverity(Severity.WARNING);
Set information about the user the error occurred for. Details can also be set individually, see Set User ID, Set User Email and Set User Name.
event.setUser("12345", "user@example.com", "User Name");
Set the email address of the user the error occurred for. Also see Set User.
event.setUserEmail("user@example.com");
Set an identifier for the user the error occurred for. Also see Set User.
event.setUserId("12345");
Set the name of the user the error occurred for. Also see Set User.
event.setUserName("User Name");
Information about the user can be accessed via the getUser() method:
Map<String, String> user = event.getUser();
String userId = user.get("id");
String userEmail = user.get("email");
String userName = user.get("name");