backtrace-js
Advanced tools
Comparing version 1.0.0-alpha.4 to 1.0.0-alpha.5
import { BacktraceReport } from './model/backtraceReport'; | ||
import { BacktraceResult } from './model/backtraceResult'; | ||
export declare class BacktraceApi { | ||
private backtraceUri; | ||
private timeout; | ||
private ignoreSslCert; | ||
private axiosInstance; | ||
@@ -8,0 +5,0 @@ constructor(backtraceUri: string, timeout: number, ignoreSslCert: boolean); |
@@ -11,2 +11,5 @@ import { BacktraceClientOptions } from './model/backtraceClientOptions'; | ||
breadcrumbs: Breadcrumbs; | ||
readonly attributes: { | ||
[index: string]: any; | ||
}; | ||
private _backtraceApi; | ||
@@ -17,3 +20,3 @@ private _clientRateLimit; | ||
* Memorize selected values from application. | ||
* Memorized attributes will be available in your next Backtrace report. | ||
* Memorized attributes will be available in your Backtrace report. | ||
* Memorized attributes will be only available for one report. | ||
@@ -24,2 +27,10 @@ * @param key attribute key | ||
memorize(key: string, value: any): void; | ||
/** | ||
* Set custom client attribute | ||
* Memorized attributes will be available in your Backtrace report. | ||
* Memorized attributes will be only available for one report. | ||
* @param key attribute key | ||
* @param value attribute value | ||
*/ | ||
setAttribute(key: string, value: any): void; | ||
createReport(payload: Error | string, reportAttributes?: object | undefined, attachment?: string | object): BacktraceReport; | ||
@@ -45,6 +56,6 @@ /** | ||
private getSubmitUrl; | ||
private combineClientAttributes; | ||
private registerHandlers; | ||
private registerPromiseHandler; | ||
private registerGlobalHandler; | ||
private readAttributes; | ||
} |
@@ -6,3 +6,5 @@ import { BacktraceReport } from '../model/backtraceReport'; | ||
token?: string; | ||
userAttributes: object; | ||
userAttributes: object | { | ||
[index: string]: any; | ||
}; | ||
ignoreSslCert: boolean; | ||
@@ -9,0 +11,0 @@ disableGlobalHandler: boolean; |
@@ -98,3 +98,2 @@ import FormData from 'form-data'; | ||
private readErrorAttributes; | ||
private readAttributes; | ||
private readAnnotation; | ||
@@ -101,0 +100,0 @@ private getSerializableError; |
@@ -55,8 +55,8 @@ import { BacktraceReport } from './../model/backtraceReport'; | ||
private readonly _rxId; | ||
readonly ObjectId: string; | ||
readonly Report: BacktraceReport; | ||
readonly Message: string; | ||
readonly Error: Error | undefined; | ||
readonly Status: BacktraceResultStatus; | ||
get ObjectId(): string; | ||
get Report(): BacktraceReport; | ||
get Message(): string; | ||
get Error(): Error | undefined; | ||
get Status(): BacktraceResultStatus; | ||
private constructor(); | ||
} |
{ | ||
"name": "backtrace-js", | ||
"version": "1.0.0-alpha.4", | ||
"version": "1.0.0-alpha.5", | ||
"description": "Backtrace.io error reporting tool for client-side applications", | ||
@@ -5,0 +5,0 @@ "browser": "./lib/index.js", |
@@ -62,2 +62,16 @@ # backtrace-js | ||
#### Breadcrumbs | ||
Add information about activity in your application to your error reports by calling `leaveBreadcrumb` when events happen. The breadcrumbs will appear in the Backtrace console along with the error object. | ||
Example: | ||
``` | ||
backtrace.leaveBreadcrumb( | ||
message, | ||
attributes, | ||
timestamp, | ||
logLevel, | ||
logType, | ||
); | ||
``` | ||
## Testing | ||
@@ -64,0 +78,0 @@ |
@@ -8,9 +8,16 @@ import axios, { AxiosInstance } from 'axios'; | ||
private axiosInstance: AxiosInstance; | ||
constructor( | ||
private backtraceUri: string, | ||
private timeout: number, | ||
private ignoreSslCert: boolean, | ||
) { | ||
this.axiosInstance = axios.create(); | ||
constructor(backtraceUri: string, timeout: number, ignoreSslCert: boolean) { | ||
this.axiosInstance = axios.create({ | ||
baseURL: backtraceUri, | ||
timeout, | ||
httpsAgent: ignoreSslCert | ||
? new Agent({ | ||
rejectUnauthorized: false, | ||
}) | ||
: globalAgent, | ||
headers: { | ||
'Content-Type': 'undefined', // https://stackoverflow.com/questions/39280438/fetch-missing-boundary-in-multipart-form-data-post | ||
}, | ||
}); | ||
} | ||
@@ -21,15 +28,3 @@ | ||
const formData = await report.toFormData(); | ||
const options = { | ||
baseURL: this.backtraceUri, | ||
timeout: this.timeout, | ||
httpsAgent: this.ignoreSslCert | ||
? new Agent({ | ||
rejectUnauthorized: false, | ||
}) | ||
: globalAgent, | ||
headers: { | ||
'Content-Type': 'undefined', // https://stackoverflow.com/questions/39280438/fetch-missing-boundary-in-multipart-form-data-post | ||
}, | ||
}; | ||
const result = await this.axiosInstance.post(this.backtraceUri, formData, options); | ||
const result = await this.axiosInstance.post('', formData); | ||
@@ -36,0 +31,0 @@ if (result.status === 429) { |
import { BacktraceApi } from './backtraceApi'; | ||
import { ClientRateLimit } from './clientRateLimit'; | ||
import { pageStartTime } from './index'; | ||
import { BacktraceClientOptions } from './model/backtraceClientOptions'; | ||
@@ -7,2 +8,3 @@ import { BacktraceReport } from './model/backtraceReport'; | ||
import { Breadcrumbs } from './model/breadcrumbs'; | ||
import { getBrowserName, getBrowserVersion, getOs, isMobile } from './utils/agentUtils'; | ||
/** | ||
@@ -14,2 +16,3 @@ * Backtrace client | ||
public breadcrumbs: Breadcrumbs; | ||
public readonly attributes: { [index: string]: any }; | ||
@@ -31,2 +34,6 @@ private _backtraceApi: BacktraceApi; | ||
this.registerHandlers(); | ||
this.attributes = { | ||
...this.readAttributes(), | ||
...this.options.userAttributes, | ||
}; | ||
} | ||
@@ -36,3 +43,3 @@ | ||
* Memorize selected values from application. | ||
* Memorized attributes will be available in your next Backtrace report. | ||
* Memorized attributes will be available in your Backtrace report. | ||
* Memorized attributes will be only available for one report. | ||
@@ -43,15 +50,24 @@ * @param key attribute key | ||
public memorize(key: string, value: any): void { | ||
(this.options.userAttributes as any)[key] = value; | ||
this.attributes[key] = value; | ||
} | ||
/** | ||
* Set custom client attribute | ||
* Memorized attributes will be available in your Backtrace report. | ||
* Memorized attributes will be only available for one report. | ||
* @param key attribute key | ||
* @param value attribute value | ||
*/ | ||
public setAttribute(key: string, value: any): void { | ||
this.attributes[key] = value; | ||
} | ||
public createReport( | ||
payload: Error | string, | ||
reportAttributes: object | undefined = {}, | ||
attachment?: string | object, | ||
payload: Error | string, | ||
reportAttributes: object | undefined = {}, | ||
attachment?: string | object, | ||
): BacktraceReport { | ||
// this.emit('new-report', payload, reportAttributes); | ||
const attributes = this.combineClientAttributes(reportAttributes); | ||
const breadcrumbs = this.breadcrumbs.isEnabled() ? this.breadcrumbs.get() : undefined; | ||
const report = new BacktraceReport(payload, attributes, breadcrumbs, attachment); | ||
const report = new BacktraceReport(payload, reportAttributes, breadcrumbs, attachment); | ||
report.send = (callback) => { | ||
@@ -108,5 +124,5 @@ this.sendAsync(report) | ||
public reportSync( | ||
payload: Error | string, | ||
reportAttributes: object | undefined = {}, | ||
attachment?: string | object | ||
payload: Error | string, | ||
reportAttributes: object | undefined = {}, | ||
attachment?: string | object, | ||
): BacktraceResult { | ||
@@ -128,2 +144,6 @@ const report = this.createReport(payload, reportAttributes, attachment); | ||
} | ||
// apply default attributes | ||
report.addObjectAttributes(this.attributes); | ||
this._backtraceApi | ||
@@ -136,11 +156,11 @@ .send(report) | ||
{ | ||
error: result.Error, | ||
message: result.Message, | ||
objectId: result.ObjectId, | ||
}, | ||
error: result.Error, | ||
message: result.Message, | ||
objectId: result.ObjectId, | ||
}, | ||
Date.now(), | ||
'error', | ||
'log' | ||
'error', | ||
'log', | ||
); | ||
}; | ||
} | ||
@@ -200,12 +220,2 @@ if (callback) { | ||
private combineClientAttributes(attributes: object = {}): object { | ||
if (!attributes) { | ||
attributes = {}; | ||
} | ||
return { | ||
...attributes, | ||
...this.options.userAttributes, | ||
}; | ||
} | ||
private registerHandlers(): void { | ||
@@ -246,2 +256,40 @@ if (!this.options.disableGlobalHandler) { | ||
} | ||
private readAttributes(): { [index: string]: any } { | ||
const browserName = getBrowserName(); | ||
return { | ||
application: document.title, | ||
'process.age': Math.floor((new Date().getTime() - pageStartTime.getTime()) / 1000), | ||
hostname: window.location && window.location.hostname, | ||
referer: window.location && window.location.href, | ||
'user.agent.full': navigator.userAgent, | ||
'location.port': document.location.port, | ||
'location.protocol': document.location.protocol, | ||
'location.origin': window.location.origin, | ||
'location.href': window.location.href || document.URL, | ||
language: navigator.language, | ||
'browser.name': browserName, | ||
'browser.version': getBrowserVersion(browserName), | ||
'browser.platform': navigator.platform, | ||
'browser.vendor': navigator.vendor, | ||
'cookies.enable': navigator.cookieEnabled, | ||
'document.domain': document.domain, | ||
'document.baseURI': document.baseURI, | ||
'document.title': document.title, | ||
'document.referrer': document.referrer, | ||
mobile: isMobile(), | ||
'localstorage.enable': !!window.localStorage, | ||
'uname.sysname': getOs(), | ||
'window.innerHeight': window.innerHeight, | ||
'window.innerWidth': window.innerWidth, | ||
'window.outerHeight': window.outerHeight, | ||
'window.outerWidth': window.outerWidth, | ||
'window.pageXOffset': window.pageXOffset, | ||
'window.pageYOffset': window.pageYOffset, | ||
'window.screenX': window.screenX, | ||
'window.screenY': window.screenY, | ||
'window.screenLeft': window.screenLeft, | ||
'window.screenTop': window.screenTop, | ||
}; | ||
} | ||
} |
@@ -68,6 +68,6 @@ import { BacktraceClient } from './backtraceClient'; | ||
export function reportSync( | ||
data: Error | string, | ||
attributes: object | undefined = {}, | ||
attachment?: string | object, | ||
): BacktraceResult { | ||
data: Error | string, | ||
attributes: object | undefined = {}, | ||
attachment?: string | object, | ||
): BacktraceResult { | ||
if (!backtraceClient) { | ||
@@ -112,30 +112,24 @@ throw new Error('Must call initialize method first'); | ||
/** | ||
* Record an event in the breadcrumbs buffer | ||
* @param message description of event | ||
* @param attributes object of values related to event | ||
* @param timestamp time of event | ||
* @param level log level | ||
* @param type type of event (e.g. "USER") | ||
*/ | ||
export function leaveBreadcrumb( | ||
message: string, | ||
attributes?: object, | ||
timestamp?: number, | ||
level?: string, | ||
type?: string, | ||
) { | ||
if (!backtraceClient) { | ||
throw new Error('Must call initialize method first'); | ||
} | ||
if (!message) { | ||
throw new Error('Breadcrumb must include message'); | ||
} | ||
backtraceClient.breadcrumbs.add( | ||
message, | ||
attributes, | ||
timestamp, | ||
level, | ||
type, | ||
); | ||
/** | ||
* Record an event in the breadcrumbs buffer | ||
* @param message description of event | ||
* @param attributes object of values related to event | ||
* @param timestamp time of event | ||
* @param level log level | ||
* @param type type of event (e.g. "USER") | ||
*/ | ||
export function leaveBreadcrumb( | ||
message: string, | ||
attributes?: object, | ||
timestamp?: number, | ||
level?: string, | ||
type?: string, | ||
) { | ||
if (!backtraceClient) { | ||
throw new Error('Must call initialize method first'); | ||
} | ||
if (!message) { | ||
throw new Error('Breadcrumb must include message'); | ||
} | ||
backtraceClient.breadcrumbs.add(message, attributes, timestamp, level, type); | ||
} |
@@ -7,3 +7,3 @@ import { BacktraceReport } from '../model/backtraceReport'; | ||
public token?: string; | ||
public userAttributes: object = {}; | ||
public userAttributes: object | { [index: string]: any } = {}; | ||
@@ -18,3 +18,3 @@ public ignoreSslCert: boolean = false; | ||
public filter?: (report: BacktraceReport) => boolean = undefined; | ||
public breadcrumbLimit?: number = -1; | ||
@@ -21,0 +21,0 @@ |
@@ -5,8 +5,7 @@ // tslint:disable-next-line: no-var-requires | ||
import FormData from 'form-data'; | ||
import { pageStartTime } from '../index'; | ||
import { IBacktraceData } from '../model/backtraceData'; | ||
import { BacktraceStackTrace } from '../model/backtraceStackTrace'; | ||
import { Breadcrumbs } from '../model/breadcrumbs'; | ||
import { getBrowserName, getBrowserVersion, getOs, isMobile } from '../utils/agentUtils'; | ||
import { IBreadcrumb } from './breadcrumbs'; | ||
const crypto = window.crypto; | ||
@@ -84,7 +83,7 @@ /** | ||
constructor( | ||
private err: Error | string = '', | ||
private clientAttributes: { [index: string]: any } = {}, | ||
private breadcrumbs?: IBreadcrumb[], | ||
private attachment?: string | object, | ||
) { | ||
private err: Error | string = '', | ||
private clientAttributes: { [index: string]: any } = {}, | ||
private breadcrumbs?: IBreadcrumb[], | ||
private attachment?: string | object, | ||
) { | ||
if (!clientAttributes) { | ||
@@ -170,3 +169,3 @@ clientAttributes = {}; | ||
} | ||
data.attributes['guid'] = this.getGuid(); | ||
@@ -182,3 +181,3 @@ | ||
formData.append('upload_file', blob, 'upload_file.json'); | ||
if (this.breadcrumbs) { | ||
@@ -188,3 +187,3 @@ const breadcrumbBlob = new Blob([JSON.stringify(this.breadcrumbs)]); | ||
} | ||
if (this.attachment) { | ||
@@ -197,3 +196,3 @@ const attachmentBlob = new Blob([JSON.stringify(this.attachment)]); | ||
} | ||
public setSourceCodeOptions(tabWidth: number, contextLineCount: number) { | ||
@@ -218,6 +217,3 @@ this.tabWidth = tabWidth; | ||
private readBuiltInAttributes(): object { | ||
return { | ||
...this.readAttributes(), | ||
...this.readErrorAttributes(), | ||
}; | ||
return this.readErrorAttributes(); | ||
} | ||
@@ -228,5 +224,5 @@ | ||
} | ||
private getGuid(): string { | ||
let guid = window.localStorage.getItem('backtrace-guid') | ||
let guid = window.localStorage.getItem('backtrace-guid'); | ||
if (!guid) { | ||
@@ -282,39 +278,2 @@ guid = this.generateUuid(); | ||
private readAttributes(): object { | ||
const browserName = getBrowserName(); | ||
return { | ||
'process.age': Math.floor((new Date().getTime() - pageStartTime.getTime()) / 1000), | ||
hostname: window.location && window.location.hostname, | ||
referer: window.location && window.location.href, | ||
'user.agent.full': navigator.userAgent, | ||
'location.port': document.location.port, | ||
'location.protocol': document.location.protocol, | ||
'location.origin': window.location.origin, | ||
'location.href': window.location.href || document.URL, | ||
language: navigator.language, | ||
'browser.name': browserName, | ||
'browser.version': getBrowserVersion(browserName), | ||
'browser.platform': navigator.platform, | ||
'browser.vendor': navigator.vendor, | ||
'cookies.enable': navigator.cookieEnabled, | ||
'document.domain': document.domain, | ||
'document.baseURI': document.baseURI, | ||
'document.title': document.title, | ||
'document.referrer': document.referrer, | ||
mobile: isMobile(), | ||
'localstorage.enable': !!window.localStorage, | ||
'uname.sysname': getOs(), | ||
'window.innerHeight': window.innerHeight, | ||
'window.innerWidth': window.innerWidth, | ||
'window.outerHeight': window.outerHeight, | ||
'window.outerWidth': window.outerWidth, | ||
'window.pageXOffset': window.pageXOffset, | ||
'window.pageYOffset': window.pageYOffset, | ||
'window.screenX': window.screenX, | ||
'window.screenY': window.screenY, | ||
'window.screenLeft': window.screenLeft, | ||
'window.screenTop': window.screenTop, | ||
}; | ||
} | ||
private readAnnotation(): object { | ||
@@ -339,2 +298,7 @@ return { | ||
private getSerializableError() { | ||
if (typeof this.err === 'string') { | ||
return { | ||
message: this.err, | ||
}; | ||
} | ||
const serializableError: { [index: string]: string } = {}; | ||
@@ -341,0 +305,0 @@ const self = this; |
@@ -5,62 +5,62 @@ const typeManual = 'manual'; | ||
export interface IBreadcrumb { | ||
id: number, | ||
timestamp: number, | ||
level: string, | ||
type: string, | ||
message: string, | ||
attributes: object, | ||
id: number; | ||
timestamp: number; | ||
level: string; | ||
type: string; | ||
message: string; | ||
attributes: object; | ||
} | ||
export class Breadcrumbs { | ||
public static readonly attachmentName = 'bt-breadcrumbs-0'; | ||
private breadcrumbLimit: number = -1; | ||
private _breadcrumbs: IBreadcrumb[] = []; | ||
private id: number = 0; | ||
constructor(breadcrumbLimit?: number) { | ||
if (!breadcrumbLimit || breadcrumbLimit <= 0) { | ||
this.breadcrumbLimit = -1; | ||
return; | ||
} | ||
this.breadcrumbLimit = breadcrumbLimit; | ||
} | ||
public static readonly attachmentName = 'bt-breadcrumbs-0'; | ||
private breadcrumbLimit: number = -1; | ||
private _breadcrumbs: IBreadcrumb[] = []; | ||
private id: number = 0; | ||
public add( | ||
message: string, | ||
attributes={}, | ||
timestamp=this.getNowTimestamp(), | ||
level: string=defaultLevel, | ||
type: string=typeManual, | ||
) { | ||
// breadcrumbs are disabled | ||
if (this.breadcrumbLimit < 0) { | ||
return; | ||
} | ||
// if breadcrumbs array is full, purge oldest entry | ||
while (this._breadcrumbs.length === this.breadcrumbLimit) { | ||
this._breadcrumbs.shift(); | ||
} | ||
const breadcrumb = { | ||
id: this.id++, | ||
timestamp, | ||
level, | ||
type, | ||
message, | ||
attributes, | ||
}; | ||
this._breadcrumbs.push(breadcrumb); | ||
} | ||
public get() { | ||
return this._breadcrumbs; | ||
} | ||
public isEnabled() { | ||
return this.breadcrumbLimit > 0; | ||
} | ||
private getNowTimestamp(): number { | ||
return Date.now(); | ||
} | ||
constructor(breadcrumbLimit?: number) { | ||
if (!breadcrumbLimit || breadcrumbLimit <= 0) { | ||
this.breadcrumbLimit = -1; | ||
return; | ||
} | ||
this.breadcrumbLimit = breadcrumbLimit; | ||
} | ||
public add( | ||
message: string, | ||
attributes = {}, | ||
timestamp = this.getNowTimestamp(), | ||
level: string = defaultLevel, | ||
type: string = typeManual, | ||
) { | ||
// breadcrumbs are disabled | ||
if (this.breadcrumbLimit < 0) { | ||
return; | ||
} | ||
// if breadcrumbs array is full, purge oldest entry | ||
while (this._breadcrumbs.length === this.breadcrumbLimit) { | ||
this._breadcrumbs.shift(); | ||
} | ||
const breadcrumb = { | ||
id: this.id++, | ||
timestamp, | ||
level, | ||
type, | ||
message, | ||
attributes, | ||
}; | ||
this._breadcrumbs.push(breadcrumb); | ||
} | ||
public get() { | ||
return this._breadcrumbs; | ||
} | ||
public isEnabled() { | ||
return this.breadcrumbLimit > 0; | ||
} | ||
private getNowTimestamp(): number { | ||
return Date.now(); | ||
} | ||
} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
664565
1935
83
0