Skip to content

Commit f24e7ba

Browse files
committed
feat/rebuilding http module to use him like singleton
1 parent 40360f2 commit f24e7ba

8 files changed

Lines changed: 89 additions & 50 deletions

File tree

packages/node/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@traceo-sdk/node",
3-
"version": "0.31.5",
3+
"version": "0.31.6",
44
"author": "Traceo",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

packages/node/src/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class Client {
2424
"x-sdk-key": this.options.apiKey,
2525
};
2626

27-
this.logger = new Logger();
27+
this.logger = new Logger(options?.scrapLogsInterval);
2828
this.scrappedData = new Scrapper();
2929

3030
this._metrics = new Metrics();

packages/node/src/core/http.ts

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,55 @@ import { Client } from "../client";
44
import { RequestType } from "../types";
55

66
type RequestOptionsType = {
7+
url: string;
8+
method?: RequestType;
79
body: {};
810
onError: (error: Error) => void;
11+
callback?: (resp: http.IncomingMessage) => void;
912
};
1013
export class HttpModule {
11-
host: string;
12-
url: URL;
13-
method: RequestType;
14+
private static instance: HttpModule;
15+
private host: string;
1416

15-
constructor(url: string, method: RequestType = "POST") {
17+
constructor() {
1618
this.host = Client.config.url;
17-
18-
this.url = new URL(url, this.host);
19-
this.method = method;
2019
}
2120

22-
public request(options: RequestOptionsType) {
23-
const { body, onError } = options;
21+
public static getInstance() {
22+
if (!HttpModule.instance) {
23+
HttpModule.instance = new HttpModule();
24+
}
25+
return HttpModule.instance;
26+
}
2427

28+
public request({
29+
url,
30+
method = "POST",
31+
body,
32+
onError,
33+
callback,
34+
}: RequestOptionsType) {
2535
const requestOptions = {
26-
...this.requestHeaders(),
27-
...this.requestOptions(),
36+
...this.requestHeaders(method),
37+
...this.requestOptions(url, method),
2838
};
2939

3040
const httpModule = this.requestModule();
3141

32-
const request = httpModule.request(requestOptions);
42+
const request = httpModule.request(requestOptions, callback);
3343
request.on("error", () => onError);
3444

35-
this.requestWriteBody(request, body);
45+
this.requestWriteBody(method, request, body);
3646

3747
request.end();
3848
}
3949

40-
private requestWriteBody(request: http.ClientRequest, body: {}) {
41-
if (this.method === "POST") {
50+
private requestWriteBody(
51+
method: RequestType,
52+
request: http.ClientRequest,
53+
body: {}
54+
) {
55+
if (method === "POST") {
4256
request.write(JSON.stringify(body));
4357
}
4458
}
@@ -51,28 +65,28 @@ export class HttpModule {
5165
return new URL(this.host);
5266
}
5367

54-
private requestOptions(): http.RequestOptions {
68+
private requestOptions(
69+
url: string,
70+
method: RequestType
71+
): http.RequestOptions {
5572
const reqUrl = this.clientURL;
73+
const path = new URL(url, this.host);
5674

5775
return {
5876
protocol: reqUrl.protocol,
5977
port: reqUrl.port,
6078
host: reqUrl.hostname,
61-
method: this.method,
62-
path: this.path,
79+
method,
80+
path: `${path.pathname}/${Client.config.appId}`,
6381
};
6482
}
6583

66-
private get path() {
67-
return `${this.url.pathname}/${Client.config.appId}`;
68-
}
69-
70-
private requestHeaders() {
84+
private requestHeaders(method: RequestType) {
7185
const headers = Client.client.headers;
7286
const baseHeaders = {
7387
...headers,
7488
};
75-
if (this.method !== "POST") return baseHeaders;
89+
if (method !== "POST") return baseHeaders;
7690
return {
7791
headers: {
7892
"Content-Type": "application/json",

packages/node/src/exceptions/handler.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ export const catchException = async (error: any) => {
2828

2929
const handleException = async (error: TraceoError) => {
3030
const event: Incident = await prepareException(error);
31-
const httpModule = new HttpModule("/api/worker/incident");
31+
const httpModule = HttpModule.getInstance();
3232
httpModule.request({
33+
url: "/api/worker/incident",
3334
body: event,
3435
onError: (error: Error) => {
3536
console.error(

packages/node/src/logger.ts

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
import { format } from "util";
22
import { HttpModule } from "./core/http";
33
import { LogLevel } from "./types";
4+
import * as http from "http";
45

56
export class Logger {
67
private readonly http: HttpModule;
8+
private DEFAULT_INTERVAL = 60; //60s
9+
private logsQueue = [];
710

8-
constructor() {
9-
this.http = new HttpModule("/api/worker/log");
11+
constructor(scrapInterval?: number) {
12+
this.http = HttpModule.getInstance();
13+
this.logsQueue = [];
14+
15+
let interval = this.DEFAULT_INTERVAL;
16+
if (scrapInterval && scrapInterval >= 15) {
17+
interval = scrapInterval;
18+
}
19+
20+
setInterval(() => this.sendLogs(), interval * 1000);
1021
}
1122

1223
public log(...args: any[]): void {
@@ -50,15 +61,25 @@ export class Logger {
5061
resources: this.resources,
5162
};
5263

53-
this.http.request({
54-
body: requestPayload,
55-
onError: (error: Error) => {
56-
console.error(
57-
`Traceo Error. Something went wrong while sending new Log to Traceo. Please report this issue.`
58-
);
59-
console.error(`Caused by: ${error.message}`);
60-
},
61-
});
64+
this.logsQueue.push(requestPayload);
65+
}
66+
67+
private async sendLogs() {
68+
if (this.logsQueue.length > 0) {
69+
this.http.request({
70+
url: "/api/worker/log",
71+
body: this.logsQueue,
72+
onError: (error: Error) => {
73+
console.error(
74+
`Traceo Error. Something went wrong while sending new Logs to Traceo. Please report this issue.`
75+
);
76+
console.error(`Caused by: ${error.message}`);
77+
},
78+
callback: () => {
79+
this.logsQueue = [];
80+
},
81+
});
82+
}
6283
}
6384

6485
private get timestamp(): string {
@@ -82,8 +103,8 @@ export class Logger {
82103
packageName: process.env["npm_package_name"],
83104
packageVersion: process.env["npm_package_version"],
84105
traceoVersion:
85-
process.env["npm_package_dependencies_traceo"] ||
86-
process.env["npm_package_devDependencies_traceo"],
106+
process.env["npm_package_dependencies_@traceo-sdk/node"] ??
107+
process.env["npm_package_devDependencies_@traceo-sdk/node"],
87108
};
88109
}
89110

packages/node/src/metrics/runner.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class MetricsRunner {
4141
this.interval =
4242
this.client.options.scrapMetricsInterval || DEFAULT_INTERVAL;
4343

44-
this.http = new HttpModule("/api/worker/metrics");
44+
this.http = HttpModule.getInstance();
4545

4646
this.cpuUsage = new CpuUsageMetrics();
4747
this.eventLoop = new EventLoopMetrics();
@@ -94,17 +94,18 @@ export class MetricsRunner {
9494
};
9595

9696
this.http.request({
97+
url: "/api/worker/metrics",
9798
body: metrics,
9899
onError: (error: Error) => {
99100
console.error(
100101
`Traceo Error. Something went wrong while sending new Log to Traceo. Please report this issue.`
101102
);
102103
console.error(`Caused by: ${error.message}`);
103104
},
105+
callback: () => {
106+
this.clearClientMetrics();
107+
}
104108
});
105-
106-
// TODO: This shouldn't be called when there is error on http.request
107-
this.clearClientMetrics();
108109
}
109110

110111
private get loadAvg(): number {

packages/node/src/scrapper.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export class Scrapper {
1010
private readonly http: HttpModule;
1111

1212
constructor() {
13-
this.http = new HttpModule("/api/worker/runtime");
13+
this.http = HttpModule.getInstance();
1414
}
1515

1616
collect(): void {
@@ -29,6 +29,7 @@ export class Scrapper {
2929
};
3030

3131
this.http.request({
32+
url: "/api/worker/runtime",
3233
body: data,
3334
onError: (error: Error) => {
3435
console.error(
@@ -41,11 +42,7 @@ export class Scrapper {
4142

4243
private get heap() {
4344
const heapStats = v8.getHeapStatistics();
44-
// const heapCodeStats = v8.getHeapCodeStatistics();
45-
return {
46-
...heapStats,
47-
// ...heapCodeStats,
48-
};
45+
return heapStats;
4946
}
5047

5148
private get packageJsonInfo() {

packages/node/src/types/options.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export interface TraceoOptions {
1313
then the data will be downloaded just for this time.
1414
*/
1515
scrapMetricsInterval?: number;
16+
/*
17+
Default is 60s.
18+
Value can't be smaller than 15.
19+
*/
20+
scrapLogsInterval?: number;
1621
}
1722

1823
export interface ErrorMiddlewareOptions {

0 commit comments

Comments
 (0)