Angular

Introduction

Before integrating a new BugSplat SDK with your application, make sure to review the Getting Started resources and complete the simple startup tasks listed below.

  • โ€‹Sign up for a BugSplat account

  • โ€‹Log in using your email address

  • Create a new database for your application

Need any further help? Check out the full BugSplat documentation here, or email the team at [email protected].

Sample

This repository includes a sample my-angular-crasher application that has be pre-configured with BugSplat. To test the sample, perform the following steps:

  1. git clone https://github.com/BugSplat-Git/bugsplat-ng

  2. cd bugsplat-ng && npm i

  3. npm run build

The npm run build command will build the sample application and upload source maps to BugSplat so that the JavaScript call stack can be mapped back to TypeScript. Once the build has completed the source maps will be uploaded and http-server will serve the app.

Navigate to the url displayed in the console by http-server (usually localhost:8080). Click the button labeled Crash to generate a crash report. A link to the crash report should display below the button. Click the link to the crash report and when prompted to log in use the email [email protected] and password Flintstone.

If everything worked correctly you should see information about your crash as well as a TypeScript stack trace.

Integration

To collect errors and crashes in your Angular application, run the following command in terminal or cmd at the root of your project to install bugsplat-ng:

npm i bugsplat-ng --save

Add a database property to your package.json file with the value of your BugSplat database.

{
"database": "{{ database }}"
}

Add values for your BugSplat database, application and version to your application's environment files:

โ€‹environment.prod.tsโ€‹

const packageJson = require('../../package.json');
export const environment = {
production: true,
bugsplat: {
database: packageJson.database,
application: packageJson.name,
version: packageJson.version
}
};

Add an import for BugSplatModule to your AppModule:

โ€‹app.module.tsโ€‹

import { BugSplatModule } from 'bugsplat-ng';

Add a call BugSplatModule.initializeApp in your AppModule's imports array passing it your database, application and version:

โ€‹app.module.tsโ€‹

...
@NgModule({
imports: [
BugSplatModule.initializeApp(environment.bugsplat)
],
...
})

Throw a new error in your application to test the bugsplat-ng integration:

โ€‹app.component.tsโ€‹

throw new Error("foobar!");

Navigate to the Crashes page in BugSplat and you should see a new crash report for the application you just configured. Click the link in the ID column to see details about your crash on the Crash page:

Crashes Page
Crash Page

Extended Integration

You can post additional information by creating a service that implements ErrorHandler. In the handlerError method make a call to BugSplat.post passing it the error and an optional options object:

โ€‹my-angular-error-handler.tsโ€‹

import { ErrorHandler, Injectable } from '@angular/core';
import { BugSplat } from 'bugsplat-ng';
โ€‹
@Injectable()
export class MyAngularErrorHandler implements ErrorHandler {
โ€‹
constructor(public bugsplat: BugSplat) { }
โ€‹
async handleError(error: Error): Promise<void> {
return this.bugsplat.post(error, {
description: 'New description from MyAngularErrorHandler.ts'
});
}
}

BugSplat provides the following properties and methods that allow you to customize its functionality:

โ€‹bugsplat.tsโ€‹

BugSplat.description: string; // Additional info about your crash that gets reset after every post
BugSplat.email: string; // The email of your user
BugSplat.key: string; // A unique identifier for your application
BugSplat.user: string; // The name or id of your user
BugSplat.files: Array<file>; // A list of files to be uploaded at post time
BugSplat.getObservable(): Observable<BugSplatPostEvent>; // Observable that emits results of BugSplat crash post events in your components.
async BugSplat.post(error): Promise<void>; // Post an Error object to BugSplat manually from within a try/catch

In your AppModule's NgModule definition, add a provider for your new ErrorHandler:

โ€‹app.module.tsโ€‹

import { ErrorHandler, NgModule } from '@angular/core';
โ€‹
@NgModule({
providers: [
{
provide: ErrorHandler,
useClass: MyAngularErrorHandler
}
]
...
})

You can also configure BugSplat's logging preferences and provide your own logging implementation. Create a provider for BugSplatLogger with useValue set to a new instance of BugSplatLogger. Pass one of the BugSplatLogLevel options as the first parameter to BugSplatLogger. You can provide an instance of your own custom logger as the second parameter granted it has error, warn, info and log methods. If no custom logger is provided console will be used:

โ€‹app.module.tsโ€‹

import { ErrorHandler, NgModule } from '@angular/core';
import { BugSplatLogger, BugSplatLogLevel, BugSplatModule } from 'bugsplat-ng';
โ€‹
@NgModule({
providers: [
{
provide: ErrorHandler,
useClass: BugSplatErrorHandler
},
{
provide: BugSplatLogger,
useValue: new BugSplatLogger(BugSplatLogLevel.Log)
}
],
...
})

Source Maps

BugSplat supports unwinding uglified and minified JavaScript stack traces via source maps. To upload source maps to BugSplat during your build, install @bugsplat/symbol-upload.

npm i -D @bugsplat/symbol-upload

Configure your angular.json file to output source maps. We suggest enabling source maps for both your application code and any vendor chunks that are generated by Angular.

{
"projects": {
"main": {
"architect": {
"build": {
"options": {
"sourceMap": {
"scripts": true,
"styles": true,
"vendor": true
},
},
}
}
}
}
}

Add SYMBOL_UPLOAD_EMAIL and SYMBOL_UPLOAD_PASSWORD environment variables for the BugSplat user that you will use to upload symbols. You can create these values as system environment variables or use dotenv.

SYMBOL_UPLOAD_EMAIL=[email protected]
SYMBOL_UPLOAD_PASSWORD=password

Create a script for uploading source maps.

const { BugSplatApiClient, Symbols } = require('@bugsplat/symbol-upload');
const packageJson = require('../package.json');
const fs = require('fs');
โ€‹
const dist = fs.readdirSync('./dist');
const files = dist
.filter(file => file.endsWith('.js.map'))
.map(file => (`./dist/${file}`));
โ€‹
const database = packageJson.database;
const application = packageJson.name;
const version = packageJson.version;
const symbols = new Symbols(
database,
application,
version,
files
);
โ€‹
const email = process.env.SYMBOL_UPLOAD_EMAIL;
const password = process.env.SYMBOL_UPLOAD_PASSWORD;
const client = new BugSplatApiClient();
return client.login(email, password)
.then(() => symbols.post(client))
.then(() => console.log('Symbols uploaded successfully!'));

Add a symbols script to your package.json.

{
"scripts": {
"symbols": "node ./scripts/symbols.js"
},
}

For best results, please upload source maps for every released version of your application.

Contributing

BugSplat loves open source software! If you have suggestions on how we can improve this integration, please reach out to [email protected], create an issue in our GitHub repo or send us a pull request.