Skip to content

Commit 5e0671a

Browse files
authored
sdk-core, browser, node: add BacktraceApi (#335)
* sdk-core: add or move http request bodies and responses * sdk-core: change RequestBacktraceReportSubmission to use new http bodies * sdk-core: add BacktraceCoreApi * node: add BacktraceApi * browser: add BacktraceApi * browser: remove options class variable from BacktraceBrowserRequestHandler * node: remove options class variable from BacktraceNodeRequestHandler * sdk-core, node, browser: MR updates * sdk-core: rename http models * sdk-core: rename http models
1 parent 8ff22bd commit 5e0671a

26 files changed

+578
-35
lines changed

packages/browser/src/BacktraceApi.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { BacktraceCoreApi, BacktraceCoreApiOptions, BacktraceRequestHandler } from '@backtrace/sdk-core';
2+
import {
3+
BacktraceBrowserRequestHandler,
4+
BacktraceBrowserRequestHandlerOptions,
5+
} from './BacktraceBrowserRequestHandler.js';
6+
7+
export interface BacktraceApiOptions extends BacktraceCoreApiOptions {
8+
readonly requestHandlerOptions?: BacktraceBrowserRequestHandlerOptions;
9+
readonly requestHandler?: BacktraceRequestHandler;
10+
}
11+
12+
export class BacktraceApi extends BacktraceCoreApi {
13+
constructor(options: BacktraceApiOptions) {
14+
super(options, options.requestHandler ?? new BacktraceBrowserRequestHandler(options.requestHandlerOptions));
15+
}
16+
}

packages/browser/src/BacktraceBrowserRequestHandler.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import {
77
DEFAULT_TIMEOUT,
88
} from '@backtrace/sdk-core';
99

10+
export interface BacktraceBrowserRequestHandlerOptions {
11+
readonly timeout?: number;
12+
}
13+
1014
export class BacktraceBrowserRequestHandler implements BacktraceRequestHandler {
1115
private readonly UPLOAD_FILE_NAME = 'upload_file';
1216
private readonly _timeout: number;
@@ -18,14 +22,8 @@ export class BacktraceBrowserRequestHandler implements BacktraceRequestHandler {
1822
private readonly MULTIPART_HEADERS = {
1923
'Transfer-Encoding': 'chunked',
2024
};
21-
constructor(
22-
private readonly _options: {
23-
url: string;
24-
token?: string;
25-
timeout?: number;
26-
},
27-
) {
28-
this._timeout = this._options.timeout ?? DEFAULT_TIMEOUT;
25+
constructor(options?: BacktraceBrowserRequestHandlerOptions) {
26+
this._timeout = options?.timeout ?? DEFAULT_TIMEOUT;
2927
}
3028
public async postError<T>(
3129
submissionUrl: string,

packages/browser/src/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@ export {
1010
BacktraceStringAttachment,
1111
BacktraceUint8ArrayAttachment,
1212
BreadcrumbLogLevel,
13-
BreadcrumbType,
1413
BreadcrumbsEventSubscriber,
1514
BreadcrumbsManager,
15+
BreadcrumbType,
1616
JavaScriptEngine,
1717
RawBreadcrumb,
1818
SingleSessionProvider,
1919
V8StackTraceConverter,
2020
} from '@backtrace/sdk-core';
2121
export * from './agentDefinition.js';
22+
export * from './BacktraceApi.js';
2223
export * from './BacktraceBrowserRequestHandler.js';
2324
export * from './BacktraceClient.js';
2425
export * from './BacktraceConfiguration.js';

packages/node/src/BacktraceApi.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { BacktraceCoreApi, BacktraceCoreApiOptions, BacktraceRequestHandler } from '@backtrace/sdk-core';
2+
import { BacktraceNodeRequestHandler, BacktraceNodeRequestHandlerOptions } from './BacktraceNodeRequestHandler.js';
3+
4+
export interface BacktraceApiOptions extends BacktraceCoreApiOptions {
5+
readonly requestHandlerOptions?: BacktraceNodeRequestHandlerOptions;
6+
readonly requestHandler?: BacktraceRequestHandler;
7+
}
8+
9+
export class BacktraceApi extends BacktraceCoreApi {
10+
constructor(options: BacktraceApiOptions) {
11+
super(options, options.requestHandler ?? new BacktraceNodeRequestHandler(options.requestHandlerOptions));
12+
}
13+
}

packages/node/src/BacktraceNodeRequestHandler.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@ import FormData from 'form-data';
1111
import http, { ClientRequest, IncomingMessage } from 'http';
1212
import https from 'https';
1313
import { Readable } from 'stream';
14+
15+
export interface BacktraceNodeRequestHandlerOptions {
16+
readonly timeout?: number;
17+
readonly ignoreSslCertificate?: boolean;
18+
}
19+
1420
export class BacktraceNodeRequestHandler implements BacktraceRequestHandler {
1521
private readonly UPLOAD_FILE_NAME = 'upload_file';
1622
private readonly _timeout: number;
23+
private readonly _ignoreSslCertificate?: boolean;
1724

1825
private readonly JSON_HEADERS = {
1926
'Content-type': 'application/json',
@@ -24,15 +31,9 @@ export class BacktraceNodeRequestHandler implements BacktraceRequestHandler {
2431
'Transfer-Encoding': 'chunked',
2532
};
2633

27-
constructor(
28-
private readonly _options: {
29-
url: string;
30-
token?: string;
31-
timeout?: number;
32-
ignoreSslCertificate?: boolean;
33-
},
34-
) {
35-
this._timeout = this._options.timeout ?? DEFAULT_TIMEOUT;
34+
constructor(options?: BacktraceNodeRequestHandlerOptions) {
35+
this._timeout = options?.timeout ?? DEFAULT_TIMEOUT;
36+
this._ignoreSslCertificate = options?.ignoreSslCertificate;
3637
}
3738

3839
public async postError(
@@ -71,7 +72,7 @@ export class BacktraceNodeRequestHandler implements BacktraceRequestHandler {
7172
const request = httpClient.request(
7273
url,
7374
{
74-
rejectUnauthorized: this._options.ignoreSslCertificate === true,
75+
rejectUnauthorized: this._ignoreSslCertificate === true,
7576
timeout: this._timeout,
7677
method: 'POST',
7778
},
@@ -129,7 +130,7 @@ export class BacktraceNodeRequestHandler implements BacktraceRequestHandler {
129130
const request = httpClient.request(
130131
url,
131132
{
132-
rejectUnauthorized: this._options.ignoreSslCertificate === true,
133+
rejectUnauthorized: this._ignoreSslCertificate === true,
133134
timeout: this._timeout,
134135
method: 'POST',
135136
headers:

packages/node/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export {
1212
RawBreadcrumb,
1313
} from '@backtrace/sdk-core';
1414
export * from './attachment/index.js';
15+
export * from './BacktraceApi.js';
1516
export * from './BacktraceClient.js';
1617
export * from './BacktraceConfiguration.js';
1718
export * from './BacktraceNodeRequestHandler.js';
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { BacktraceAttachment } from './model/attachment/BacktraceAttachment.js';
2+
import {
3+
BacktraceAttachmentResponse,
4+
BacktraceReportSubmissionResult,
5+
BacktraceRequestHandler,
6+
BacktraceSubmitBody,
7+
BacktraceSubmitResponse,
8+
RequestBacktraceReportSubmission,
9+
} from './model/http/index.js';
10+
import {
11+
BacktraceSubmitSummedMetricsBody,
12+
BacktraceSubmitUniqueMetricsBody,
13+
} from './model/http/model/metric/request/BacktraceSubmitMetricsBody.js';
14+
import { MetricsUrlInformation } from './modules/metrics/MetricsUrlInformation.js';
15+
16+
export interface BacktraceCoreApiOptions {
17+
readonly url: string;
18+
readonly token?: string;
19+
20+
readonly metrics?: {
21+
readonly url?: string;
22+
};
23+
24+
readonly requestBacktraceReportSubmission?: RequestBacktraceReportSubmission;
25+
}
26+
27+
export class BacktraceCoreApi {
28+
private readonly _summedMetricsSubmissionUrl?: string;
29+
private readonly _uniqueMetricsSubmissionUrl?: string;
30+
31+
private readonly _requestBacktraceReportSubmission: RequestBacktraceReportSubmission;
32+
33+
constructor(
34+
options: BacktraceCoreApiOptions,
35+
private readonly _requestHandler: BacktraceRequestHandler,
36+
) {
37+
this._summedMetricsSubmissionUrl = MetricsUrlInformation.generateSummedEventsUrl(
38+
options.metrics?.url ?? 'https://events.backtrace.io',
39+
options.url,
40+
options.token,
41+
);
42+
43+
this._uniqueMetricsSubmissionUrl = MetricsUrlInformation.generateUniqueEventsUrl(
44+
options.metrics?.url ?? 'https://events.backtrace.io',
45+
options.url,
46+
options.token,
47+
);
48+
49+
this._requestBacktraceReportSubmission =
50+
options.requestBacktraceReportSubmission ??
51+
new RequestBacktraceReportSubmission(
52+
{
53+
url: options.url,
54+
},
55+
this._requestHandler,
56+
);
57+
}
58+
59+
public sendReport(
60+
data: BacktraceSubmitBody,
61+
attachments: BacktraceAttachment[],
62+
abortSignal?: AbortSignal,
63+
): Promise<BacktraceReportSubmissionResult<BacktraceSubmitResponse>> {
64+
return this._requestBacktraceReportSubmission.send(data, attachments, abortSignal);
65+
}
66+
67+
public sendAttachment(
68+
rxid: string,
69+
attachment: BacktraceAttachment,
70+
abortSignal?: AbortSignal,
71+
): Promise<BacktraceReportSubmissionResult<BacktraceAttachmentResponse>> {
72+
return this._requestBacktraceReportSubmission.sendAttachment(rxid, attachment, abortSignal);
73+
}
74+
75+
public sendUniqueMetrics(
76+
metrics: BacktraceSubmitUniqueMetricsBody,
77+
abortSignal?: AbortSignal,
78+
): Promise<BacktraceReportSubmissionResult<unknown>> {
79+
if (!this._uniqueMetricsSubmissionUrl) {
80+
throw new Error('Unique metrics URL is not available.');
81+
}
82+
83+
return this._requestHandler.post(this._uniqueMetricsSubmissionUrl, JSON.stringify(metrics), abortSignal);
84+
}
85+
86+
public sendSummedMetrics(
87+
metrics: BacktraceSubmitSummedMetricsBody,
88+
abortSignal?: AbortSignal,
89+
): Promise<BacktraceReportSubmissionResult<unknown>> {
90+
if (!this._summedMetricsSubmissionUrl) {
91+
throw new Error('Summed metrics URL is not available.');
92+
}
93+
94+
return this._requestHandler.post(this._summedMetricsSubmissionUrl, JSON.stringify(metrics), abortSignal);
95+
}
96+
}

packages/sdk-core/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './BacktraceCoreApi.js';
12
export * from './BacktraceCoreClient.js';
23
export * from './builder/BacktraceCoreClientBuilder.js';
34
export * from './builder/CoreClientSetup.js';

packages/sdk-core/src/model/http/BacktraceReportSubmission.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import { jsonEscaper } from '../../common/jsonEscaper.js';
22
import { BacktraceAttachment } from '../attachment/index.js';
3-
import { BacktraceConfiguration } from '../configuration/BacktraceConfiguration.js';
4-
import { BacktraceData } from '../data/BacktraceData.js';
53
import { BacktraceReportSubmissionResult } from '../data/BacktraceSubmissionResult.js';
64
import { BacktraceRequestHandler } from './BacktraceRequestHandler.js';
7-
import { BacktraceAttachmentResponse } from './model/BacktraceAttachmentResponse.js';
8-
import { BacktraceSubmissionResponse } from './model/BacktraceSubmissionResponse.js';
5+
import { BacktraceAttachmentResponse } from './model/attachment/response/BacktraceAttachmentResponse.js';
6+
import { BacktraceSubmissionResponse } from './model/submit/index.js';
7+
import { BacktraceSubmitBody } from './model/submit/request/BacktraceSubmitBody.js';
98
import { SubmissionUrlInformation } from './SubmissionUrlInformation.js';
109

1110
export interface BacktraceReportSubmission {
1211
send(
13-
data: BacktraceData,
12+
data: BacktraceSubmitBody,
1413
attachments: BacktraceAttachment[],
1514
abortSignal?: AbortSignal,
1615
): Promise<BacktraceReportSubmissionResult<BacktraceSubmissionResponse>>;
@@ -25,13 +24,13 @@ export interface BacktraceReportSubmission {
2524
export class RequestBacktraceReportSubmission implements BacktraceReportSubmission {
2625
private readonly _submissionUrl: string;
2726
constructor(
28-
options: BacktraceConfiguration,
27+
options: { url: string; token?: string },
2928
private readonly _requestHandler: BacktraceRequestHandler,
3029
) {
3130
this._submissionUrl = SubmissionUrlInformation.toJsonReportSubmissionUrl(options.url, options.token);
3231
}
3332

34-
public send(data: BacktraceData, attachments: BacktraceAttachment[], abortSignal?: AbortSignal) {
33+
public send(data: BacktraceSubmitBody, attachments: BacktraceAttachment[], abortSignal?: AbortSignal) {
3534
const json = JSON.stringify(data, jsonEscaper());
3635
return this._requestHandler.postError(this._submissionUrl, json, attachments, abortSignal);
3736
}

packages/sdk-core/src/model/http/BacktraceRequestHandler.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { BacktraceAttachment } from '../attachment/index.js';
22
import { BacktraceReportSubmissionResult } from '../data/BacktraceSubmissionResult.js';
3-
import { BacktraceAttachmentResponse } from './model/BacktraceAttachmentResponse.js';
4-
import { BacktraceSubmissionResponse } from './model/BacktraceSubmissionResponse.js';
3+
import { BacktraceAttachmentResponse } from './model/attachment/response/BacktraceAttachmentResponse.js';
4+
import { BacktraceSubmitResponse } from './model/submit/index.js';
55
export const DEFAULT_TIMEOUT = 15_000;
66
export interface BacktraceRequestHandler {
77
/**
@@ -17,7 +17,7 @@ export interface BacktraceRequestHandler {
1717
dataJson: string,
1818
attachments: BacktraceAttachment[],
1919
abortSignal?: AbortSignal,
20-
): Promise<BacktraceReportSubmissionResult<BacktraceSubmissionResponse>>;
20+
): Promise<BacktraceReportSubmissionResult<BacktraceSubmitResponse>>;
2121

2222
/**
2323
* Post data to Backtrace API

packages/sdk-core/src/model/http/index.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export * from '../data/BacktraceSubmissionResult.js';
22
export * from './BacktraceReportSubmission.js';
33
export * from './BacktraceRequestHandler.js';
44
export * from './common/ConnectionError.js';
5-
export * from './model/BacktraceAttachmentResponse.js';
6-
export * from './model/BacktraceSubmissionResponse.js';
5+
export * from './model/attachment/index.js';
6+
export * from './model/metric/index.js';
7+
export * from './model/submit/index.js';
78
export * from './SubmissionUrlInformation.js';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './response/BacktraceAttachmentResponse.js';

packages/sdk-core/src/model/http/model/BacktraceAttachmentResponse.ts packages/sdk-core/src/model/http/model/attachment/response/BacktraceAttachmentResponse.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { BacktraceSubmissionResponse } from './BacktraceSubmissionResponse.js';
1+
import { BacktraceSubmitResponse } from '../../submit/index.js';
22

3-
export interface BacktraceAttachmentResponse extends BacktraceSubmissionResponse {
3+
export interface BacktraceAttachmentResponse extends BacktraceSubmitResponse {
44
attachment_name: string;
55
attachment_id: string;
66
object: string;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './request/BacktraceSubmitMetricEventBody.js';
2+
export * from './request/BacktraceSubmitMetricsBody.js';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { AttributeType } from '../../../../data/BacktraceData.js';
2+
3+
export interface BacktraceSubmitSummedMetricEventBody {
4+
timestamp: number;
5+
attributes: Record<string, AttributeType>;
6+
metric_group: string;
7+
}
8+
9+
export interface BacktraceSubmitUniqueMetricEventBody {
10+
timestamp: number;
11+
attributes: Record<string, AttributeType>;
12+
unique: string[];
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {
2+
BacktraceSubmitSummedMetricEventBody,
3+
BacktraceSubmitUniqueMetricEventBody,
4+
} from './BacktraceSubmitMetricEventBody.js';
5+
6+
export interface BacktraceSubmitMetricsMetadataBody {
7+
dropped_events?: number;
8+
}
9+
10+
export type BacktraceSubmitSummedMetricsBody = {
11+
application: string;
12+
appversion: string;
13+
metadata?: BacktraceSubmitMetricsMetadataBody;
14+
summed_events: BacktraceSubmitSummedMetricEventBody[];
15+
};
16+
17+
export type BacktraceSubmitUniqueMetricsBody = {
18+
application: string;
19+
appversion: string;
20+
metadata?: BacktraceSubmitMetricsMetadataBody;
21+
unique_events: BacktraceSubmitUniqueMetricEventBody[];
22+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export * from './request/BacktraceSubmitArch.js';
2+
export * from './request/BacktraceSubmitAttributeType.js';
3+
export * from './request/BacktraceSubmitBody.js';
4+
export * from './request/BacktraceSubmitMemory.js';
5+
export * from './request/BacktraceSubmitModule.js';
6+
export * from './request/BacktraceSubmitSourceCode.js';
7+
export * from './request/BacktraceSubmitStackFrame.js';
8+
export * from './request/BacktraceSubmitThread.js';
9+
10+
export * from './response/BacktraceSubmitResponse.js';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export interface BacktraceSubmitArch {
2+
/**
3+
* On some systems the running program can be run with a different arch than the system itself.
4+
* `attributes.uname.machine` has to do with the system arch;
5+
* this field has to do with the running process arch.
6+
*/
7+
name: string;
8+
9+
/**
10+
* It corresponds with registers in the stack frame. Specifies the names of the registers for this arch.
11+
* The values are the types.
12+
*
13+
* If you use `string`, you can format the value as you want.
14+
*/
15+
registers: 'i32' | 'u32' | 'i64' | 'u64' | 'f32' | 'string';
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type BacktraceSubmitAttributeType = string | number | boolean | undefined | null;

0 commit comments

Comments
 (0)