feat(profile): add profile command to surface CPU profiling data#187
feat(profile): add profile command to surface CPU profiling data#187
Conversation
Add new `sentry profile` command with two subcommands: - `profile list` - Lists transactions with profiling data available - `profile view` - Analyzes CPU profile for a specific transaction, showing hot paths, percentiles, and optimization recommendations Features: - Flamegraph API integration for detailed call stack analysis - Hot path detection with CPU time percentages - P75/P95/P99 percentile statistics per function - User code vs library code filtering (--all-frames to include all) - JSON output support for CI/automation - Web flag to open profiles in Sentry UI - Configurable time periods (1h/24h/7d/14d/30d) Closes #56
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨Build
Other
Bug Fixes 🐛Telemetry
Other
Internal Changes 🔧
🤖 This preview updates automatically when you update the PR. |
Codecov Results 📊✅ Patch coverage is 92.27%. Project has 4052 uncovered lines. Files with missing lines (77)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 71.21% 72.83% +1.62%
==========================================
Files 111 121 +10
Lines 13764 14915 +1151
Branches 0 0 —
==========================================
+ Hits 9801 10863 +1062
- Misses 3963 4052 +89
- Partials 0 0 —Generated by Codecov Action |
- Make shared.profiles optional in schema (may be absent when no data) - Handle null values for sample_durations_ns and sample_counts - Fix hot path percentage calculation to use total self time
Enable quick access to transactions via numeric indices or short aliases: - `sentry profile list` now shows # and ALIAS columns - `sentry profile view 1` - access by numeric index - `sentry profile view i` - access by alias (last unique segment) Implementation: - Add transaction_aliases SQLite table (schema v5) - Add TransactionAliasEntry type for cached aliases - Add buildTransactionAliases() using existing alias algorithm - Add resolveTransaction() with stale cache detection - Update formatters to show alias columns Aliases are fingerprinted by org:project:period and error with helpful messages when stale (e.g., different period) or unknown.
Add comprehensive test coverage for the transaction alias system: - test/lib/transaction-alias.property.test.ts: Property-based tests using fast-check to verify extractTransactionSegment and buildTransactionAliases invariants - test/lib/db/transaction-aliases.test.ts: Unit tests for SQLite storage layer including fingerprint building, CRUD operations, and stale detection - test/lib/resolve-transaction.test.ts: Unit tests for transaction resolution including index/alias lookup, full name pass-through, and stale alias error handling
Resolve conflicts by combining: - Profile commands (profile list, profile view) - Log commands (log list, logs shortcut) - Both profiling and logs API functions in api-client.ts - Schema v5 with transaction_aliases table (composite primary key) - SKILL.md documentation for both profile and log commands
…segments The fallback path was returning numeric segments when all other segments were placeholders or numeric. Now the fallback also filters out numeric and placeholder patterns, defaulting to 'txn' if nothing meaningful found. Fixes flaky property-based test 'does not return purely numeric segments'.
- Fix mismatched default periods: both list and view now use 24h default - Handle duplicate segments with numeric suffixes (issues, issues2, etc.) - Add --web/-w flag to profile list command - Fix schema repair for transaction_aliases to use custom DDL with composite primary key
Cherry-pick from refactor/positional-args-flags branch (PR #204). Migrate profile view command from --org/--project flags to use the <org>/<project> positional argument syntax for consistency with other commands. Changes: - profile view now uses: sentry profile view [<org>/<project>] <transaction> - Export parsePositionalArgs for unit testing - Add unit tests for parsePositionalArgs Co-authored-by: Burak Yigit Kaya <byk@sentry.io>
Resolve conflicts in: - src/lib/api-client.ts (keep both profile and logs imports) - src/lib/sentry-urls.ts (keep both profile and logs URL functions)
- Add unit + property-based tests for profile analyzer (nsToMs, formatDuration, hasProfileData, analyzeHotPaths, calculatePercentiles, analyzeFlamegraph) - Add unit tests for profile formatters (formatProfileAnalysis, formatProfileListHeader, formatProfileListTableHeader, formatProfileListRow, formatProfileListFooter) - Add property tests for buildProfileUrl and buildProfilingSummaryUrl - Add edge case tests for extractTransactionSegment (empty, placeholder-only, numeric-only inputs) - Fix buildProfilingSummaryUrl to use numeric project ID instead of slug - Fix getFlamegraph default statsPeriod from '7d' to '24h' to match CLI
- Add 18 mock-based tests for listCommand covering target resolution, --web, --json, empty state, human-readable output, alias building - Add resolveFromProjectSearch tests (4 tests) with spyOn mocking - Add 13 mock-based tests for viewCommand covering target resolution, --web, --json, no profile data, human-readable output - Export resolveFromProjectSearch for testability - Use Stricli loader() pattern for command function access in tests
The 'alias is a prefix of the extracted segment' property test could fail with duplicate transaction inputs because disambiguateSegments appends numeric suffixes to duplicates, breaking the prefix relationship with the raw extracted segment. Use uniqueArray to ensure unique transactions in the property test.
- Fix disambiguateSegments collision: track all result values in a Set and increment suffix until unique (Bug 1) - Fix orgSlug usage: replace resolveFromProjectSearch with shared resolveProjectBySlug that uses foundProject.orgSlug (Bug 2) - Deduplicate resolveFromProjectSearch across event/log/profile view commands into resolveProjectBySlug in resolve-target.ts (Bug 3) - Fix buildProfileUrl: wrap transaction in encoded quotes for proper Sentry search syntax with spaces (Bug 4) - Extract parsePeriod/VALID_PERIODS to shared.ts to avoid duplication between profile list and view commands (Bug 5) - Fix profile list project-search: add resolveListTarget with proper findProjectsBySlug handling instead of broken resolveOrgAndProject passthrough (Bug 6)
…tDurationMs - profile list: delegate project-search to shared resolveProjectBySlug() instead of duplicating findProjectsBySlug + error handling logic - Rename formatDuration → formatDurationMs in analyzer.ts to avoid name collision with formatDuration in formatters/human.ts (different input units) - Update all call sites and tests accordingly
|
Re: formatDuration name collision (Bug 8) — Fixed: renamed |
getStaleFingerprint and getStaleIndexFingerprint now accept the current fingerprint and use 'AND fingerprint != ?' to exclude it from results. Previously the queries could return the current context's own fingerprint, leading to incorrect stale-alias error messages.
# Conflicts: # plugins/sentry-cli/skills/sentry-cli/SKILL.md # src/app.ts # src/commands/event/view.ts # src/commands/log/view.ts # src/lib/api-client.ts # src/lib/db/schema.ts # src/lib/resolve-target.ts # test/commands/event/view.test.ts # test/commands/log/view.test.ts
- Remove misleading PROFILES column (always 0 from profile_functions dataset) - Add p95 column alongside p75 for better performance context - Sort by p75 descending instead of count (which was always 0) - Smart transaction name truncation: strip common prefix, middle-truncate - Rename File:Line column to Location, widen to 30 chars with middle-truncation - Improve no-data error message to suggest running profile list - Add tests for truncateMiddle and findCommonPrefix utilities
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
Use count_unique(timestamp) instead of count() to show real sample counts in the profile list table. Add documentation page with anonymized example outputs for both list and view commands.
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
- Fix common prefix stripping for null transactions ("unknown" fallback
was being sliced by the prefix length, producing empty strings)
- Fix misaligned table rows when hasAliases is true but a row has no
alias (now pads index/alias columns to maintain column alignment)
- Fix formatDurationMs boundary rounding for 1-10ms and µs ranges
(9.999ms no longer renders as "10.00ms", 0.9995ms no longer as "1000µs")
- Change formatProfileListRow to use options object for clearer API
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
Remove custom DDL handling (CUSTOM_DDL_TABLES, TRANSACTION_ALIASES_DDL, repairTransactionAliasesTable) since TABLE_SCHEMAS already supports compositePrimaryKey (used by pagination_cursors). Add compositePrimaryKey: ["fingerprint", "idx"] to the schema definition. Bump schema version 5→6 and split the migration so databases already at v5 (from pagination_cursors) correctly pick up the transaction_aliases table via the new v5→v6 migration block.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
Pad # to padStart(3) and ALIAS to padEnd(6) in the header to match the data row formatting. Fix non-alias divider width from 91 to 87 to match actual content width.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
- Remove trailing \d* from ALIAS_PATTERN since disambiguateSegments uses 'x' prefix, not numeric suffix. This prevents misclassifying inputs like 'process2' as aliases. - Separate index creation from table DDL in repairMissingTables so a failed index doesn't prevent subsequent repair passes from creating it (table exists check was skipping the index).
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
When project is null, the stale/unknown ref error messages suggested 'sentry profile list --org <org>' but profile list has no --org flag. Now omits the target when project is unknown, letting auto-detection handle it.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
…ion example - Explicit org/project targets now use parsed values directly instead of routing through resolveOrgAndProject (consistent with view.ts) - Add disambiguationExample to resolveProjectBySlug call in list.ts so users see an actionable command when a project exists in multiple orgs
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
Summary
Adds a new
sentry profilecommand with two subcommands to surface CPU profiling data from Sentry:profile list- Lists transactions that have profiling data, with sample counts, p75/p95 durations, and short aliasesprofile view <transaction>- Analyzes CPU profile for a transaction, showing hot paths and performance metricsFeatures
--allFramesto include all)--webflag to open profiles in Sentry UIcount_unique(timestamp)Usage Examples
List Transactions with Profiles
View Profile Analysis
Access by index, alias, or full transaction name:
Output:
Stale Alias Detection
If you change the period or project, the CLI warns you:
Other Options
How Aliases Work
/api/.../issues/→i)org:project:periodfor cache validationFormatting Improvements
count_unique(timestamp)which returns real sample counts (notcount()which returned 0)/api/0/) across all transactions for readability…in the middle, preserving both start and endprofile listinstead of vague "check the transaction name"Closes #56