Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions packages/browser/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { IBrowserClient, TraceoOptions } from "./types/client";
import { Transport } from "./transport";
import { utils } from "./utils";
import { stacktrace } from "./exceptions/stacktrace";
import { Trace } from "./types/stacktrace";
import { BrowserIncidentType } from "./types/transport";

export abstract class BrowserClient implements IBrowserClient {
public headers!: { [key: string]: any };
Expand All @@ -17,13 +20,29 @@ export abstract class BrowserClient implements IBrowserClient {
public abstract postInitSDK(): void;

public sendError(error: Error): void {
const err = this.constructError(error);
this.transport.send<BrowserIncidentType>(err, this.headers);
}

private constructError(error: Error): BrowserIncidentType {
const browser = utils.browserDetails();
this.transport.send({
type: error.name,
message: error.message,
stack: error.stack as string,

const type = error.name;
const message = error.message;

const stack = error.stack || "";

const traces: Trace[] = stacktrace.parse(stack);

const err: BrowserIncidentType = {
type,
message,
stack,
traces,
browser
}, this.headers);
};

return err;
}

private initSDK(): void {
Expand Down
68 changes: 68 additions & 0 deletions packages/browser/src/exceptions/stacktrace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Trace } from "../types/stacktrace";

const LINE_REGEXP = /\s*at\s*(?:(.+?)\s*\()?(?:(.+):(\d+):(\d+))?\)?/;
const EXTENSION_REGEXP = /\.(\w+)$/;
const CLASS_METHOD_REGEXP = /(.+)\.([^.]+)$/;

const EXCLUDED = ["<anonymous>"];

const parse = (stackTrace: string): Trace[] => {
const lines = stackTrace.split("\n");
const traces: Trace[] = [];

for (const line of lines) {
const stackTraceLine = parseStackTraceLine(line);
if (stackTraceLine) {
traces.push(stackTraceLine);
}
}

return traces;
};

const parseStackTraceLine = (line: string): Trace | null => {
const match = line.match(LINE_REGEXP);
if (!match || EXCLUDED.includes(match[1])) {
return null;
}

const [, method, file, lineStr, columnStr] = match;
const lineNo = parseOptionalInt(lineStr);
const columnNo = parseOptionalInt(columnStr);
const ext = getFileExtension(file);
const methodName = getFullMethodName(method);

return {
filename: file,
lineNo,
columnNo,
function: methodName,
extension: ext
};
};

const parseOptionalInt = (str?: string): number | null => {
return str ? parseInt(str, 10) : null;
};

const getFileExtension = (file?: string): string | null => {
if (!file) {
return null;
}

const match = file.match(EXTENSION_REGEXP);
return match ? match[1] : null;
};

const getFullMethodName = (method?: string): string | null => {
if (!method) {
return null;
}

const match = method.match(CLASS_METHOD_REGEXP);
return match ? `${match[1]}.${match[2]}` : method;
};

export const stacktrace = {
parse
};
6 changes: 3 additions & 3 deletions packages/browser/src/transport/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ITransport, RequestOptions } from "../types/transport";

export class FetchTransport implements ITransport {
private _options: RequestOptions;
export class FetchTransport<T> implements ITransport {
private _options: RequestOptions<T>;

constructor(options: RequestOptions) {
constructor(options: RequestOptions<T>) {
this._options = options;
}

Expand Down
14 changes: 7 additions & 7 deletions packages/browser/src/transport/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ export class Transport {
this._options = options;
}

public send(body: object, headers: Dictionary<string>) {
public send<T>(body: T, headers: Dictionary<string>) {
try {
const options = this.requestOptions(body, headers);
this.transport(options).request();
const options = this.requestOptions<T>(body, headers);
this.transport<T>(options).request();
} catch (error) {
console.log("Error sending data to traceo: ", error);
}
}

private transport(options: RequestOptions) {
private transport<T>(options: RequestOptions<T>) {
if (window.XMLHttpRequest && !window.fetch) {
return new XhrTransport(options);
return new XhrTransport<T>(options);
}

return new FetchTransport(options);
return new FetchTransport<T>(options);
}

private requestOptions(body: {}, headers: Dictionary<string>): RequestOptions {
private requestOptions<T>(body: T, headers: Dictionary<string>): RequestOptions<T> {
const reqUrl = this.clientURL;

// http://localhost:3000/api/worker/incident/app-id
Expand Down
6 changes: 3 additions & 3 deletions packages/browser/src/transport/xhr.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ITransport, RequestOptions } from "../types/transport";

const XHR_DONE = 4;
export class XhrTransport implements ITransport {
public _options: RequestOptions;
export class XhrTransport<T> implements ITransport {
public _options: RequestOptions<T>;

constructor(options: RequestOptions) {
constructor(options: RequestOptions<T>) {
this._options = options;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/browser/src/types/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ export type BrowserInfoType = {
version?: string;
};
url: string;
};
};
12 changes: 12 additions & 0 deletions packages/browser/src/types/stacktrace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface Trace {
filename?: string;
function?: string | null;
lineNo?: number | null;
columnNo?: number | null;
internal?: boolean;
absPath?: string | null;
extension?: string | null;
preCode?: string[] | null;
code?: string | null;
postCode?: string[] | null;
}
6 changes: 4 additions & 2 deletions packages/browser/src/types/transport.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { BrowserInfoType } from "./browser";
import { Dictionary } from "./client";
import { Trace } from "./stacktrace";

export interface ITransport {
request(): Promise<void>;
}

export type RequestOptions = {
body: object;
export type RequestOptions<T> = {
body: T;
headers: Dictionary<string>;
url: string;
protocol: string; //"http" | "https"
Expand All @@ -20,4 +21,5 @@ export type BrowserIncidentType = {
message: string;
stack: string;
browser: BrowserInfoType;
traces: Trace[];
};