Customizing error reports

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

Updating events using callbacks

If you’d like to add diagnostic data to reports, or adjust event data conditionally, you can register a callback to be run before an error is delivered to your Bugsnag dashboard using a callback:

Configuration->AddOnSendError([](TSharedRef<IBugsnagEvent> Event)
{
    Event->AddMetadata(TEXT("account"), TEXT("name"), TEXT("Acme Co."));
    Event->AddMetadata(TEXT("account"), TEXT("paying_customer"), true);

    // Return `false` if you'd like to stop this error being reported
    return true;
});

This callback gives you access to an Event object, so you can inspect and modify the error event which is about to be sent to Bugsnag.

If the app has crashed, these delivery-time callbacks will be executed in a background thread when the app next launches and has network connectivity. This means the state of the app and device are likely to be different to how they were when the crash occurred and so care must be taken when reading or adding external data in a callback.

Discarding events

If you want to prevent an event from being sent to Bugsnag, you can return false within a callback. This would allow for users to opt out of sending error reports, for example:

Configuration->AddOnSendError([](TSharedRef<IBugsnagEvent> Event)
{
    return !UserHasOptedOut();
});

Global metadata

If you have metadata that is applicable to all captured events, it can be set globally on the UBugsnagFunctionLibrary and will be set on all subsequently generated events. To ensure that events contain metadata as soon as Bugsnag starts capturing events, we recommend that you add metadata in your initial Bugsnag configuration if the data is available at startup.

Data is added to a specified “section”, which is displayed as a tab in the Bugsnag dashboard, and can either be added individually or as an FJsonObject:

Configuration->AddMetadata(TEXT("account"), TEXT("name"), TEXT("Acme Co."));

TSharedRef<FJsonObject> Basket = MakeShared<FJsonObject>();
Basket->SetStringField(TEXT("delivery"), TEXT("express"));
Basket->SetStringField(TEXT("sale"), TEXT("spring"));
Configuration->AddMetadata(TEXT("basket"), Basket);

Metadata can also be managed whilst your application is running using AddMetadata and ClearMetadata on UBugsnagFunctionLibrary:

UBugsnagFunctionLibrary::AddMetadata(TEXT("account"), TEXT("name"), TEXT("Acme Co."));
// ...
UBugsnagFunctionLibrary::ClearMetadata(TEXT("account"));

Adding user data

Information about the user affected by errors can be added to events sent to your Bugsnag dashboard by setting an initial user ID, email and name in your initial Bugsnag configuration when Bugsnag starts:

Configuration->SetUser(
    FString(TEXT("3")), // User ID
    FString(TEXT("bugs.nag@bugsnag.com")),
    FString(TEXT("Bugs Nag")));

When the Persist User configuration option configuration option is set to true, this user information will also be set in subsequent application launches.

If the user changes whilst the application is running, for example if a user signs in, you can update the user data on the UBugsnagFunctionLibrary for all subsequent events:

UBugsnagFunctionLibrary::SetUser(
    TEXT("3"), // User ID
    TEXT("bugs.nag@bugsnag.com"),
    TEXT("Bugs Nag"));

You can use metadata to add additional user information to the “user” section.

You can also update the user data from Blueprints using Bugsnag’s “Set User” action.

Setting context

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 this is set this to the name of the currently executing function. If you would like to set this value manually, you can set an initial value in your initial Bugsnag configuration when Bugsnag starts:

Configuration->SetContext(FString(TEXT("InitialTutorialStep")));

The context can then be amended through UBugsnagFunctionLibrary as/when it changes for all subsequent events:

UBugsnagFunctionLibrary::SetContext(TEXT("SecondTutorialStep"));

You can also amend the context from Blueprints using Bugsnag’s “Set Context” action.

The IBugsnagEvent class

An IBugsnagEvent object represents an error captured by Bugsnag and is available as a parameter on an event callback. The following methods are available on an IBugsnagEvent for you to query and update the captured data.

API Key

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(TEXT("YOUR-API-KEY"));

App

Information set by the notifier about your app can be found in the App object:

property type description
BinaryArch String The architecture of the running application binary
BuildUuid String The unique identifier for the build of the application (Android only)
BundleVersion String The bundle version used by the application (iOS & macOS only)
Duration Number The number of milliseconds the application was running before the event occurred
DurationInForeground Number The number of milliseconds the application was running in the foreground before the event occurred
Id String The package name of the application
InForeground Boolean Whether the application was in the foreground when the event occurred
IsLaunching Boolean Whether the application was still launching when the event occurred
ReleaseStage String The release stage set in Configuration
Type String The application type set in Configuration
Version String The version of the application set in Configuration
VersionCode String The version code of the application set in Configuration (Android only)

These values can be accessed and amended if necessary:

Event->GetApp()->SetAppVersion(FString(TEXT("1.2.3-alpha")));

A list of breadcrumbs leading up to the event can be found in Event.Breadcrumbs. See the Breadcrumb class for details of the data available.

These values can be accessed and amended if necessary:

Event->GetBreadcrumbs()[0]->SetMessage(TEXT(""));

Context

The context represents what was happening in your application at the time an error occurs.

Event->SetContext(FString(TEXT("SecondTutorialStep")));

See Setting context for more information.

Device

Information set by the notifier about the device on which the event occurred can be found in Event.Device:

