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 ✨
Bug Fixes 🐛Upgrade
Documentation 📚
🤖 This preview updates automatically when you update the PR. |
Codecov Results 📊❌ Patch coverage is 54.41%. Project has 2288 uncovered lines. Files with missing lines (46)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
- Coverage 76.73% 74.98% -1.75%
==========================================
Files 65 71 +6
Lines 8419 9143 +724
Branches 0 0 —
==========================================
+ Hits 6460 6855 +395
- Misses 1959 2288 +329
- 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
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| projectSlug: string | ||
| ): string { | ||
| return `${getSentryBaseUrl()}/organizations/${orgSlug}/profiling/?project=${projectSlug}`; | ||
| } |
There was a problem hiding this comment.
Summary URL uses project slug instead of numeric ID
Medium Severity
buildProfilingSummaryUrl puts the project slug into the ?project= query parameter, but Sentry's web frontend expects a numeric project ID for this parameter. The --web flag in profile list returns before calling getProject() (which retrieves the numeric ID), so only the slug is available. This causes the opened browser URL to not correctly filter to the target project.
Additional Locations (1)
| orgSlug: string, | ||
| projectId: string | number, | ||
| transactionName: string, | ||
| statsPeriod = "7d" |
There was a problem hiding this comment.
Default period mismatch between API function and CLI
Low Severity
getFlamegraph defaults statsPeriod to "7d", but both CLI commands (profile list and profile view) default their --period flag to "24h". While the CLI always passes the flag value so the mismatch doesn't currently trigger, any future caller omitting the parameter would silently get a different period than the documented CLI default.
| ); | ||
| } | ||
| return value; | ||
| } |
There was a problem hiding this comment.
Duplicated period validation logic across command files
Low Severity
VALID_PERIODS and parsePeriod are identically defined in both list.ts and view.ts. This duplicated validation logic means any future change (e.g., adding a new period option) needs to be applied in two places, risking inconsistency.
Additional Locations (1)
| " - Performance percentiles (p75, p95, p99)\n" + | ||
| " - Hot paths (functions consuming the most CPU time)\n" + | ||
| " - Recommendations for optimization\n\n" + | ||
| "By default, only user application code is shown. Use --all-frames to include library code.\n\n" + |
There was a problem hiding this comment.
Help text references wrong flag name for allFrames
Medium Severity
The fullDescription tells users to "Use --all-frames" (kebab-case), but the flag is defined as allFrames (camelCase) and Stricli matches flag names exactly by default (no scanner.caseStyle is configured). Users following this help text would get an unrecognized flag error. The SKILL.md correctly documents it as --allFrames.


Summary
Adds a new
sentry profilecommand with two subcommands to surface CPU profiling data from Sentry:profile list- Lists transactions that have profiling data availableprofile view <transaction>- Analyzes CPU profile for a transaction, showing hot paths and performance metricsFeatures
--all-framesto include all)--webflag to open profiles in Sentry UIUsage 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 validationCloses #56