From c182ee01d21e9c4c6cdcd48b87da15317d0bfaa8 Mon Sep 17 00:00:00 2001 From: Konrad Dysput Date: Fri, 25 Aug 2023 12:54:20 +0200 Subject: [PATCH 1/9] Backtrace node readme --- packages/node/README.md | 401 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100644 packages/node/README.md diff --git a/packages/node/README.md b/packages/node/README.md new file mode 100644 index 00000000..5eff02b3 --- /dev/null +++ b/packages/node/README.md @@ -0,0 +1,401 @@ +# **Backtrace Node SDK** + +[Backtrace](https://backtrace.io) captures and reports handled and unhandled exceptions in your production software so +you can manage application quality through the complete product lifecycle. + +The [@backtrace-labs/node](#) SDK connects your JavaScript application to Backtrace. The basic integration is quick and +easy, after which you can explore the rich set of Backtrace features. + +## Table of Contents + +1. [Basic Integration - Reporting your first errors](#basic-integration) + - [Install the package](#install-the-package) + - [Integrate the SDK](#integrate-the-sdk) + - [Upload source maps](#upload-source-maps) +1. [Error Reporting Features](#error-reporting-features) + - [Attributes](#attributes) + - [File Attachments](#file-attachments) + - [Breadcrumbs](#breadcrumbs) + - [Application Stability Metrics](#application-stability-metrics) + - [Metrics Configuration](#metrics-configuration) + - [Metrics Usage](#metrics-usage) + - [Offline Database support](#offline-database-support) + - [Database Configuration](#database-configuration) + - [Native crash support](#native-crash-support) + - [Manual database operations](#manual-database-operations) +1. [Advanced SDK Features](#advanced-sdk-features) + - [Manually send an error](#manually-send-an-error) + - [BacktraceClient](#backtraceclient) + - [BacktraceClientOptions](#backtraceclientoptions) + - [BacktraceClient Methods](#backtraceclient-methods) + - [BacktraceDatabase Methods](#backtracedatabase-methods) + - [BacktraceReports](#backtracereport) + +## Basic Integration + +### Install the package + +``` +$ npm install @backtrace-labs/node +``` + +### Integrate the SDK + +Add the following code to your application before all other scripts to report node errors to Backtrace. + +```ts +// Import the BacktraceClient from @backtrace-labs/node with your favoriate package manager. +import { BacktraceClient, BacktraceConfiguration } from '@backtrace-labs/node'; + +// Configure client options +const options: BacktraceConfiguration = { + // Submission url + // is the subdomain of your Backtrace instance (.backtrace.io) + // can be found in Project Settings/Submission tokens + url: 'https://submit.backtrace.io///json', +}; + +// Initialize the client with the options +const client = BacktraceClient.initialize(options); + +// By default, Backtrace will send an error for Uncaught Exceptions and Unhandled Promise Rejections + +// Manually send an error +client.send(new Error('Something broke!')); +``` + +### Upload source maps + +Client-side error reports are based on minified code. Upload source maps and source code to resolve minified code to +your original source identifiers. + +[(Source Map feature documentation)](https://docs.saucelabs.com/error-reporting/platform-integrations/source-map/) + + + +## Error Reporting Features + +### Attributes + +Custom attributes are key-value pairs that can be added to your error reports. They are used in report aggregation, +sorting and filtering, can provide better contextual data for an error, and much more. They are foundational to many of +the advanced Backtrace features detailed in +[Error Reporting documentation](https://docs.saucelabs.com/error-reporting/getting-started/). By default attributes such +as application name and version are populated automatically based on your package.json information. If Backtrace cannot +find them, you need to provide them manually via userAttributes attributes. + +There are several places where attributes can be added, modified or deleted. + +#### Attach attributes object to BacktraceClient + +It is possible to include an attributes object during [BacktraceClient](#backtraceclient) initialization. This list of +attributes will be included with every error report, referred to as global attributes. + +```ts +// Create an attributes object that can be modified throughout runtime +const attributes: Record = { + release: 'PROD', +}; + +// BacktraceClientOptions +const options: BacktraceConfiguration = { + url: 'https://submit.backtrace.io///json', + + // Attach the attributes object + userAttributes: attributes, +}; + +// Initialize the client +const client = BacktraceClient.initialize(options); +``` + +#### Add attributes during application runtime + +Global attributes can be set during the runtime once specific data has be loaded (e.g. a user has logged in). + +```ts +const client = BacktraceClient.initialize(options); +... + +client.addAttribute({ + "clientID": "de6faf4d-d5b5-486c-9789-318f58a14476" +}) +``` + +#### Add attributes to an error report + +The attributes list of a BacktraceReport object can be directly modified. + +```ts +const report: BacktraceReport = new BacktraceReport('My error message', { myReportKey: 'myValue' }); +report.attributes['myReportKey'] = 'New value'; +``` + +--- + +### File Attachments + +Files can be attached to error reports. This can be done when initalizing the BacktraceClient, updating the +BacktraceClient, or dynamically for specific reports. When including attachments in BacktraceClient, all files will be +uploaded with each report. + +```ts +// Import attachment types from @backtrace-labs/node +import { BacktraceStringAttachment, BacktraceUint8ArrayAttachment } from "@backtrace-labs/node"; + +// BacktraceStringAttachment should be used for text object like a log file, for example +const stringAttachment = new BacktraceStringAttachment("logfile.txt", "This is the start of my log") + +// Buffer attachment is an attachment type dedicated to store buffer data +const bufferAttachment = new BacktraceBufferAttachment('buffer-attachment.txt', Buffer.from('sample')); + +// File attachment is an attachment type dedicated for streaming files +const fileAttachment = new BacktraceFileAttachment('/path/to/sample/file'); + +// BacktraceClientOptions +const options = { + url: "https://submit.backtrace.io///json", + + // Attach the files to all reports + attachments: [path.join('/path/to/attachment'), stringAttachment], +} + +const client = BacktraceClient.initialize(options); + +// Later decide to add an attachment to all reports +client.attachments.push(bufferAttachment) + +// After catching an exception and generating a report +try { + throw new Error("Caught exception!") +} catch (error) { + const report = const report = new BacktraceReport(error, {}, [fileAttachment]) + client.send(report); +} +``` + +--- + +### Breadcrumbs + +Breadcrumbs are snippets of chronological data tracing runtime events. This SDK records a number of events by default, +and manual breadcrumbs can also be added. + +[(Breadcrumbs feature documentation)](https://docs.saucelabs.com/error-reporting/web-console/debug/#breadcrumbs) + +#### Breadcrumbs Configuration + +| Option Name | Type | Description | Default | Required? | +| -------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------------------------ | +| `enable` | Boolean | Determines if the breadcrumbs support is enabled. By default the value is set to true. | `true` |
  • - [ ]
| +| `logLevel` | BreadcrumbLogLevel | Specifies which log level severity to include. By default all logs are included. | All Logs |
  • - [ ]
| +| `eventType` | BreadcrumbType | Specifies which breadcrumb type to include. By default all types are included. | All Types |
  • - [ ]
| +| `maximumBreadcrumbs` | Number | Specifies maximum number of breadcrumbs stored by the library. By default, only 100 breadcrumbs will be stored. | `100` |
  • - [ ]
