Skip to content

Commit 966e3cf

Browse files
committed
refactor: fix lint
1 parent b9bcc72 commit 966e3cf

4 files changed

Lines changed: 141 additions & 75 deletions

File tree

packages/utils/docs/profiler.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,12 @@ const saved = profiler.measure('save-user', () => saveToDb(user), {
277277
This profiler extends all options and API from Profiler with automatic process exit handling for buffered performance data.
278278
The NodeJSProfiler automatically subscribes to performance observation and installs exit handlers that flush buffered data on process termination (signals, fatal errors, or normal exit).
279279

280+
### Exit Handlers
281+
282+
The profiler automatically subscribes to process events (`exit`, `SIGINT`, `SIGTERM`, `SIGQUIT`, `uncaughtException`, `unhandledRejection`) during construction. When any of these occur, the handlers call `close()` to ensure buffered data is flushed.
283+
284+
The `close()` method is idempotent and safe to call from exit handlers. It unsubscribes from exit handlers, closes the WAL sink, and unsubscribes from the performance observer, ensuring all buffered performance data is written before process termination.
285+
280286
## Configuration
281287

282288
```ts

packages/utils/src/lib/profiler/profiler-node.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ export class NodejsProfiler<
8888
* A WriteAheadLogFile sink is automatically created for buffering performance data.
8989
* @param options - Configuration options
9090
*/
91+
// eslint-disable-next-line max-lines-per-function
9192
constructor(options: NodejsProfilerOptions<DomainEvents, Tracks>) {
9293
const {
9394
encodePerfEntry,

testing/test-utils/src/lib/utils/omit-trace-json.ts

Lines changed: 124 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,33 @@
1010
* then mapping to incremental values starting from mocked epoch clock base,
1111
* while preserving the original order of events in the output.
1212
*
13-
* @param jsonlContent - JSONL string content (one JSON object per line)
13+
* @param jsonlContent - JSONL string content (one JSON object per line) or parsed JSON object/array
1414
* @param baseTimestampUs - Base timestamp in microseconds to start incrementing from (default: 1_700_000_005_000_000)
1515
* @returns Normalized JSONL string with deterministic pid, tid, and ts values
1616
*/
1717
export function omitTraceJson(
18-
jsonlContent: string,
18+
jsonlContent: string | object,
1919
baseTimestampUs = 1_700_000_005_000_000,
2020
): string {
21-
if (!jsonlContent.trim()) {
21+
if (typeof jsonlContent !== 'string') {
22+
const eventsArray = Array.isArray(jsonlContent)
23+
? jsonlContent
24+
: [jsonlContent];
25+
if (eventsArray.length === 0) {
26+
return '';
27+
}
28+
const events = eventsArray as TraceEvent[];
29+
return normalizeAndFormatEvents(events, baseTimestampUs);
30+
}
31+
32+
// Handle string input (JSONL format)
33+
const trimmedContent = jsonlContent.trim();
34+
if (!trimmedContent) {
2235
return jsonlContent;
2336
}
2437

2538
// Parse all events from JSONL
26-
const events = jsonlContent
27-
.trim()
39+
const events = trimmedContent
2840
.split('\n')
2941
.filter(Boolean)
3042
.map(line => JSON.parse(line) as TraceEvent);
@@ -33,46 +45,85 @@ export function omitTraceJson(
3345
return jsonlContent;
3446
}
3547

36-
// Collect unique pid and tid values
37-
const uniquePids = new Set<number>();
38-
const uniqueTids = new Set<number>();
39-
const timestamps: number[] = [];
40-
const uniqueLocalIds = new Set<string>();
41-
42-
for (const event of events) {
43-
if (typeof event.pid === 'number') {
44-
uniquePids.add(event.pid);
45-
}
46-
if (typeof event.tid === 'number') {
47-
uniqueTids.add(event.tid);
48-
}
49-
if (typeof event.ts === 'number') {
50-
timestamps.push(event.ts);
51-
}
52-
// Collect id2.local values
53-
if (
54-
event.id2 &&
55-
typeof event.id2 === 'object' &&
56-
'local' in event.id2 &&
57-
typeof event.id2.local === 'string'
58-
) {
59-
uniqueLocalIds.add(event.id2.local);
60-
}
48+
return normalizeAndFormatEvents(events, baseTimestampUs);
49+
}
50+
51+
/**
52+
* Normalizes trace events and formats them as JSONL.
53+
*/
54+
function normalizeAndFormatEvents(
55+
events: TraceEvent[],
56+
baseTimestampUs: number,
57+
): string {
58+
if (events.length === 0) {
59+
return '';
6160
}
6261

62+
// Collect unique pid and tid values
63+
type Accumulator = {
64+
uniquePids: Set<number>;
65+
uniqueTids: Set<number>;
66+
timestamps: number[];
67+
uniqueLocalIds: Set<string>;
68+
};
69+
70+
const { uniquePids, uniqueTids, timestamps, uniqueLocalIds } =
71+
events.reduce<Accumulator>(
72+
(acc, event) => {
73+
const newUniquePids = new Set(acc.uniquePids);
74+
const newUniqueTids = new Set(acc.uniqueTids);
75+
const newUniqueLocalIds = new Set(acc.uniqueLocalIds);
76+
77+
if (typeof event.pid === 'number') {
78+
newUniquePids.add(event.pid);
79+
}
80+
if (typeof event.tid === 'number') {
81+
newUniqueTids.add(event.tid);
82+
}
83+
84+
const newTimestamps =
85+
typeof event.ts === 'number'
86+
? [...acc.timestamps, event.ts]
87+
: acc.timestamps;
88+
89+
// Collect id2.local values
90+
if (
91+
event.id2 &&
92+
typeof event.id2 === 'object' &&
93+
'local' in event.id2 &&
94+
typeof event.id2.local === 'string'
95+
) {
96+
newUniqueLocalIds.add(event.id2.local);
97+
}
98+
99+
return {
100+
uniquePids: newUniquePids,
101+
uniqueTids: newUniqueTids,
102+
timestamps: newTimestamps,
103+
uniqueLocalIds: newUniqueLocalIds,
104+
};
105+
},
106+
{
107+
uniquePids: new Set<number>(),
108+
uniqueTids: new Set<number>(),
109+
timestamps: [] as number[],
110+
uniqueLocalIds: new Set<string>(),
111+
},
112+
);
113+
63114
// Create mappings: original value -> normalized incremental value
64115
const pidMap = new Map<number, number>();
65116
const tidMap = new Map<number, number>();
66117
const localIdMap = new Map<string, string>();
67118

68119
// Sort unique values to ensure consistent mapping order
69-
const sortedPids = Array.from(uniquePids).sort((a, b) => a - b);
70-
const sortedTids = Array.from(uniqueTids).sort((a, b) => a - b);
71-
const sortedLocalIds = Array.from(uniqueLocalIds).sort();
120+
const sortedPids = [...uniquePids].sort((a, b) => a - b);
121+
const sortedTids = [...uniqueTids].sort((a, b) => a - b);
122+
const sortedLocalIds = [...uniqueLocalIds].sort();
72123

73124
// Map pids starting from 10001
74125
sortedPids.forEach((pid, index) => {
75-
pidMap.set(pid, 10001 + index);
126+
pidMap.set(pid, 10_001 + index);
76127
});
77128

78129
// Map tids starting from 1
@@ -87,50 +138,58 @@ export function omitTraceJson(
87138

88139
// Sort timestamps to determine incremental order
89140
const sortedTimestamps = [...timestamps].sort((a, b) => a - b);
90-
const tsMap = new Map<number, number>();
91141

92142
// Map timestamps incrementally starting from baseTimestampUs
93-
sortedTimestamps.forEach((ts, index) => {
94-
if (!tsMap.has(ts)) {
95-
tsMap.set(ts, baseTimestampUs + index);
143+
const tsMap = sortedTimestamps.reduce((map, ts, index) => {
144+
if (!map.has(ts)) {
145+
return new Map(map).set(ts, baseTimestampUs + index);
96146
}
97-
});
147+
return map;
148+
}, new Map<number, number>());
98149

99150
// Normalize events while preserving original order
100151
const normalizedEvents = events.map(event => {
101-
const normalized: TraceEvent = { ...event };
152+
const pidUpdate =
153+
typeof event.pid === 'number' && pidMap.has(event.pid)
154+
? { pid: pidMap.get(event.pid)! }
155+
: {};
102156

103-
if (typeof normalized.pid === 'number' && pidMap.has(normalized.pid)) {
104-
normalized.pid = pidMap.get(normalized.pid)!;
105-
}
157+
const tidUpdate =
158+
typeof event.tid === 'number' && tidMap.has(event.tid)
159+
? { tid: tidMap.get(event.tid)! }
160+
: {};
106161

107-
if (typeof normalized.tid === 'number' && tidMap.has(normalized.tid)) {
108-
normalized.tid = tidMap.get(normalized.tid)!;
109-
}
110-
111-
if (typeof normalized.ts === 'number' && tsMap.has(normalized.ts)) {
112-
normalized.ts = tsMap.get(normalized.ts)!;
113-
}
162+
const tsUpdate =
163+
typeof event.ts === 'number' && tsMap.has(event.ts)
164+
? { ts: tsMap.get(event.ts)! }
165+
: {};
114166

115167
// Normalize id2.local if present
116-
if (
117-
normalized.id2 &&
118-
typeof normalized.id2 === 'object' &&
119-
'local' in normalized.id2 &&
120-
typeof normalized.id2.local === 'string' &&
121-
localIdMap.has(normalized.id2.local)
122-
) {
123-
normalized.id2 = {
124-
...normalized.id2,
125-
local: localIdMap.get(normalized.id2.local)!,
126-
};
127-
}
128-
129-
return normalized;
168+
const id2Update =
169+
event.id2 &&
170+
typeof event.id2 === 'object' &&
171+
'local' in event.id2 &&
172+
typeof event.id2.local === 'string' &&
173+
localIdMap.has(event.id2.local)
174+
? {
175+
id2: {
176+
...event.id2,
177+
local: localIdMap.get(event.id2.local)!,
178+
},
179+
}
180+
: {};
181+
182+
return {
183+
...event,
184+
...pidUpdate,
185+
...tidUpdate,
186+
...tsUpdate,
187+
...id2Update,
188+
};
130189
});
131190

132191
// Convert back to JSONL format
133-
return normalizedEvents.map(event => JSON.stringify(event)).join('\n') + '\n';
192+
return `${normalizedEvents.map(event => JSON.stringify(event)).join('\n')}\n`;
134193
}
135194

136195
/**

testing/test-utils/src/lib/utils/omit-trace-json.unit.test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('omitTraceJson', () => {
2121
it('should normalize pid field starting from 10001', () => {
2222
const result = omitTraceJson('{"pid":12345}\n');
2323
const parsed = JSON.parse(result.trim());
24-
expect(parsed.pid).toBe(10001);
24+
expect(parsed.pid).toBe(10_001);
2525
});
2626

2727
it('should normalize tid field starting from 1', () => {
@@ -76,9 +76,9 @@ describe('omitTraceJson', () => {
7676
expect(events[0].name).toBe('third');
7777
expect(events[1].name).toBe('first');
7878
expect(events[2].name).toBe('second');
79-
expect(events[0].pid).toBe(10003);
80-
expect(events[1].pid).toBe(10001);
81-
expect(events[2].pid).toBe(10002);
79+
expect(events[0].pid).toBe(10_003);
80+
expect(events[1].pid).toBe(10_001);
81+
expect(events[2].pid).toBe(10_002);
8282
});
8383

8484
it('should preserve event order when TIDs are out of order', () => {
@@ -106,9 +106,9 @@ describe('omitTraceJson', () => {
106106
.split('\n')
107107
.map(line => JSON.parse(line));
108108
expect(events.map(e => e.name)).toEqual(['e', 'a', 'c']);
109-
expect(events[0].pid).toBe(10003);
110-
expect(events[1].pid).toBe(10001);
111-
expect(events[2].pid).toBe(10002);
109+
expect(events[0].pid).toBe(10_003);
110+
expect(events[1].pid).toBe(10_001);
111+
expect(events[2].pid).toBe(10_002);
112112
});
113113

114114
it('should not normalize non-number pid values', () => {
@@ -188,9 +188,9 @@ describe('omitTraceJson', () => {
188188
.trim()
189189
.split('\n')
190190
.map(line => JSON.parse(line));
191-
expect(events[0].pid).toBe(10001);
192-
expect(events[1].pid).toBe(10002);
193-
expect(events[2].pid).toBe(10001);
191+
expect(events[0].pid).toBe(10_001);
192+
expect(events[1].pid).toBe(10_002);
193+
expect(events[2].pid).toBe(10_001);
194194
});
195195

196196
it('should handle duplicate timestamps correctly', () => {

0 commit comments

Comments
 (0)