Skip to content

Commit 5feb324

Browse files
fix/improvements for open telemetry exporters
1 parent be6fe3c commit 5feb324

17 files changed

Lines changed: 321 additions & 162 deletions

File tree

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
"lint:prettier": "lerna run lint:prettier"
1010
},
1111
"workspaces": [
12-
"packages/node-core",
13-
"packages/opentelemetry-node",
14-
"packages/node",
15-
"packages/browser",
16-
"packages/react",
17-
"packages/vue"
12+
"packages/traceo-sdk-node",
13+
"packages/traceo-sdk-node-core",
14+
"packages/traceo-sdk-opentelemetry",
15+
"packages/traceo-sdk-browser",
16+
"packages/traceo-sdk-react",
17+
"packages/traceo-sdk-vue"
1818
],
1919
"devDependencies": {
2020
"@types/jest": "^29.2.0",

packages/traceo-sdk-browser/src/client.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { BrowserClientConfigType, IBrowserClient, TraceoBrowserError } from "./t
22
import { Transport } from "./transport";
33
import { Performance } from "./performance";
44
import { utils } from "./utils";
5-
import { stacktrace } from "./exceptions/stacktrace";
5+
import { StacktraceParser } from "./exceptions/stacktrace";
66
import { Trace } from "./types/stacktrace";
77
import { BrowserIncidentType, CAPTURE_ENDPOINT } from "./types/transport";
88
import { EventOnErrorType, EventOnUnhandledRejectionType, windowEventHandlers } from "./handlers";
@@ -80,7 +80,7 @@ export abstract class BrowserClient implements IBrowserClient {
8080

8181
const stack = error?.stack || "";
8282

83-
const traces: Trace[] = stacktrace.parse(stack);
83+
const traces: Trace[] = StacktraceParser.parse(stack);
8484

8585
const err: BrowserIncidentType = {
8686
name,
@@ -149,7 +149,7 @@ export abstract class BrowserClient implements IBrowserClient {
149149
stack = reason.toString();
150150
}
151151

152-
const traces: Trace[] = stacktrace.parse(stack);
152+
const traces: Trace[] = StacktraceParser.parse(stack);
153153
const err: BrowserIncidentType = {
154154
name,
155155
message,

packages/traceo-sdk-browser/src/exceptions/stacktrace.ts

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,63 +6,64 @@ const CLASS_METHOD_REGEXP = /(.+)\.([^.]+)$/;
66

77
const EXCLUDED = ["<anonymous>"];
88

9-
const parse = (stackTrace: string): Trace[] => {
10-
const lines = stackTrace.split("\n");
11-
const traces: Trace[] = [];
9+
export class StacktraceParser {
10+
constructor() { }
1211

13-
for (const line of lines) {
14-
const stackTraceLine = parseStackTraceLine(line);
15-
if (stackTraceLine && stackTraceLine?.filename) {
16-
traces.push(stackTraceLine);
17-
}
18-
}
12+
public static parse(stackTrace: string): Trace[] {
13+
const lines = stackTrace.split("\n");
14+
const traces: Trace[] = [];
1915

20-
return traces;
21-
};
16+
for (const line of lines) {
17+
const stackTraceLine = this.parseStackTraceLine(line);
18+
if (stackTraceLine && stackTraceLine?.filename) {
19+
traces.push(stackTraceLine);
20+
}
21+
}
2222

23-
const parseStackTraceLine = (line: string): Trace | null => {
24-
const match = line.match(LINE_REGEXP);
25-
if (!match || EXCLUDED.includes(match[1])) {
26-
return null;
23+
return traces;
2724
}
2825

29-
const [, method, file, lineStr, columnStr] = match;
30-
const lineNo = parseOptionalInt(lineStr);
31-
const columnNo = parseOptionalInt(columnStr);
32-
const ext = getFileExtension(file);
33-
const methodName = getFullMethodName(method);
26+
private static parseStackTraceLine = (line: string): Trace | null => {
27+
const match = line.match(LINE_REGEXP);
28+
if (!match || EXCLUDED.includes(match[1])) {
29+
return null;
30+
}
31+
32+
const [, method, file, lineStr, columnStr] = match;
33+
const lineNo = this.parseOptionalInt(lineStr);
34+
const columnNo = this.parseOptionalInt(columnStr);
35+
const ext = this.getFileExtension(file);
36+
const methodName = this.getFullMethodName(method);
3437

35-
return {
36-
filename: file,
37-
lineNo,
38-
columnNo,
39-
function: methodName,
40-
extension: ext
38+
return {
39+
filename: file,
40+
lineNo,
41+
columnNo,
42+
function: methodName,
43+
extension: ext
44+
};
4145
};
42-
};
4346

44-
const parseOptionalInt = (str?: string): number | null => {
45-
return str ? parseInt(str, 10) : null;
46-
};
47+
private static parseOptionalInt = (str?: string): number | null => {
48+
return str ? parseInt(str, 10) : null;
49+
};
4750

48-
const getFileExtension = (file?: string): string | null => {
49-
if (!file) {
50-
return null;
51-
}
51+
private static getFileExtension = (file?: string): string | null => {
52+
if (!file) {
53+
return null;
54+
}
5255

53-
const match = file.match(EXTENSION_REGEXP);
54-
return match ? match[1] : null;
55-
};
56+
const match = file.match(EXTENSION_REGEXP);
57+
return match ? match[1] : null;
58+
};
5659

57-
const getFullMethodName = (method?: string): string | null => {
58-
if (!method) {
59-
return null;
60-
}
60+
private static getFullMethodName = (method?: string): string | null => {
61+
if (!method) {
62+
return null;
63+
}
6164

62-
const match = method.match(CLASS_METHOD_REGEXP);
63-
return match ? `${match[1]}.${match[2]}` : method;
64-
};
65+
const match = method.match(CLASS_METHOD_REGEXP);
66+
return match ? `${match[1]}.${match[2]}` : method;
67+
};
6568

66-
export const stacktrace = {
67-
parse
68-
};
69+
}

packages/traceo-sdk-node-core/src/transport.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,79 @@ import * as https from "https";
33
import { RequestType, RequestOptionsType } from "./types";
44
import { getGlobalTraceo } from "./utils";
55

6+
/**
7+
* Http client for SDK requestst
8+
*/
9+
export class HttpClient {
10+
11+
protected constructor() {}
12+
13+
/**
14+
* Make http/s request to Traceo platoform.
15+
*
16+
* Default request method is POST, in this case in hedaers is passed "Content-Type": "application/json".
17+
* URL is concatenation of passed host to client and pathanme to this method.
18+
* Use callback/onError callbacks to handle action after operation.
19+
*/
20+
public static request = ({ url, method = "POST", body, onError, callback }: RequestOptionsType) => {
21+
const options = {
22+
...this.requestHeaders(method),
23+
...this.requestOptions(url, method)
24+
};
25+
26+
const httpModule = this.requestModule();
27+
28+
const request = httpModule.request(options, callback);
29+
request.on("error", () => onError);
30+
31+
this.requestWriteBody(method, request, body);
32+
33+
request.end();
34+
};
35+
36+
37+
private static requestWriteBody = (method: RequestType, request: http.ClientRequest, body: {}) => {
38+
if (method === "POST") {
39+
request.write(JSON.stringify(body));
40+
}
41+
};
42+
43+
private static requestModule = (): typeof http | typeof https => {
44+
const protocol = this.clientURL().protocol;
45+
return protocol == "http:" ? http : https;
46+
};
47+
48+
private static clientURL = (): URL => {
49+
return new URL(getGlobalTraceo().options.host);
50+
};
51+
52+
private static requestOptions = (url: string, method: RequestType): http.RequestOptions => {
53+
const host = getGlobalTraceo().options.host;
54+
const reqUrl = new URL(host);
55+
const path = new URL(url, host);
56+
57+
return {
58+
protocol: reqUrl.protocol,
59+
port: reqUrl.port,
60+
host: reqUrl.hostname,
61+
method,
62+
path: path.pathname
63+
};
64+
};
65+
66+
private static requestHeaders = (method: RequestType) => {
67+
const headers = getGlobalTraceo().headers;
68+
69+
if (method !== "POST") return headers;
70+
return {
71+
headers: {
72+
"Content-Type": "application/json",
73+
...headers
74+
}
75+
};
76+
};
77+
}
78+
679
const requestWriteBody = (method: RequestType, request: http.ClientRequest, body: {}) => {
780
if (method === "POST") {
881
request.write(JSON.stringify(body));

packages/traceo-sdk-node-core/src/types/metrics.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { MetricData } from "./opentelemetry";
33

44
export type MetricType = DeepPartial<MetricData>[];
55
export interface IMetrics {
6-
collect(): MetricType;
6+
collect(): TraceoMetric[];
77
}
88

99
export type EventLoopMetricType = {
@@ -48,3 +48,16 @@ export type AverageCpuMetricType = {
4848
idle: number;
4949
total: number;
5050
};
51+
52+
export type TraceoMetric = {
53+
name: string;
54+
type: TraceoMetricType;
55+
value: number;
56+
unixTimestamp: number;
57+
}
58+
59+
export enum TraceoMetricType {
60+
HISTOGRAM,
61+
COUNTER,
62+
GAUGE
63+
}

packages/traceo-sdk-node/src/exceptions/handler.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { stacktrace } from "stacktrace-parser-node";
22
import {
3-
transport,
43
TraceoError,
54
NodeIncidentType,
65
CAPTURE_ENDPOINT,
7-
utils
6+
utils,
7+
HttpClient
88
} from "@traceo-sdk/node-core";
99

1010
/**
@@ -32,7 +32,7 @@ export const catchException = async (error: Error) => {
3232
const handleException = async (error: TraceoError) => {
3333
const event: NodeIncidentType = await prepareException(error);
3434

35-
transport.request({
35+
HttpClient.request({
3636
url: CAPTURE_ENDPOINT.INCIDENT,
3737
body: event,
3838
onError: (error: Error) => {

packages/traceo-sdk-node/src/logger.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { format } from "util";
2-
import { CAPTURE_ENDPOINT, LogLevel, transport } from "@traceo-sdk/node-core";
3-
import { getGlobalTraceo } from "@traceo-sdk/node-core/dist/utils";
2+
import { CAPTURE_ENDPOINT, HttpClient, LogLevel, utils } from "@traceo-sdk/node-core";
43

54
const DEFAULT_EXPORT_INTERVAL = 15000;
65
export class Logger {
@@ -10,7 +9,7 @@ export class Logger {
109
constructor() {
1110
this.logsQueue = [];
1211

13-
const client = getGlobalTraceo();
12+
const client = utils.getGlobalTraceo();
1413

1514
const scrapLogsInterval = client.options.exportIntervalMillis;
1615
if (scrapLogsInterval && scrapLogsInterval >= DEFAULT_EXPORT_INTERVAL) {
@@ -77,7 +76,7 @@ export class Logger {
7776

7877
private async sendLogs() {
7978
if (this.logsQueue.length > 0) {
80-
transport.request({
79+
HttpClient.request({
8180
url: CAPTURE_ENDPOINT.LOG,
8281
body: this.logsQueue,
8382
onError: (error: Error) => {

packages/traceo-sdk-node/src/metrics/default/cpu-usage.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ import * as os from "os";
22
import {
33
IMetrics,
44
AverageCpuMetricType,
5-
InstrumentType,
6-
ValueType,
7-
MetricType,
85
utils,
9-
DataPointType
6+
TraceoMetric,
7+
TraceoMetricType
108
} from "@traceo-sdk/node-core";
119

1210
export class CpuUsageMetrics implements IMetrics {
@@ -16,7 +14,7 @@ export class CpuUsageMetrics implements IMetrics {
1614
this.measureStart = this.calculateAverageCpuUsage();
1715
}
1816

19-
public collect(): MetricType {
17+
public collect(): TraceoMetric[] {
2018
const endMeasure = this.calculateAverageCpuUsage();
2119

2220
const idleDifference = endMeasure.idle - this.measureStart.idle;
@@ -26,13 +24,10 @@ export class CpuUsageMetrics implements IMetrics {
2624

2725
return [
2826
{
29-
descriptor: {
30-
name: "cpu_usage",
31-
type: InstrumentType.TIME_SERIES,
32-
valueType: ValueType.DOUBLE
33-
},
34-
dataPointType: DataPointType.TIME_SERIES,
35-
dataPoints: [{ value: cpuUsage, startTime: [utils.currentUnix()] }]
27+
name: "cpu_usage",
28+
type: TraceoMetricType.GAUGE,
29+
unixTimestamp: utils.currentUnix(),
30+
value: cpuUsage
3631
}
3732
];
3833
}

packages/traceo-sdk-node/src/metrics/default/event-loop.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ import {
22
utils,
33
IMetrics,
44
EventLoopMetricType,
5-
MetricType,
6-
InstrumentType,
7-
ValueType,
8-
DataPointType
5+
TraceoMetric,
6+
TraceoMetricType
97
} from "@traceo-sdk/node-core";
108

119
let perf_hooks;
@@ -29,7 +27,7 @@ export class EventLoopMetrics implements IMetrics {
2927
}
3028
}
3129

32-
public collect(): MetricType {
30+
public collect(): TraceoMetric[] {
3331
const metrics = ["loop_min", "loop_max", "loop_mean", "loop_stddev"];
3432

3533
const data: EventLoopMetricType = {
@@ -40,14 +38,11 @@ export class EventLoopMetrics implements IMetrics {
4038
};
4139
this.histogram.reset();
4240

43-
const response: MetricType = metrics.map((metric) => ({
44-
descriptor: {
45-
name: metric,
46-
type: InstrumentType.TIME_SERIES,
47-
valueType: ValueType.DOUBLE
48-
},
49-
dataPointType: DataPointType.TIME_SERIES,
50-
dataPoints: [{ value: data[metric], startTime: [utils.currentUnix()] }]
41+
const response: TraceoMetric[] = metrics.map((metric) => ({
42+
name: metric,
43+
type: TraceoMetricType.GAUGE,
44+
unixTimestamp: utils.currentUnix(),
45+
value: data[metric]
5146
}));
5247

5348
return response;

0 commit comments

Comments
 (0)