| +| `intercept` | (breadcrumb: RawBreadcrumb) => RawBreadcrumb \| undefined; | Inspects breadcrumb and allows to modify it. If the undefined value is being returned from the method, no breadcrumb will be added to the breadcrumb storage. | All Breadcrumbs |
  • - [ ]
| + +```ts +import { BacktraceClient, BacktraceConfiguration } from '@backtrace-labs/ndoe'; + +// BacktraceClientOptions +const options: BacktraceConfiguration = { + // ignoring all but breadcrumbs config for simplicity + breadcrumbs: { + // breadcrumbs configuration + }, +}; + +// Initialize the client +const client = BacktraceClient.initialize(options); +``` + +#### Default Breadcrumbs + +| Type | Description | +| ------- | ------------------------------------------------------------------------ | +| Console | Adds a breadcrumb every time console log is being used by the developer. | + +#### Intercepting Breadcrumbs + +If PII or other information needs to be filtered from a breadcrumb, you can use the intercept function to skip or filter +out the sensitive information. Any RawBreadcrumb returned will be used for the breadcrumb. If undefined is returned, no +breadcrumb will be added. + +#### Manual Breadcrumbs + +In addition to all of the default breadcrumbs that are automatically collected, you can also manually add breadcrumbs of +your own. + +```ts +client.breadcrumbs?.info('This is a manual breadcrumb.', { + customAttr: 'wow!', +}); +``` + +--- + +### Application Stability Metrics + +The Backtrace Node SDK has the ability to send usage Metrics to be viewable in the Backtrace UI. + +[(Stability Metrics feature documentation)](https://docs.saucelabs.com/error-reporting/project-setup/stability-metrics/) + +#### Metrics Configuration + +| Option Name | Type | Description | Default | Required? | +| ---------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------ | +| `metricsSubmissionUrl` | String | Metrics server hostname. By default the value is set to https://events.backtrace.io. | `https://events.backtrace.io` |
  • - [ ]
| +| `enable` | Boolean | Determines if the metrics support is enabled. By default the value is set to true. | `true` |
  • - [ ]
| +| `autoSendInterval` | Number | Indicates how often crash free metrics are sent to Backtrace. The interval is a value in ms. By default, session events are sent on application startup/finish, and every 30 minutes while the application is running. If the value is set to 0. The auto send mode is disabled. In this situation the application needs to maintain send mode manually. | On application startup/finish |
  • - [ ]
| +| `size` | Number | Indicates how many events the metrics storage can store before auto submission. | `50` |
  • - [ ]
| + +#### Metrics Usage + +```ts +// metrics will be undefined if not enabled +client.metrics?.send(); +``` + +--- + +### Offline database support + +The Backtrace Node SDK allows to store generated reports and crashes on the hard drive before sending them to Backtrace. +Based on your node configuration, your application might crash before the SDK finishes submitting data. In addition to +that if the application user has a slow Internet connection, your application might wait in a closing window until the +HTTP submission finishes. To prevent this situation, we recommend to use the database solution. By using it, you can: + +- cache your reports when the user doesn't have Internet connection or the service is unavailable, +- capture crashes +- manually decide when to send them or not + +By default the offline database support is disabled. To enable it, please add "enable: true" and the path to the +directory where Backtrace can store crash data. + +#### Database Configuration + +| Option Name | Type | Description | Default | Required? | +| ------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------ | +| `enabled` | Boolean | Determine if the Database is enabled. | false |
  • - [x]
| +| `path` | String | Path where the SDK can store data. | - |
  • - [x]
| +| `createDatabaseDirectory` | Boolean | Determine if the directory should be auto created by the SDK. | true | | +| `autoSend` | Boolean | Sends reports to the server based on the retry settings. If the value is set to 'false', you can use the Flush or Send methods as an alternative. | true | +| `maximumNumberOfRecords` | Number | The maximum number of reports stored in the offline database. When the limit is reached, the oldest reports are removed. If the value is equal to '0', then no limit is set. | 8 | +| `retryInterval` | Number | The amount of time (in ms) to wait between retries if the database is unable to send a report. | 60 000 | +| `maximumRetries` | Number | The maximum number of retries to attempt if the database is unable to send a report. | 3 | +| `captureNativeCrashes` | Boolean | Captures and symbolicates stack traces for native crashes if the runtime supports this. A crash report is generated, stored locally, and uploaded upon next start. | false | + +--- + +#### Native crash support + +The Backtrace Node SDK allows to capture native crashes generated by the node application such as Assert/OOM crashes. In +order to collect them, the SDK uses the Node's `process.report` API. After setting up the native crash support, your +`process.report` settings might be overridden and your crash data might be created in the database directory. + +Database records sent in the next session might not have some information about the crashing session such as attributes +or breadcrumbs. To reduce database record size, attachment support was limited only to file attachments. + +#### Manual database operations + +Database support is available in the client options. You can use it to manually operate on database records. The +database object allows you to: + +- add manually your Backtrace data, +- get all records, +- count all records, +- dispose of the database, +- remove the record, +- flush all records - send and forget, +- send manually all records. + +```ts +const client = BacktraceClient.initialize({ + // ignoring all but database config for simplicity + database: { + enabled: true, + path: '/path/to/the/database/directory', + captureNativeCrashes: true, + }, +}); + +// manuall send and keep the data on connection issue +client.database.send(); +// manuall send and remove all data no matter if received success or not. +client.database.flush(); +``` + +## Advanced SDK Features + +### Manually send an error + +There are several ways to send an error to Backtrace. For more details on the definition of `client.send()` see +[Methods](#methods) below. + +```ts +// send as a string +await client.send('This is a string!'); + +// send as an Error +await client.send(new Error('This is an Error!')); + +// as a BacktraceReport (string) +await client.send(new BacktraceReport('This is a report with a string!')); + +// as a BacktraceReport (Error) +await client.send(new BacktraceReport(new Error('This is a report with a string!'))); +``` + +### BacktraceClient + +BacktraceClient is the main SDK class. Error monitoring starts when this object is instantiated, and it will compose and +send reports for unhandled errors and unhandled promise rejections. It can also be used to manually send reports from +exceptions and rejection handlers. + +#### BacktraceClientOptions + +The following options are available for the BacktraceClientOptions passed when initializing the BacktraceClient. + +| Option Name | Type | Description | Default | Required? | +| ----------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | ------------------------ | +| `url` | String | Submission URL to send errors to | |
  • - [x]
| +| `token` | String | The submission token for error injestion. This is required only if submitting directly to a Backtrace URL. (uncommon) | |
  • - [ ]
| +| `userAttributes` | Dictionary | Additional attributes that can be filtered and aggregated against in the Backtrace UI. | |
  • - [ ]