property type description
CpuAbi String[] The Application Binary Interface used (Android only)
FreeDisk Number The number of free bytes of storage available on the device
FreeMemory Number The available RAM on the device (in bytes)
Id String A UUID generated by Bugsnag and used for the individual application on a device
Jailbroken String Whether the device has been jailbroken
Locale String The IETF language tag of the locale used
Manufacturer String The manufacturer of the device used
Model String The model name of the device used
ModelNumber String The model number of the device used
Orientation String The orientation of the device when the event occurred: either portrait or landscape
OsName String The name of the operating system running on the device used
OsVersion String The version of the operating system running on the device used
RuntimeVersions Map A collection of names and their versions of the primary languages, frameworks or runtimes that the application is running on
Time String The timestamp on the device when the event occurred
TotalMemory Number The total RAM size of the device (in bytes)

These values can be accessed and amended if necessary:

Event->GetDevice()->SetLocale(FString(TEXT("de-DE")));

Errors

event.errors is an array of one or more Error objects. The first item in the list represents the thrown object. Each subsequent item represents the exception that caused the preceding one.

An Error object contains the following information:

property type description
ErrorClass String The fully-qualified class name of the error generating the event
ErrorMessage String The message string from the error generating the event
Stacktrace Array<Stackframe> A representation of the stacktrace
Type ErrorType The type of error based on the originating platform
Event->GetErrors()[0]->SetErrorClass(TEXT("MyErrorClass"));

In an Error object, the stacktrace is a list of the following Stackframe objects:

property type description
File String The location of the source file
FrameAddress String The stack frame address (iOS & macOS only)
InProject Boolean Whether the package is considered to be in your project for the purposes of grouping and readability on the Bugsnag dashboard.
IsLr Boolean Whether the frame was within the link register (iOS & macOS only)
IsPc Boolean Whether the frame was within the program counter (iOS & macOS only)
LineNumber Number The line number within the source file this stackframe refers to
MachoFile String The Mach-O file used by the stackframe (iOS & macOS only)
MachoLoadAddress Number The load address of the Mach-O file (iOS & macOS only)
MachoUuid String A UUID identifying the Mach-O file used by the stackframe (iOS & macOS only)
MachoVmAddress Number The VM address of the Mach-O file (iOS & macOS only)
Method String The name of the method that was being executed
SymbolAddress Number The address of the stackframe symbol (iOS & macOS only)

It is therefore possible to modify the stacktrace that is associated with the Event object in the following way:

TSharedRef<IBugsnagError> Error = Event->GetErrors()[0];
TArray<TSharedRef<IBugsnagStackframe>> Stacktrace = Error->GetStacktrace();
Stacktrace.RemoveAt(0);
Error->SetStacktrace(Stacktrace);

Grouping Hash

The grouping hash of the event to override the default grouping on the dashboard. All events with the same grouping hash will be grouped together into one error. This is an advanced usage of the library and mis-using it will cause your events not to group properly in your dashboard.

As the name implies, this option accepts a hash of sorts.

// ... generate the hash
FString GroupingHash = TEXT("f8803769f3e293dfcabdb6dec5100b8c52c6ae6b");
Event->SetGroupingHash(GroupingHash);

Metadata

Add and remove metadata from a specified section, which is shown as a tab on the Bugsnag dashboard.

Data can be added key-by-key with a value that is a primitive type or a collection such as a map, set or array:

Event->AddMetadata(TEXT("account"), TEXT("name"), TEXT("Acme Co."));
Event->AddMetadata(TEXT("account"), TEXT("paying_customer"), true);
Event->AddMetadata(TEXT("account"), TEXT("roles"),
    MakeShared<FJsonValueArray>((TArray< TSharedPtr<FJsonValue> >){
        MakeShared<FJsonValueString>(TEXT("basic")),
        MakeShared<FJsonValueString>(TEXT("admin"))}));

Alternatively a whole map of key-value pairs can be added for a section:

TSharedRef<FJsonObject> Basket = MakeShared<FJsonObject>();
Basket->SetStringField(TEXT("delivery"), TEXT("express"));
Basket->SetStringField(TEXT("sale"), TEXT("spring"));
Event->AddMetadata(TEXT("basket"), Basket);

Metadata set on the event will be combined with global metadata set on the UBugsnagFunctionLibrary, with properties on the Event taking precedence.

To remove all the data from the specified section or from a key in the section:

Event->ClearMetadata(TEXT("account"));
// or
Event->ClearMetadata(TEXT("account"), TEXT("name"));

You can also obtain a map of data in the specified section and optionally key:

TSharedPtr<FJsonObject> Metadata = Event->GetMetadata(TEXT("account"));
// or
TSharedPtr<FJsonValue> AccountName = Event->GetMetadata(TEXT("account"), TEXT("name"));

Severity

The severity of the event. By default, unhandled exceptions will be EBugsnagSeverity::Error and handled exceptions sent with Notify will be EBugsnagSeverity::Warning.

Event->SetSeverity(EBugsnagSeverity::Warning);

Threads

If thread state is being captured along with the event, event.threads will contain a list of Thread objects as follows:

property type description
Id Number The unique ID of the thread
IsErrorReportingThread Boolean Whether the thread was the thread that caused the event
Name String The name of the thread
State Thread.State The state of the thread when the event occurred
Type ThreadType The type of thread based on the originating platform
Event->GetThreads()[0]->SetName(TEXT("New name"));

Unhandled

Whether the error was detected automatically by Bugsnag (true), or reported manually via Notify (false).

Event->SetUnhandled(true);

Changing the Unhandled flag for an event will affect how it contributes to your application’s stability score.

User

The current user information.

Event->SetUser(
    FString(TEXT("3")), // User ID
    FString(TEXT("bugs.nag@bugsnag.com")),
    TOptional<FString>());

TOptional<FString>() can be used as a parameter value to clear the user attribute.