Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions profiler-cli/guide.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ CORE WORKFLOW
profiler-cli profile logs --search "connect" Filter by substring in message
profiler-cli profile logs --thread t-0 Restrict to a specific thread
profiler-cli profile logs --limit 200 Show only the first 200 entries
profiler-cli profile logs --limit 0 All entries (no limit)

Step 6: Drill into specifics
profiler-cli marker info m-1234 Full details for a marker (from handles in marker list)
Expand Down Expand Up @@ -343,6 +344,7 @@ COMMON ANALYSIS PATTERNS
profiler-cli thread markers --search "Paint" --list | head -50
profiler-cli thread markers --search "GC" --min-duration 5 --list
profiler-cli thread markers --list --limit 100 First 100 markers in chronological order
profiler-cli thread markers --list --limit 0 Every matching marker (no limit; can be very long)

Investigate a page load:
profiler-cli thread page-load Overview: milestones, top resources, CPU categories, jank
Expand Down
10 changes: 4 additions & 6 deletions profiler-cli/src/commands/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
*/

import type { Command } from 'commander';
import { addGlobalOptions, parseIntArg, runCommand } from './shared';
import { parseLimitArg } from '../utils/parse';
import { addGlobalOptions, runCommand } from './shared';

export function registerProfileCommand(
program: Command,
Expand Down Expand Up @@ -69,7 +70,7 @@ export function registerProfileCommand(
`Minimum log level: ${VALID_LOG_LEVELS.join(', ')}`
)
.option('--search <term>', 'Filter by substring in message')
.option('--limit <N>', 'Limit to first N entries')
.option('--limit <N>', 'Limit to first N entries (0 = no limit)')
).action(async (opts) => {
if (opts.level !== undefined && !VALID_LOG_LEVELS.includes(opts.level)) {
console.error(
Expand All @@ -78,10 +79,7 @@ export function registerProfileCommand(
process.exit(1);
}

let limit: number | undefined;
if (opts.limit !== undefined) {
limit = parseIntArg('--limit', opts.limit, 1);
}
const limit = parseLimitArg('--limit', opts.limit);

const hasFilters =
opts.thread !== undefined ||
Expand Down
36 changes: 14 additions & 22 deletions profiler-cli/src/commands/thread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import type { Command } from 'commander';
import { parseEphemeralFilters } from '../utils/parse';
import { parseEphemeralFilters, parseLimitArg } from '../utils/parse';
import {
addGlobalOptions,
addSampleFilterOptions,
Expand Down Expand Up @@ -206,7 +206,7 @@ export function registerThreadCommand(
'Filter by maximum duration in milliseconds'
)
.option('--has-stack', 'Show only markers with stack traces')
.option('--limit <N>', 'Limit the number of results shown')
.option('--limit <N>', 'Limit the number of results shown (0 = no limit)')
.option(
'--group-by <keys>',
'Group by custom keys (e.g. "type,name" or "type,field:eventType")'
Expand Down Expand Up @@ -297,9 +297,7 @@ Examples:
'Error: --max-duration must be a positive number (in milliseconds)'
);
}
if (opts.limit !== undefined) {
markerFilters.limit = parseIntArg('--limit', opts.limit, 1);
}
markerFilters.limit = parseLimitArg('--limit', opts.limit);
if (opts.topN !== undefined) {
markerFilters.topN = parseIntArg('--top-n', opts.topN, 1);
}
Expand Down Expand Up @@ -332,7 +330,7 @@ Examples:
'--max-duration <ms>',
'Filter by maximum total request duration in milliseconds'
)
.option('--limit <N>', 'Max requests to show (default: 20, 0 = show all)')
.option('--limit <N>', 'Max requests to show (default: 20, 0 = no limit)')
.option(
'--sort <order>',
'Sort requests by "duration" (default, slowest first) or "start" (chronological)'
Expand Down Expand Up @@ -375,12 +373,7 @@ Examples:
);
}
if (opts.limit !== undefined) {
networkFilters.limit = parseIntArg(
'--limit',
opts.limit,
0,
'Error: --limit must be a non-negative integer (0 = show all)'
);
networkFilters.limit = parseLimitArg('--limit', opts.limit) ?? 0;
} else {
networkFilters.limit = 20;
}
Expand Down Expand Up @@ -426,12 +419,10 @@ Examples:
);
}
if (opts.jankLimit !== undefined) {
pageLoadOptions.jankLimit = parseIntArg(
'--jank-limit',
opts.jankLimit,
0,
'Error: --jank-limit must be a non-negative integer (0 = show all)'
);
// `collectPageLoad` does `jankLimit ?? 10`, so forwarding `undefined`
// here would silently reinstate that default; 0 is its show-all sentinel.
pageLoadOptions.jankLimit =
parseLimitArg('--jank-limit', opts.jankLimit) ?? 0;
}

