Skip to content

Commit 73ff371

Browse files
committed
refactor: wip
1 parent 5ea2ac4 commit 73ff371

File tree

5 files changed

+53
-272
lines changed

5 files changed

+53
-272
lines changed

packages/utils/src/lib/performance-observer.unit.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
type PerformanceObserverOptions,
1414
PerformanceObserverSink,
1515
} from './performance-observer.js';
16-
import type { Codec } from './types.js';
16+
import type { Codec } from './wal.js';
1717

1818
describe('PerformanceObserverSink', () => {
1919
let encode: MockedFunction<(entry: PerformanceEntry) => string[]>;

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

Lines changed: 20 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
import path from 'node:path';
2-
import { performance } from 'node:perf_hooks';
3-
import type { PerformanceEntry } from 'node:perf_hooks';
41
import process from 'node:process';
5-
import { threadId } from 'node:worker_threads';
62
import { isEnvVarEnabled } from '../env.js';
7-
import { installExitHandlers } from '../exit-process.js';
8-
import { PerformanceObserverSink } from '../performance-observer.js';
93
import {
104
type ActionTrackConfigs,
115
type MeasureCtxOptions,
@@ -20,23 +14,25 @@ import type {
2014
DevToolsColor,
2115
EntryMeta,
2216
} from '../user-timing-extensibility-api.type.js';
23-
import {
24-
PROFILER_DIRECTORY,
25-
PROFILER_ENABLED_ENV_VAR,
26-
PROFILER_ORIGIN_PID_ENV_VAR,
27-
} from './constants.js';
28-
import { entryToTraceEvents } from './trace-file-utils.js';
29-
import type { UserTimingTraceEvent } from './trace-file.type.js';
30-
import { traceEventWalFormat } from './wal-json-trace.js';
31-
import {
32-
ShardedWal,
33-
WriteAheadLogFile,
34-
getShardId,
35-
getShardedGroupId,
36-
isLeaderWal,
37-
setLeaderWal,
38-
} from './wal.js';
39-
import type { WalFormat } from './wal.js';
17+
import { PROFILER_ENABLED_ENV_VAR } from './constants.js';
18+
19+
/**
20+
* Configuration options for creating a Profiler instance.
21+
*
22+
* @template T - Record type defining available track names and their configurations
23+
*/
24+
type ProfilerMeasureOptions<T extends ActionTrackConfigs> =
25+
MeasureCtxOptions & {
26+
/** Custom track configurations that will be merged with default settings */
27+
tracks?: Record<keyof T, Partial<ActionTrackEntryPayload>>;
28+
/** Whether profiling should be enabled (defaults to CP_PROFILING env var) */
29+
enabled?: boolean;
30+
};
31+
32+
/**
33+
* Options for creating a performance marker.
34+
*/
35+
export type MarkerOptions = EntryMeta & { color?: DevToolsColor };
4036

4137
/**
4238
* Options for configuring a Profiler instance.
@@ -53,15 +49,7 @@ import type { WalFormat } from './wal.js';
5349
* @property tracks - Custom track configurations merged with defaults
5450
*/
5551
export type ProfilerOptions<T extends ActionTrackConfigs = ActionTrackConfigs> =
56-
MeasureCtxOptions & {
57-
tracks?: Record<keyof T, Partial<ActionTrackEntryPayload>>;
58-
enabled?: boolean;
59-
};
60-
61-
/**
62-
* Options for creating a performance marker.
63-
*/
64-
export type MarkerOptions = EntryMeta & { color?: DevToolsColor };
52+
ProfilerMeasureOptions<T>;
6553

6654
/**
6755
* Performance profiler that creates structured timing measurements with Chrome DevTools Extensibility API payloads.
@@ -117,13 +105,6 @@ export class Profiler<T extends ActionTrackConfigs> {
117105
this.#enabled = enabled;
118106
}
119107

120-
/**
121-
* Close the profiler. Subclasses should override this to perform cleanup.
122-
*/
123-
close(): void {
124-
// Base implementation does nothing
125-
}
126-
127108
/**
128109
* Is profiling enabled?
129110
*
@@ -245,104 +226,3 @@ export class Profiler<T extends ActionTrackConfigs> {
245226
}
246227
}
247228
}
248-
249-
export class NodeProfiler<
250-
TracksConfig extends ActionTrackConfigs = ActionTrackConfigs,
251-
CodecOutput extends UserTimingTraceEvent = UserTimingTraceEvent,
252-
> extends Profiler<TracksConfig> {
253-
#shard: WriteAheadLogFile<CodecOutput>;
254-
#perfObserver: PerformanceObserverSink<CodecOutput>;
255-
#shardWal: ShardedWal<CodecOutput>;
256-
readonly #format: WalFormat<CodecOutput>;
257-
readonly #debug: boolean;
258-
#closed: boolean = false;
259-
260-
constructor(
261-
options: ProfilerOptions<TracksConfig> & {
262-
directory?: string;
263-
performanceEntryEncode: (entry: PerformanceEntry) => CodecOutput[];
264-
debug?: boolean;
265-
},
266-
) {
267-
// Initialize origin PID early - must happen before user code runs
268-
setLeaderWal(PROFILER_ORIGIN_PID_ENV_VAR);
269-
270-
const {
271-
directory = PROFILER_DIRECTORY,
272-
performanceEntryEncode,
273-
debug = false,
274-
...profilerOptions
275-
} = options;
276-
super(profilerOptions);
277-
const walGroupId = getShardedGroupId();
278-
const shardId = getShardId(process.pid, threadId);
279-
280-
this.#format = traceEventWalFormat({ groupId: walGroupId });
281-
this.#debug = debug;
282-
this.#shardWal = new ShardedWal(
283-
path.join(directory, walGroupId),
284-
this.#format,
285-
);
286-
this.#shard = this.#shardWal.shard(shardId);
287-
288-
this.#perfObserver = new PerformanceObserverSink({
289-
sink: this.#shard,
290-
encode: performanceEntryEncode,
291-
buffered: true,
292-
flushThreshold: 1, // Lower threshold for immediate flushing
293-
});
294-
295-
this.#perfObserver.subscribe();
296-
297-
installExitHandlers({
298-
onExit: () => {
299-
this.close();
300-
},
301-
});
302-
}
303-
304-
getFinalPath() {
305-
return this.#format.finalPath();
306-
}
307-
308-
/**
309-
* Close the profiler and finalize files if this is the leader process.
310-
* This method can be called manually to ensure proper cleanup.
311-
*/
312-
close(): void {
313-
if (this.#closed) {
314-
return;
315-
}
316-
317-
this.#closed = true;
318-
319-
try {
320-
if (!this.#perfObserver || !this.#shard || !this.#shardWal) {
321-
console.warn('Warning: Profiler not fully initialized during close');
322-
return;
323-
}
324-
325-
this.#perfObserver.flush();
326-
this.#perfObserver.unsubscribe();
327-
328-
this.#shard.close();
329-
330-
if (isLeaderWal(PROFILER_ORIGIN_PID_ENV_VAR)) {
331-
this.#shardWal.finalize();
332-
if (!this.#debug) {
333-
this.#shardWal.cleanup();
334-
}
335-
}
336-
} catch (error) {
337-
console.warn('Warning: Error during profiler close:', error);
338-
}
339-
}
340-
}
341-
342-
export const profiler = new NodeProfiler({
343-
prefix: 'cp',
344-
track: 'CLI',
345-
trackGroup: 'Code Pushup',
346-
performanceEntryEncode: entryToTraceEvents,
347-
debug: process.env.CP_PROFILER_DEBUG === 'true',
348-
});

0 commit comments

Comments
 (0)