| +| `attachments` | BacktraceAttachment[] | Additional files to be sent with error reports. See [File Attachments](#file-attachments) | |
  • - [ ]
| +| `beforeSend` | (data: BacktraceData) => BacktraceData \| undefined | Triggers an event every time an exception in the managed environment occurs, which allows you to skip the report (by returning a null value) or to modify data that library collected before sending the report. You can use the BeforeSend event to extend attributes or JSON object data based on data the application has at the time of exception. See [BeforeSend](#beforesend) | |
  • - [ ]
| +| `skipReport` | (report: BacktraceReport) => boolean | If you want to ignore specific types of error reports, we recommend that you use the skipReport callback. By using it, based on the data generated in the report, you can decide to filter the report, or send it to Backtrace. | |
  • - [ ]
| +| `captureUnhandledErrors` | Boolean | Enable unhandled errors | `true` |
  • - [ ]
| +| `captureUnhandledPromiseRejections` | Boolean | Enable unhandled promise rejection | `true` |
  • - [ ]
| +| `timeout` | Integer | How long to wait in ms before timing out the connection | `15000` |
  • - [ ]
| +| `ignoreSslCertificate` | Boolean | Ignore SSL Certificate errors | `false` |
  • - [ ]
| +| `rateLimit` | Integer | Limits the number of reports the client will send per minute. If set to '0', there is no limit. If set to a value greater than '0' and the value is reached, the client will not send any reports until the next minute. | `0` |
  • - [ ]
| +| `metrics` | BacktraceMetricsOptions | See [Backtrace Stability Metrics](#application-stability-metrics) | |
  • - [ ]
| +| `breadcrumbs` | BacktraceBreadcrumbsSettings | See [Backtrace Breadcrumbs](#breadcrumbs) | |
  • - [ ]
| +| `database` | BacktraceDatabaseSettings | See [Backtrace Database](#offline-database-support) | |
  • - [ ]
| + +#### BacktraceClient Methods + +| Name | Return Type | Description | +| ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | --------------------------------------------------------------------------------- | +| `addAttribute(attributes: Record)` | void | Add attributes to the BacktraceClient reports | +| `initialize(options: BacktraceClientOptions)` | BacktraceClient | Initializes a new BacktraceClient (returns the same instance on subsequent calls) | +| `builder(options: BacktraceClientOptions).build()` | BacktraceClient | (Advanced) Sets up a new BacktraceClient for reporting | +| `send(data: BacktraceReport \| Error \| string, reportAttributes: Record = {}, reportAttachments: BacktraceAttachment[] = [])` | Promise | Asynchronously sends error data to Backtrace | + +#### BacktraceDatabase Methods + +| Name | Return Type | Description | +| ----------------------------------------------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `enable` | Boolean | Determines if the database is enabled | +| `start()` | Boolean | Starts the database | +| `add(backtraceData: Backtracedata, attachments: BacktraceAttachment[])` | BacktraceDatabaseRecord \| undefined | Adds manually a data object to the database. If the database is not available or the record cannot be stored on the hard drive, the add method can return undefined. | +| `get()` | BacktraceDatabaseRecord[] | Returns all records stored in the database | +| `count()` | Number | Returns the number of records stored in the database | +| `dispose()` | void | Disables the database integration | +| `remove(record: BacktraceDatabaseRecord)` | void | Removes the record from the database | +| `flush()` | Promise | Sends all records to Backtrace and remove them no matter if the submission was successful or not | +| `send()` | Promise | Sends all records to Backtrace. If the submission process fails, the retry information is being increased by the records are not removed from the database. | + +### BacktraceReport + +A Backtrace Report is the format that ultimately gets sent to Backtrace. Its structure can be found in +`BacktraceReport.ts`. From 795a7104a2fc2549629f38ad11ec62f053ac0377 Mon Sep 17 00:00:00 2001 From: Konrad Dysput Date: Fri, 25 Aug 2023 13:50:27 +0200 Subject: [PATCH 2/9] Client dispose --- packages/browser/src/BacktraceClient.ts | 64 +++++++++++++------ packages/node/src/BacktraceClient.ts | 13 +++- .../node/tests/client/disposeTests.spec.ts | 23 +++++++ packages/sdk-core/src/BacktraceCoreClient.ts | 8 +++ 4 files changed, 86 insertions(+), 22 deletions(-) create mode 100644 packages/node/tests/client/disposeTests.spec.ts diff --git a/packages/browser/src/BacktraceClient.ts b/packages/browser/src/BacktraceClient.ts index 890a3c5a..e3d748a1 100644 --- a/packages/browser/src/BacktraceClient.ts +++ b/packages/browser/src/BacktraceClient.ts @@ -14,6 +14,8 @@ import { BacktraceConfiguration } from './BacktraceConfiguration'; import { BacktraceClientBuilder } from './builder/BacktraceClientBuilder'; export class BacktraceClient extends BacktraceCoreClient { + private readonly _disposeController: AbortController = new AbortController(); + protected static _instance?: BacktraceClient; constructor( options: BacktraceConfiguration, @@ -70,32 +72,52 @@ export class BacktraceClient extends BacktraceCoreClient { return this._instance; } + /** + * Disposes the client and all client callbacks + */ + public dispose(): void { + this._disposeController.abort(); + super.dispose(); + } + private captureUnhandledErrors(captureUnhandledExceptions = true, captureUnhandledRejections = true) { if (captureUnhandledExceptions) { - window.addEventListener('error', async (errorEvent: ErrorEvent) => { - await this.send( - new BacktraceReport(errorEvent.error, { - 'error.type': 'Unhandled exception', - }), - ); - }); + window.addEventListener( + 'error', + async (errorEvent: ErrorEvent) => { + await this.send( + new BacktraceReport(errorEvent.error, { + 'error.type': 'Unhandled exception', + }), + ); + }, + { + signal: this._disposeController.signal, + }, + ); } if (captureUnhandledRejections) { - window.addEventListener('unhandledrejection', async (errorEvent: PromiseRejectionEvent) => { - await this.send( - new BacktraceReport( - errorEvent.reason, - { - 'error.type': 'Unhandled exception', - }, - [], - { - classifiers: ['UnhandledPromiseRejection'], - }, - ), - ); - }); + window.addEventListener( + 'unhandledrejection', + async (errorEvent: PromiseRejectionEvent) => { + await this.send( + new BacktraceReport( + errorEvent.reason, + { + 'error.type': 'Unhandled exception', + }, + [], + { + classifiers: ['UnhandledPromiseRejection'], + }, + ), + ); + }, + { + signal: this._disposeController.signal, + }, + ); } } } diff --git a/packages/node/src/BacktraceClient.ts b/packages/node/src/BacktraceClient.ts index 07c3910b..b8e61c90 100644 --- a/packages/node/src/BacktraceClient.ts +++ b/packages/node/src/BacktraceClient.ts @@ -19,6 +19,8 @@ import { NodeDiagnosticReportConverter } from './converter/NodeDiagnosticReportC import { BacktraceDatabaseFileStorageProvider } from './database/BacktraceDatabaseFileStorageProvider'; export class BacktraceClient extends BacktraceCoreClient { + private _listeners: Record = {}; + private static _instance?: BacktraceClient; constructor( options: CoreConfiguration, @@ -70,6 +72,14 @@ export class BacktraceClient extends BacktraceCoreClient { return this._instance; } + public dispose(): void { + for (const [name, listener] of Object.entries(this._listeners)) { + process.removeListener(name, listener); + } + + super.dispose(); + } + protected initialize() { super.initialize(); @@ -105,7 +115,7 @@ export class BacktraceClient extends BacktraceCoreClient { }; process.prependListener('uncaughtExceptionMonitor', captureUncaughtException); - + this._listeners['uncaughtExceptionMonitor'] = captureUncaughtException; if (!captureUnhandledRejections) { return; } @@ -188,6 +198,7 @@ export class BacktraceClient extends BacktraceCoreClient { process.emitWarning(warning); }; process.prependListener('unhandledRejection', captureUnhandledRejectionsCallback); + this._listeners['unhandledRejection'] = captureUnhandledRejectionsCallback; } private captureNodeCrashes() { diff --git a/packages/node/tests/client/disposeTests.spec.ts b/packages/node/tests/client/disposeTests.spec.ts new file mode 100644 index 00000000..8d826b0c --- /dev/null +++ b/packages/node/tests/client/disposeTests.spec.ts @@ -0,0 +1,23 @@ +import { BacktraceClient } from '../../src/'; +describe('Client Dispose tests', () => { + it('Should dispose process callbacks', () => { + const expectedUnhandledRejectionListenerCount = process.listenerCount('unhandledRejection'); + const expectedUncaughtExceptionListenerCount = process.listenerCount('uncaughtExceptionMonitor'); + const client = BacktraceClient.initialize({ + url: 'https://submit.backtrace.io/foo/bar/baz', + metrics: { + enable: false, + }, + breadcrumbs: { + enable: false, + }, + }); + + expect( + process.listenerCount('unhandledRejection') + process.listenerCount('uncaughtExceptionMonitor'), + ).toBeGreaterThan(expectedUnhandledRejectionListenerCount + expectedUncaughtExceptionListenerCount); + client.dispose(); + expect(process.listenerCount('unhandledRejection')).toBe(expectedUnhandledRejectionListenerCount); + expect(process.listenerCount('uncaughtExceptionMonitor')).toBe(expectedUncaughtExceptionListenerCount); + }); +}); diff --git a/packages/sdk-core/src/BacktraceCoreClient.ts b/packages/sdk-core/src/BacktraceCoreClient.ts index d43f8693..f2734091 100644 --- a/packages/sdk-core/src/BacktraceCoreClient.ts +++ b/packages/sdk-core/src/BacktraceCoreClient.ts @@ -219,6 +219,14 @@ export abstract class BacktraceCoreClient { } } + /** + * Disposes the client and all client callbacks + */ + public dispose() { + this.database?.dispose(); + this.breadcrumbsManager?.dispose(); + } + private addToDatabase( data: BacktraceData, attachments: BacktraceAttachment[], From 7a25f0548b6f99e363ad73939527255eca88802e Mon Sep 17 00:00:00 2001 From: Konrad Dysput Date: Fri, 25 Aug 2023 13:51:55 +0200 Subject: [PATCH 3/9] Client dispose --- packages/node/src/BacktraceClient.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/node/src/BacktraceClient.ts b/packages/node/src/BacktraceClient.ts index b8e61c90..dd780cc9 100644 --- a/packages/node/src/BacktraceClient.ts +++ b/packages/node/src/BacktraceClient.ts @@ -72,6 +72,9 @@ export class BacktraceClient extends BacktraceCoreClient { return this._instance; } + /** + * Disposes the client and all client callbacks + */ public dispose(): void { for (const [name, listener] of Object.entries(this._listeners)) { process.removeListener(name, listener); From f7605e0bab709705d6a3fad70819ef9025e26ddd Mon Sep 17 00:00:00 2001 From: Konrad Dysput Date: Fri, 25 Aug 2023 13:53:32 +0200 Subject: [PATCH 4/9] Do not send reports via disposed client --- packages/sdk-core/src/BacktraceCoreClient.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/sdk-core/src/BacktraceCoreClient.ts b/packages/sdk-core/src/BacktraceCoreClient.ts index f2734091..6e729790 100644 --- a/packages/sdk-core/src/BacktraceCoreClient.ts +++ b/packages/sdk-core/src/BacktraceCoreClient.ts @@ -26,6 +26,13 @@ import { MetricsBuilder } from './modules/metrics/MetricsBuilder'; import { SingleSessionProvider } from './modules/metrics/SingleSessionProvider'; import { RateLimitWatcher } from './modules/rateLimiter/RateLimitWatcher'; export abstract class BacktraceCoreClient { + /** + * Determines if the client is enabled. + */ + public get enabled() { + return this._enabled; + } + /** * Current session id */ @@ -87,6 +94,7 @@ export abstract class BacktraceCoreClient { private readonly _attributeProvider: AttributeManager; private readonly _metrics?: BacktraceMetrics; private readonly _database?: BacktraceDatabase; + private _enabled = true; protected constructor( protected readonly options: BacktraceConfiguration, @@ -186,6 +194,9 @@ export abstract class BacktraceCoreClient { reportAttributes: Record = {}, reportAttachments: BacktraceAttachment[] = [], ): Promise { + if (!this._enabled) { + return; + } if (this._rateLimitWatcher.skipReport()) { return; } @@ -223,6 +234,7 @@ export abstract class BacktraceCoreClient { * Disposes the client and all client callbacks */ public dispose() { + this._enabled = false; this.database?.dispose(); this.breadcrumbsManager?.dispose(); } From f93fd5a8492921dde594d2a1bb0758671bcb514b Mon Sep 17 00:00:00 2001 From: Konrad Dysput Date: Fri, 25 Aug 2023 13:56:49 +0200 Subject: [PATCH 5/9] Close metrics --- packages/sdk-core/src/BacktraceCoreClient.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/sdk-core/src/BacktraceCoreClient.ts b/packages/sdk-core/src/BacktraceCoreClient.ts index 6e729790..4c698511 100644 --- a/packages/sdk-core/src/BacktraceCoreClient.ts +++ b/packages/sdk-core/src/BacktraceCoreClient.ts @@ -237,6 +237,7 @@ export abstract class BacktraceCoreClient { this._enabled = false; this.database?.dispose(); this.breadcrumbsManager?.dispose(); + this._metrics?.close(); } private addToDatabase( From 0c6fcd18d9b7ddd9850abb88bce9c82b4ce2ce69 Mon Sep 17 00:00:00 2001 From: Konrad Dysput Date: Fri, 25 Aug 2023 13:58:31 +0200 Subject: [PATCH 6/9] Rename close to dispose --- packages/sdk-core/src/BacktraceCoreClient.ts | 2 +- packages/sdk-core/src/modules/metrics/BacktraceMetrics.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sdk-core/src/BacktraceCoreClient.ts b/packages/sdk-core/src/BacktraceCoreClient.ts index 4c698511..eea0a56a 100644 --- a/packages/sdk-core/src/BacktraceCoreClient.ts +++ b/packages/sdk-core/src/BacktraceCoreClient.ts @@ -237,7 +237,7 @@ export abstract class BacktraceCoreClient { this._enabled = false; this.database?.dispose(); this.breadcrumbsManager?.dispose(); - this._metrics?.close(); + this._metrics?.dispose(); } private addToDatabase( diff --git a/packages/sdk-core/src/modules/metrics/BacktraceMetrics.ts b/packages/sdk-core/src/modules/metrics/BacktraceMetrics.ts index d2fada30..fa9bc77e 100644 --- a/packages/sdk-core/src/modules/metrics/BacktraceMetrics.ts +++ b/packages/sdk-core/src/modules/metrics/BacktraceMetrics.ts @@ -96,7 +96,7 @@ export class BacktraceMetrics { /** * Cleans up metrics interface. */ - public close() { + public dispose() { if (this._updateIntervalId) { clearInterval(this._updateIntervalId); } From 54e8bbde1bb20b09e9e7fa9fab347f040e59b4de Mon Sep 17 00:00:00 2001 From: Konrad Dysput Date: Mon, 28 Aug 2023 17:43:00 +0200 Subject: [PATCH 7/9] Squashed commit of the following: commit a6408e44cccbe0a4a5182ac3cd4b6a7b3f8092f6 Merge: 2ab4feb 184ab33 Author: Rick Foster <115846221+rick-bt@users.noreply.github.com> Date: Fri Aug 25 11:29:43 2023 -0700 Merge pull request #97 from backtrace-labs/rick/sourcemap-readmes Add webpack readme commit 184ab33b74bed028a0177f746085f5a3967004f0 Author: Rick Foster Date: Fri Aug 25 11:22:34 2023 -0700 Add rollup, vite readmes. Fix instructions for url commit 3c392f3781756bb82ab39c9ff39c6ee23b08214a Author: Rick Foster Date: Fri Aug 25 11:01:19 2023 -0700 Add webpack readme commit 2ab4febb33c2ea070d6d9d2df26b5dc96122b455 Author: Konrad Dysput Date: Fri Aug 25 19:44:22 2023 +0200 Backtrace node readme (#93) * Backtrace node readme * Fit 'n finish on node readme (#96) * Fit 'n finish on node readme * Modify enabled option to enable * Fix tests --------- Co-authored-by: Konrad Dysput --------- Co-authored-by: Rick Foster <115846221+rick-bt@users.noreply.github.com> commit 41fb8fc89c686570abbae43714889fcedcab33ac Author: Konrad Dysput Date: Fri Aug 25 19:15:04 2023 +0200 SDK Core README (#91) * SDK Core README * Document format * Update packages/sdk-core/README.md commit ea111f199d62ca9ee434d81e2e5cb27cb8f8bacb Author: Konrad Dysput Date: Fri Aug 25 17:11:29 2023 +0200 Source map tools README (#92) commit 6e9659d04b4a6d7fe9a8d20cbae6142f3032cf91 Author: Konrad Dysput Date: Fri Aug 25 14:59:50 2023 +0200 Invoke directly the console method to not generate an error in our code --- examples/sdk/node/src/index.ts | 2 +- packages/node/README.md | 80 +++++++++---------- packages/node/src/BacktraceClient.ts | 2 +- .../BacktraceDatabaseFileStorageProvider.ts | 4 +- packages/sdk-core/README.md | 5 ++ packages/sdk-core/src/BacktraceCoreClient.ts | 2 +- .../BacktraceDatabaseConfiguration.ts | 8 +- .../events/ConsoleEventSubscriber.ts | 3 +- .../src/modules/database/BacktraceDatabase.ts | 2 +- .../databaseContextMemoryStorageTests.spec.ts | 2 +- .../databaseContextValidationTests.spec.ts | 2 +- .../database/databaseRecordBatchTests.spec.ts | 4 +- .../tests/database/databaseSendTests.spec.ts | 2 +- .../tests/database/databaseSetupTests.spec.ts | 4 +- .../database/databaseStorageFlowTests.spec.ts | 2 +- tools/rollup-plugin/README.md | 46 +++++++++++ tools/sourcemap-tools/README.md | 5 ++ tools/vite-plugin/README.md | 46 +++++++++++ tools/webpack-plugin/README.md | 45 +++++++++++ 19 files changed, 203 insertions(+), 63 deletions(-) create mode 100644 packages/sdk-core/README.md create mode 100644 tools/rollup-plugin/README.md create mode 100644 tools/sourcemap-tools/README.md create mode 100644 tools/vite-plugin/README.md create mode 100644 tools/webpack-plugin/README.md diff --git a/examples/sdk/node/src/index.ts b/examples/sdk/node/src/index.ts index e0c15d46..aea7327a 100644 --- a/examples/sdk/node/src/index.ts +++ b/examples/sdk/node/src/index.ts @@ -21,7 +21,7 @@ const client = BacktraceClient.initialize({ }, }, database: { - enabled: true, + enable: true, path: path.join(process.cwd(), 'database'), captureNativeCrashes: true, createDatabaseDirectory: true, diff --git a/packages/node/README.md b/packages/node/README.md index 5eff02b3..071a979a 100644 --- a/packages/node/README.md +++ b/packages/node/README.md @@ -194,7 +194,7 @@ and manual breadcrumbs can also be added. | `intercept` | (breadcrumb: RawBreadcrumb) => RawBreadcrumb \| undefined; | Inspects breadcrumb and allows to modify it. If the undefined value is being returned from the method, no breadcrumb will be added to the breadcrumb storage. | All Breadcrumbs |
  • - [ ]
| ```ts -import { BacktraceClient, BacktraceConfiguration } from '@backtrace-labs/ndoe'; +import { BacktraceClient, BacktraceConfiguration } from '@backtrace-labs/node'; // BacktraceClientOptions const options: BacktraceConfiguration = { @@ -259,70 +259,64 @@ client.metrics?.send(); ### Offline database support -The Backtrace Node SDK allows to store generated reports and crashes on the hard drive before sending them to Backtrace. -Based on your node configuration, your application might crash before the SDK finishes submitting data. In addition to -that if the application user has a slow Internet connection, your application might wait in a closing window until the -HTTP submission finishes. To prevent this situation, we recommend to use the database solution. By using it, you can: +The Backtrace Node SDK can cache generated reports and crashes to local disk before sending them to Backtrace. This is +recommended; in certain configurations Node applications can crash before the SDK finishes submitting data, and under +slow internet conditions your application might wait in a closing window until the HTTP submission finishes. In such an +event occurs cached reports will be sent on next application launch. + +With offline database support you can: - cache your reports when the user doesn't have Internet connection or the service is unavailable, -- capture crashes -- manually decide when to send them or not +- capture crashes, +- manually decide when to send them or not. By default the offline database support is disabled. To enable it, please add "enable: true" and the path to the directory where Backtrace can store crash data. +```ts +const client = BacktraceClient.initialize({ + // ignoring all but database config for simplicity + database: { + enable: true, + path: '/path/to/the/database/directory', + captureNativeCrashes: true, + }, +}); + +// manually send and keep the data on connection issue +client.database.send(); +// manually send and remove all data no matter if received success or not. +client.database.flush(); +``` + #### Database Configuration | Option Name | Type | Description | Default | Required? | | ------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------ | -| `enabled` | Boolean | Determine if the Database is enabled. | false |
  • - [x]
| -| `path` | String | Path where the SDK can store data. | - |
  • - [x]
| -| `createDatabaseDirectory` | Boolean | Determine if the directory should be auto created by the SDK. | true | | +| `enabled` | Boolean | Enable/disable offline database support. | false |
  • - [x]
| +| `path` | String | Local storage path for crash data. | - |
  • - [x]
| +| `createDatabaseDirectory` | Boolean | Allow the SDK to create the offline database directory.. | true | | `autoSend` | Boolean | Sends reports to the server based on the retry settings. If the value is set to 'false', you can use the Flush or Send methods as an alternative. | true | | `maximumNumberOfRecords` | Number | The maximum number of reports stored in the offline database. When the limit is reached, the oldest reports are removed. If the value is equal to '0', then no limit is set. | 8 | | `retryInterval` | Number | The amount of time (in ms) to wait between retries if the database is unable to send a report. | 60 000 | | `maximumRetries` | Number | The maximum number of retries to attempt if the database is unable to send a report. | 3 | -| `captureNativeCrashes` | Boolean | Captures and symbolicates stack traces for native crashes if the runtime supports this. A crash report is generated, stored locally, and uploaded upon next start. | false | +| `captureNativeCrashes` | Boolean | Capture and symbolicate stack traces for native crashes if the runtime supports this. A crash report is generated, stored locally, and uploaded upon next start. | false | --- #### Native crash support -The Backtrace Node SDK allows to capture native crashes generated by the node application such as Assert/OOM crashes. In -order to collect them, the SDK uses the Node's `process.report` API. After setting up the native crash support, your -`process.report` settings might be overridden and your crash data might be created in the database directory. +The Backtrace Node SDK can capture native crashes generated by a Node application such as Assert/OOM crashes. In order +to collect them, the SDK uses the Node's `process.report` API. After setting up the native crash support, your +`process.report` settings may be overridden and your crash data might be created in the database directory. -Database records sent in the next session might not have some information about the crashing session such as attributes -or breadcrumbs. To reduce database record size, attachment support was limited only to file attachments. +Database records sent in the next session may not have some information about the crashing session such as attributes or +breadcrumbs. To reduce database record size, attachment support was limited only to file attachments. #### Manual database operations -Database support is available in the client options. You can use it to manually operate on database records. The -database object allows you to: - -- add manually your Backtrace data, -- get all records, -- count all records, -- dispose of the database, -- remove the record, -- flush all records - send and forget, -- send manually all records. - -```ts -const client = BacktraceClient.initialize({ - // ignoring all but database config for simplicity - database: { - enabled: true, - path: '/path/to/the/database/directory', - captureNativeCrashes: true, - }, -}); - -// manuall send and keep the data on connection issue -client.database.send(); -// manuall send and remove all data no matter if received success or not. -client.database.flush(); -``` +Database support is available in the client options with the BacktraceDatabase object. You can use it to manually +operate on database records. Options are detailed in [BacktraceDatabase Methods](#backtracedatabase-methods). ## Advanced SDK Features @@ -385,7 +379,7 @@ The following options are available for the BacktraceClientOptions passed when i | Name | Return Type | Description | | ----------------------------------------------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `enable` | Boolean | Determines if the database is enabled | +| `enabled` | Boolean | Determines if the database is enabled | | `start()` | Boolean | Starts the database | | `add(backtraceData: Backtracedata, attachments: BacktraceAttachment[])` | BacktraceDatabaseRecord \| undefined | Adds manually a data object to the database. If the database is not available or the record cannot be stored on the hard drive, the add method can return undefined. | | `get()` | BacktraceDatabaseRecord[] | Returns all records stored in the database | diff --git a/packages/node/src/BacktraceClient.ts b/packages/node/src/BacktraceClient.ts index dd780cc9..926b3867 100644 --- a/packages/node/src/BacktraceClient.ts +++ b/packages/node/src/BacktraceClient.ts @@ -209,7 +209,7 @@ export class BacktraceClient extends BacktraceCoreClient { return; } - if (!this.options.database?.enabled) { + if (!this.options.database?.enable) { return; } diff --git a/packages/node/src/database/BacktraceDatabaseFileStorageProvider.ts b/packages/node/src/database/BacktraceDatabaseFileStorageProvider.ts index 3a06bd04..288ead44 100644 --- a/packages/node/src/database/BacktraceDatabaseFileStorageProvider.ts +++ b/packages/node/src/database/BacktraceDatabaseFileStorageProvider.ts @@ -25,11 +25,11 @@ export class BacktraceDatabaseFileStorageProvider implements BacktraceDatabaseSt if (!options) { return undefined; } - if (!options.enabled) { + if (!options.enable) { return undefined; } - if (options.enabled && !options.path) { + if (options.enable && !options.path) { throw new Error( 'Missing mandatory path to the database. Please define the database.path option in the configuration.', ); diff --git a/packages/sdk-core/README.md b/packages/sdk-core/README.md new file mode 100644 index 00000000..1c9944db --- /dev/null +++ b/packages/sdk-core/README.md @@ -0,0 +1,5 @@ +# **Backtrace SDK core** + +[Backtrace](https://backtrace.io) captures and reports handled and unhandled exceptions in your production software so you can manage application quality through the complete product lifecycle. + +The [@backtrace-labs/core](#) SDK connects all JavasSript SDKs created by Backtrace on all platforms. In this package you can find the common code shared by all our modules. For platform-specific implementation or overrides, please visit our repository https://github.com/backtrace-labs/backtrace-javascript \ No newline at end of file diff --git a/packages/sdk-core/src/BacktraceCoreClient.ts b/packages/sdk-core/src/BacktraceCoreClient.ts index eea0a56a..428ca4fd 100644 --- a/packages/sdk-core/src/BacktraceCoreClient.ts +++ b/packages/sdk-core/src/BacktraceCoreClient.ts @@ -125,7 +125,7 @@ export abstract class BacktraceCoreClient { ]); this.attachments = options.attachments ?? []; - if (databaseStorageProvider && options?.database?.enabled === true) { + if (databaseStorageProvider && options?.database?.enable === true) { this._database = new BacktraceDatabase( this.options.database, databaseStorageProvider, diff --git a/packages/sdk-core/src/model/configuration/BacktraceDatabaseConfiguration.ts b/packages/sdk-core/src/model/configuration/BacktraceDatabaseConfiguration.ts index cf553022..f5a131a2 100644 --- a/packages/sdk-core/src/model/configuration/BacktraceDatabaseConfiguration.ts +++ b/packages/sdk-core/src/model/configuration/BacktraceDatabaseConfiguration.ts @@ -2,7 +2,7 @@ export interface EnabledBacktraceDatabaseConfiguration { /** * Determine if the Database is enabled */ - enabled: true; + enable: true; /** * Path where the SDK can store data. */ @@ -46,11 +46,11 @@ export interface EnabledBacktraceDatabaseConfiguration { } export interface DisabledBacktraceDatabaseConfiguration - extends Omit, 'enabled'> { + extends Omit, 'enable'> { /** - * Determine if the Database is enabled + * Determine if the Database is enable */ - enabled?: false; + enable?: false; } export type BacktraceDatabaseConfiguration = diff --git a/packages/sdk-core/src/modules/breadcrumbs/events/ConsoleEventSubscriber.ts b/packages/sdk-core/src/modules/breadcrumbs/events/ConsoleEventSubscriber.ts index 46fa384e..1ee4fd13 100644 --- a/packages/sdk-core/src/modules/breadcrumbs/events/ConsoleEventSubscriber.ts +++ b/packages/sdk-core/src/modules/breadcrumbs/events/ConsoleEventSubscriber.ts @@ -38,10 +38,9 @@ export class ConsoleEventSubscriber implements BreadcrumbsEventSubscriber { breadcrumbsManager: BreadcrumbsManager, ) { const originalMethod = console[name] as ConsoleMethod; - const defaultImplementation = originalMethod.bind(console); (console[name] as ConsoleMethod) = (...args: unknown[]) => { - defaultImplementation.apply(console, args); + originalMethod(...args); const message = this._formatter(...args); breadcrumbsManager.addBreadcrumb(message, level, BreadcrumbType.Log); }; diff --git a/packages/sdk-core/src/modules/database/BacktraceDatabase.ts b/packages/sdk-core/src/modules/database/BacktraceDatabase.ts index 271b2e6f..71ff6d53 100644 --- a/packages/sdk-core/src/modules/database/BacktraceDatabase.ts +++ b/packages/sdk-core/src/modules/database/BacktraceDatabase.ts @@ -43,7 +43,7 @@ export class BacktraceDatabase { return this._enabled; } - if (this._options?.enabled === false) { + if (this._options?.enable === false) { return false; } diff --git a/packages/sdk-core/tests/database/databaseContextMemoryStorageTests.spec.ts b/packages/sdk-core/tests/database/databaseContextMemoryStorageTests.spec.ts index 7bf850be..2e032f78 100644 --- a/packages/sdk-core/tests/database/databaseContextMemoryStorageTests.spec.ts +++ b/packages/sdk-core/tests/database/databaseContextMemoryStorageTests.spec.ts @@ -7,7 +7,7 @@ import { testStorageProvider } from '../mocks/testStorageProvider'; describe('Database context memory storage tests', () => { const testDatabaseSettings = { - enabled: true, + enable: true, autoSend: false, // this option doesn't matter because we mock the database provider // interface. However, if bug happen we want to be sure to not create diff --git a/packages/sdk-core/tests/database/databaseContextValidationTests.spec.ts b/packages/sdk-core/tests/database/databaseContextValidationTests.spec.ts index 41cfda12..cc39c5ee 100644 --- a/packages/sdk-core/tests/database/databaseContextValidationTests.spec.ts +++ b/packages/sdk-core/tests/database/databaseContextValidationTests.spec.ts @@ -7,7 +7,7 @@ import { testStorageProvider } from '../mocks/testStorageProvider'; describe('Database context validation tests', () => { describe('Record overflow tests', () => { const testDatabaseSettings: BacktraceDatabaseConfiguration = { - enabled: true, + enable: true, autoSend: false, // this option doesn't matter because we mock the database provider // interface. However, if bug happen we want to be sure to not create diff --git a/packages/sdk-core/tests/database/databaseRecordBatchTests.spec.ts b/packages/sdk-core/tests/database/databaseRecordBatchTests.spec.ts index cc1a0ba0..9e016284 100644 --- a/packages/sdk-core/tests/database/databaseRecordBatchTests.spec.ts +++ b/packages/sdk-core/tests/database/databaseRecordBatchTests.spec.ts @@ -23,7 +23,7 @@ describe('Database record batch tests', () => { const client = BacktraceTestClient.buildFakeClient( { database: { - enabled: true, + enable: true, autoSend: true, path: path.join(__dirname, 'database'), maximumRetries, @@ -56,7 +56,7 @@ describe('Database record batch tests', () => { const client = BacktraceTestClient.buildFakeClient( { database: { - enabled: true, + enable: true, autoSend: true, path: path.join(__dirname, 'database'), maximumRetries, diff --git a/packages/sdk-core/tests/database/databaseSendTests.spec.ts b/packages/sdk-core/tests/database/databaseSendTests.spec.ts index 63b01417..919219ba 100644 --- a/packages/sdk-core/tests/database/databaseSendTests.spec.ts +++ b/packages/sdk-core/tests/database/databaseSendTests.spec.ts @@ -9,7 +9,7 @@ describe('Database send tests', () => { jest.clearAllMocks(); }); const testDatabaseSettings: BacktraceDatabaseConfiguration = { - enabled: true, + enable: true, autoSend: false, // this option doesn't matter because we mock the database provider // interface. However, if bug happen we want to be sure to not create diff --git a/packages/sdk-core/tests/database/databaseSetupTests.spec.ts b/packages/sdk-core/tests/database/databaseSetupTests.spec.ts index c0b4ab63..52b0097d 100644 --- a/packages/sdk-core/tests/database/databaseSetupTests.spec.ts +++ b/packages/sdk-core/tests/database/databaseSetupTests.spec.ts @@ -43,7 +43,7 @@ describe('Database setup tests', () => { it('Should not enable the database if the enable option is set to false', () => { const database = new BacktraceDatabase( - { enabled: false }, + { enable: false }, testStorageProvider, new BacktraceReportSubmission( { @@ -62,7 +62,7 @@ describe('Database setup tests', () => { it('Should not enable the database if the storage is not prepared', () => { const database = new BacktraceDatabase( { - enabled: true, + enable: true, path: '/path/to/fake/dir', }, testStorageProvider, diff --git a/packages/sdk-core/tests/database/databaseStorageFlowTests.spec.ts b/packages/sdk-core/tests/database/databaseStorageFlowTests.spec.ts index baadafef..7682e5be 100644 --- a/packages/sdk-core/tests/database/databaseStorageFlowTests.spec.ts +++ b/packages/sdk-core/tests/database/databaseStorageFlowTests.spec.ts @@ -6,7 +6,7 @@ import { testStorageProvider } from '../mocks/testStorageProvider'; describe('Database storage provider flow tests', () => { const testDatabaseSettings = { - enabled: true, + enable: true, autoSend: false, // this option doesn't matter because we mock the database provider // interface. However, if bug happen we want to be sure to not create diff --git a/tools/rollup-plugin/README.md b/tools/rollup-plugin/README.md new file mode 100644 index 00000000..0fae39bd --- /dev/null +++ b/tools/rollup-plugin/README.md @@ -0,0 +1,46 @@ +# @backtrace-labs/rollup-plugin +If you're using rollup as your project bundler, you can use `@backtrace-labs/rollup-plugin` to automate working with sourcemaps. + +[(Source Map feature documentation)](https://docs.saucelabs.com/error-reporting/platform-integrations/source-map/) + +## Enable Source Maps for Your Application + +Set `sourcemap` in `output` to `true` in your `rollup.config.js`: + +```js +module.exports = { + build: { + sourcemap: true + } +} +``` + +If you're using code transpiler plugins (such as Typescript), ensure to enable source-mapping there as well. + +## Set up `@backtrace-labs/rollup-plugin` + +### Construct an upload URL + +A specific URL is required to upload source maps. Follow [these instructions](https://docs.saucelabs.com/error-reporting/project-setup/submission-url/) to create an upload URL for the `sourcemap` endpoint with a `symbol-post` token. + +### Install `@backtrace-labs/rollup-plugin` as a developer dependency: + +```bash +> npm install --save-dev @backtrace-labs/rollup-plugin +``` + +### Add it to your `plugins` array in `rollup.config.js`: + +```js +import { BacktracePlugin } from '@backtrace-labs/rollup-plugin'; +// or +const { BacktracePlugin } = require('@backtrace-labs/rollup-plugin'); + +module.exports = { + // other configuration + plugins: [new BacktracePlugin({ + // enable upload only on production builds + uploadUrl: process.env.NODE_ENV === "production" ? "" : undefined + })] +} +``` \ No newline at end of file diff --git a/tools/sourcemap-tools/README.md b/tools/sourcemap-tools/README.md new file mode 100644 index 00000000..bb5ccccd --- /dev/null +++ b/tools/sourcemap-tools/README.md @@ -0,0 +1,5 @@ +# **Backtrace Source maps tools** + +[Backtrace](https://backtrace.io) captures and reports handled and unhandled exceptions in your production software so you can manage application quality through the complete product lifecycle. + +The [@backtrace-labs/sourcemap-tools](#) SDK connects all source maps tools created by Backtrace on all platforms. In this package you can find the common code shared by all our modules. For platform-specific implementation or overrides, please visit our repository https://github.com/backtrace-labs/backtrace-javascript \ No newline at end of file diff --git a/tools/vite-plugin/README.md b/tools/vite-plugin/README.md new file mode 100644 index 00000000..d73b5995 --- /dev/null +++ b/tools/vite-plugin/README.md @@ -0,0 +1,46 @@ +# @backtrace-labs/vite-plugin +If you're using Vite as your project bundler, you can use `@backtrace-labs/vite-plugin` to automate working with sourcemaps. + +[(Source Map feature documentation)](https://docs.saucelabs.com/error-reporting/platform-integrations/source-map/) + +## Enable Source Maps for Your Application + +Set `sourcemap` in `output` to `true` in your `vite.config.js`: + +```js +module.exports = { + build: { + sourcemap: true + } +} +``` + +If you're using code transpiler plugins (such as Typescript), ensure to enable source-mapping there as well. + +## Set up `@backtrace-labs/vite-plugin` + +### Construct an upload URL + +A specific URL is required to upload source maps. Follow [these instructions](https://docs.saucelabs.com/error-reporting/project-setup/submission-url/) to create an upload URL for the `sourcemap` endpoint with a `symbol-post` token. + +### Install `@backtrace-labs/vite-plugin` as a developer dependency: + +```bash +> npm install --save-dev @backtrace-labs/vite-plugin +``` + +### Add it to your `plugins` array in `vite.config.js`: + +```js +import { BacktracePlugin } from '@backtrace-labs/vite-plugin'; +// or +const { BacktracePlugin } = require('@backtrace-labs/vite-plugin'); + +module.exports = { + // other configuration + plugins: [new BacktracePlugin({ + // enable upload only on production builds + uploadUrl: process.env.NODE_ENV === "production" ? "" : undefined + })] +} +``` \ No newline at end of file diff --git a/tools/webpack-plugin/README.md b/tools/webpack-plugin/README.md new file mode 100644 index 00000000..c7a33550 --- /dev/null +++ b/tools/webpack-plugin/README.md @@ -0,0 +1,45 @@ +# @backtrace-labs/webpack-plugin +If you're using Webpack as your project bundler, you can use `@backtrace-labs/webpack-plugin` to automate working with sourcemaps. + +[(Source Map feature documentation)](https://docs.saucelabs.com/error-reporting/platform-integrations/source-map/) + +## Enable Source Maps for Your Application + +Set `devtool` to `source-map` in your `webpack.config.js`: + +```js +module.exports = { + devtool: 'source-map', + // other configuration +} +``` + +If you're using code transpiler plugins (such as Typescript), ensure to enable `source-mapping` there as well. + +## Set up `@backtrace-labs/webpack-plugin` + +### Construct an upload URL + +A specific URL is required to upload source maps. Follow [these instructions](https://docs.saucelabs.com/error-reporting/project-setup/submission-url/) to create an upload URL for the `sourcemap` endpoint with a `symbol-post` token. + +### Install `@backtrace-labs/webpack-plugin` as a developer dependency: + +```bash +> npm install --save-dev @backtrace-labs/webpack-plugin +``` + +### Add it to your `plugins` array in `webpack.config.js`: + +```js +import { BacktracePlugin } from '@backtrace-labs/webpack-plugin'; +// or +const { BacktracePlugin } = require('@backtrace-labs/webpack-plugin'); + +module.exports = { + // other configuration + plugins: [new BacktracePlugin({ + // enable upload only on production builds + uploadUrl: process.env.NODE_ENV === "production" ? "" : undefined + })] +} +``` \ No newline at end of file From 1ea417482e25a4a5dc1484ca78e05fcbae426d93 Mon Sep 17 00:00:00 2001 From: Konrad Dysput Date: Mon, 28 Aug 2023 17:48:06 +0200 Subject: [PATCH 8/9] Enable in the end --- packages/sdk-core/src/BacktraceCoreClient.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/sdk-core/src/BacktraceCoreClient.ts b/packages/sdk-core/src/BacktraceCoreClient.ts index a5c9bec0..451a6840 100644 --- a/packages/sdk-core/src/BacktraceCoreClient.ts +++ b/packages/sdk-core/src/BacktraceCoreClient.ts @@ -90,11 +90,12 @@ export abstract class BacktraceCoreClient { private readonly _attributeProvider: AttributeManager; private readonly _metrics?: BacktraceMetrics; private readonly _database?: BacktraceDatabase; - private _enabled = true; private readonly _sessionProvider: BacktraceSessionProvider; private readonly _sdkOptions: SdkOptions; protected readonly options: BacktraceConfiguration; + private _enabled = false; + protected constructor(private readonly _setup: CoreClientSetup) { this.options = _setup.options; this._sdkOptions = _setup.sdkOptions; @@ -148,6 +149,7 @@ export abstract class BacktraceCoreClient { } this.initialize(); + this._enabled = true; } /** From 275dc2f0b2d87468d88e4bd49454d0ec31c42d71 Mon Sep 17 00:00:00 2001 From: Konrad Dysput Date: Mon, 28 Aug 2023 17:50:08 +0200 Subject: [PATCH 9/9] Drop the instance on dispose --- packages/browser/src/BacktraceClient.ts | 1 + packages/node/src/BacktraceClient.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/browser/src/BacktraceClient.ts b/packages/browser/src/BacktraceClient.ts index 0fb63271..46acda48 100644 --- a/packages/browser/src/BacktraceClient.ts +++ b/packages/browser/src/BacktraceClient.ts @@ -80,6 +80,7 @@ export class BacktraceClient extends BacktraceCoreClient { public dispose(): void { this._disposeController.abort(); super.dispose(); + BacktraceClient._instance = undefined; } private captureUnhandledErrors(captureUnhandledExceptions = true, captureUnhandledRejections = true) { diff --git a/packages/node/src/BacktraceClient.ts b/packages/node/src/BacktraceClient.ts index 045046f5..9f405ecd 100644 --- a/packages/node/src/BacktraceClient.ts +++ b/packages/node/src/BacktraceClient.ts @@ -88,6 +88,7 @@ export class BacktraceClient extends BacktraceCoreClient { } super.dispose(); + BacktraceClient._instance = undefined; } private captureUnhandledErrors(captureUnhandledExceptions = true, captureUnhandledRejections = true) {