await runCommand(
Expand All @@ -458,7 +449,10 @@ Examples:
'--min-self <percent>',
'Filter by minimum self time percentage'
)
.option('--limit <N>', 'Limit the number of results shown')
.option(
'--limit <N>',
'Limit the number of results shown (0 = no limit)'
)
.option('--include-idle', 'Include idle samples in percentages')
)
).action(async (opts) => {
Expand All @@ -482,9 +476,7 @@ Examples:
'Error: --min-self must be a number between 0 and 100 (percentage)'
);
}
if (opts.limit !== undefined) {
functionFilters.limit = parseIntArg('--limit', opts.limit, 1);
}
functionFilters.limit = parseLimitArg('--limit', opts.limit);
}

const sampleFilters = parseEphemeralFilters(opts);
Expand Down
28 changes: 24 additions & 4 deletions profiler-cli/src/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,15 @@ export function formatThreadMarkersResult(
` ${m.handle.padEnd(8)} ${m.name.padEnd(30)} ${startStr.padEnd(14)} ${durationStr.padEnd(10)} ${stackIndicator}${labelSuffix}`
);
}
// Truncating a chronological list silently would hide the tail of the
// timeline, so always say how much was dropped and how to get it back.
const omitted = result.filteredMarkerCount - result.flatMarkers.length;
if (omitted > 0) {
lines.push(
`\n ... (${omitted} more markers omitted: showing the first ${result.flatMarkers.length} of ${result.filteredMarkerCount})`,
' Use --limit 0 to list all of them, or --limit <N> for a larger window.'
);
}
return lines.join('\n');
}

Expand Down Expand Up @@ -1207,7 +1216,12 @@ export function formatThreadMarkersResult(
}

if (result.byType.length > 15) {
lines.push(` ... (${result.byType.length - 15} more marker names)`);
// This list is capped at 15 by the formatter, not by --limit, so point at
// what does show the rest rather than leaving a dead end.
lines.push(
` ... (${result.byType.length - 15} more marker names: showing the top 15 of ${result.byType.length})`,
' Use --json for every marker name, or --search <term> to narrow to one.'
);
}

lines.push('');
Expand Down Expand Up @@ -1394,12 +1408,15 @@ export function formatThreadFunctionsResult(

if (result.filteredFunctionCount > result.functions.length) {
const omittedCount = result.filteredFunctionCount - result.functions.length;
lines.push(`\n ... (${omittedCount} more functions omitted)`);
lines.push(
`\n ... (${omittedCount} more functions omitted: showing the first ${result.functions.length} of ${result.filteredFunctionCount})`,
' Use --limit 0 to list all of them, or --limit <N> for a larger window.'
);
}

lines.push('');
lines.push(
'Use --search <term>, --min-self <percent>, or --limit <N> to filter functions, or f-<N> handles to inspect individual functions.'
'Use --search <term>, --min-self <percent>, or --limit <N> (0 = no limit) to filter functions, or f-<N> handles to inspect individual functions.'
);

return lines.join('\n');
Expand Down Expand Up @@ -1864,7 +1881,10 @@ export function formatProfileLogsResult(
}

if (isFiltered && shown < total) {
lines.push(`Showing ${shown} of ${total} log entries (filtered/limited)`);
lines.push(
`Showing the first ${shown} of ${total} log entries — ${total - shown} omitted by --limit ${shown}.`,
'Use --limit 0 to print all of them, or --limit <N> for a larger window.'
);
} else if (isFiltered) {
lines.push(`${total} log entries (filtered)`);
} else {
Expand Down
Loading
Loading