@@ -108,6 +108,23 @@ const trace = getTrace("metro");
108108const myTrace = someCondition ? customTrace : nullTrace ;
109109```
110110
111+ ### Manual event timing
112+
113+ Use ` startEvent ` on a domain to manually control the start and end of a timed
114+ event. This is useful when start and end points don't wrap a single function
115+ call:
116+
117+ ``` typescript
118+ import { getDomain } from " @rnx-kit/tools-performance" ;
119+
120+ const domain = getDomain (" metro" );
121+ if (domain ) {
122+ const endEvent = domain .startEvent (" resolve" );
123+ // ... do work across multiple steps ...
124+ endEvent (); // records the duration
125+ }
126+ ```
127+
111128### Custom trace functions
112129
113130Use ` createTrace ` with a ` TraceRecorder ` to build trace functions backed by
@@ -172,6 +189,27 @@ trackPerformance({ enable: ["resolve", "transform"] });
172189// Calls are additive — all three domains above are now enabled
173190```
174191
192+ ### Subdomains
193+
194+ Subdomains create a parent–child relationship between domains. When a parent
195+ domain is enabled, all its registered subdomains are automatically enabled too.
196+ This is useful for organizing related operations under a single toggle.
197+
198+ ``` typescript
199+ import { registerSubdomain , getDomain } from " @rnx-kit/tools-performance" ;
200+
201+ // Register "metro:resolver" as a subdomain of "metro"
202+ registerSubdomain (" metro" , " resolver" );
203+
204+ // Enabling "metro" now also enables "metro:resolver"
205+ trackPerformance ({ enable: " metro" , strategy: " timing" });
206+
207+ const domain = getDomain (" metro:resolver" ); // enabled via parent
208+ ```
209+
210+ Subdomains can be registered before or after the parent is enabled — the
211+ relationship is resolved in either order.
212+
175213### Checking if tracing is enabled
176214
177215` isTraceEnabled ` checks domain and frequency without creating a domain as a
@@ -245,40 +283,74 @@ const table = formatAsTable(
245283console .log (table );
246284```
247285
286+ ## Metro Integration
287+
288+ ` createPerfLoggerFactory ` returns a factory compatible with Metro's
289+ ` unstable_perfLoggerFactory ` config option. It bridges Metro's performance
290+ logging into the tools-performance domain system under the ` "metro" ` parent
291+ domain.
292+
293+ ``` typescript
294+ import {
295+ createPerfLoggerFactory ,
296+ trackPerformance ,
297+ } from " @rnx-kit/tools-performance" ;
298+
299+ // Enable the metro domain
300+ trackPerformance ({ enable: " metro" , strategy: " timing" });
301+
302+ // Pass the factory to Metro config
303+ module .exports = {
304+ unstable_perfLoggerFactory: createPerfLoggerFactory (),
305+ };
306+ ```
307+
308+ When Metro calls the factory, it creates subdomains like ` metro:start_up ` ,
309+ ` metro:bundling_request ` , and ` metro:hmr ` . Metro's ` subSpan ` calls create deeper
310+ subdomains (e.g. ` metro:start_up:resolver ` ). Metro's ` point ` events with
311+ ` _start ` /` _end ` suffixes are mapped to timed events via ` startEvent ` .
312+
313+ When the ` "metro" ` domain is not enabled, the factory returns no-op loggers with
314+ zero overhead.
315+
248316## API Reference
249317
250318### Module-Level Functions
251319
252- | Function | Description |
253- | ------------------------------- | ----------------------------------------------------------------------- |
254- | ` trackPerformance(config?) ` | Enable tracking. Config controls domains, strategy, and report options. |
255- | ` getTrace(domain, frequency?) ` | Get a trace function for a domain. Returns ` nullTrace ` if not enabled. |
256- | ` getDomain(name) ` | Get the ` PerfDomain ` for a domain, or ` undefined ` if not enabled. |
257- | ` isTraceEnabled(domain, freq?) ` | Check if tracing is enabled for a domain and optional frequency. |
258- | ` reportPerfData() ` | Finish tracking and print the performance report. |
320+ | Function | Description |
321+ | -------------------------------------- | ----------------------------------------------------------------------- |
322+ | ` trackPerformance(config?) ` | Enable tracking. Config controls domains, strategy, and report options. |
323+ | ` getTrace(domain, frequency?) ` | Get a trace function for a domain. Returns ` nullTrace ` if not enabled. |
324+ | ` getDomain(name) ` | Get the ` PerfDomain ` for a domain, or ` undefined ` if not enabled. |
325+ | ` isTraceEnabled(domain, freq?) ` | Check if tracing is enabled for a domain and optional frequency. |
326+ | ` registerSubdomain(domain, subdomain) ` | Register a subdomain under a parent. Enabled when the parent is. |
327+ | ` reportPerfData() ` | Finish tracking and print the performance report. |
328+ | ` createPerfLoggerFactory() ` | Create a Metro-compatible ` unstable_perfLoggerFactory ` . |
259329
260330### PerfTracker
261331
262- | Member | Description |
263- | -------------------------- | ---------------------------------------------------------------------- |
264- | ` new PerfTracker(config?) ` | Create a new tracker. Auto-registers a process exit handler. |
265- | ` enable(domain) ` | Enable tracking for ` true ` (all), a string, or string array. |
266- | ` isEnabled(domain, freq?) ` | Check if a domain is enabled, optionally at a given frequency. |
267- | ` domain(name) ` | Get or create a ` PerfDomain ` for an enabled domain. |
268- | ` finish(processExit?) ` | Stop all domains, print the report, and unregister. Only reports once. |
269- | ` updateConfig(config) ` | Merge new configuration values. |
332+ | Member | Description |
333+ | -------------------------------- | ---------------------------------------------------------------------- |
334+ | ` new PerfTracker(config?) ` | Create a new tracker. Auto-registers a process exit handler. |
335+ | ` enable(domain) ` | Enable tracking for ` true ` (all), a string, or string array. |
336+ | ` isEnabled(domain, freq?) ` | Check if a domain is enabled, optionally at a given frequency. |
337+ | ` domain(name) ` | Get or create a ` PerfDomain ` for an enabled domain. |
338+ | ` registerSubdomain(domain, sub) ` | Register a subdomain. Enabling the parent enables the subdomain. |
339+ | ` finish(processExit?) ` | Stop all domains, print the report, and unregister. Only reports once. |
340+ | ` updateConfig(config) ` | Merge new configuration values. |
270341
271342### PerfDomain
272343
273- | Member | Description |
274- | ---------------------- | ---------------------------------------------------------------------- |
275- | ` name ` | Domain name (readonly). |
276- | ` strategy ` | Tracing strategy: ` "timing" ` or ` "node" ` (readonly). |
277- | ` frequency ` | Current frequency level (mutable). |
278- | ` start() ` | Begin domain-level timing (called automatically unless ` waitOnStart ` ). |
279- | ` stop(processExit?) ` | End domain-level timing and clean up marks. |
280- | ` enabled(frequency?) ` | Check if a frequency level is active for this domain. |
281- | ` getTrace(frequency?) ` | Get a trace function, or ` nullTrace ` if frequency is not active. |
344+ | Member | Description |
345+ | ------------------------ | ---------------------------------------------------------------------- |
346+ | ` name ` | Domain name (readonly). |
347+ | ` strategy ` | Tracing strategy: ` "timing" ` or ` "node" ` (readonly). |
348+ | ` frequency ` | Current frequency level (mutable). |
349+ | ` start() ` | Begin domain-level timing (called automatically unless ` waitOnStart ` ). |
350+ | ` stop(processExit?) ` | End domain-level timing and clean up marks. |
351+ | ` startEvent(tag, freq?) ` | Start a timed event. Returns a function to call when the event ends. |
352+ | ` enabled(frequency?) ` | Check if a frequency level is active for this domain. |
353+ | ` getTrace(frequency?) ` | Get a trace function, or ` nullTrace ` if frequency is not active. |
282354
283355### Trace Primitives
284356
0 commit comments