-
-
Notifications
You must be signed in to change notification settings - Fork 7
feat(event): add 'sentry event list' command for issue-scoped event listing #671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
c291a74
feat(event): add 'sentry event list' command for issue-scoped event l…
BYK a9bd0c8
chore: regenerate skill files and command docs
github-actions[bot] 6b6d816
chore: regenerate skill files and command docs
github-actions[bot] 39faa8d
refactor: consolidate limit constants into shared LIST_MAX_LIMIT/LIST…
BYK f34a490
chore: regenerate skill files and command docs
github-actions[bot] 5c011bd
fix: register event list in ORG_PROJECT_COMMANDS and update synonym test
BYK d0b8ce1
fix(event-list): guard against undefined issueArg from interceptSubco…
BYK 76edd1c
fix: restore 100 default limit for log commands
BYK 4c088dc
chore: regenerate skill files and command docs
github-actions[bot] 3782284
fix: pass commandBase through to resolveNumericIssue error hints
BYK File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,20 @@ | ||
| import { buildRouteMap } from "@stricli/core"; | ||
| import { listCommand } from "./list.js"; | ||
| import { viewCommand } from "./view.js"; | ||
|
|
||
| export const eventRoute = buildRouteMap({ | ||
| routes: { | ||
| view: viewCommand, | ||
| list: listCommand, | ||
| }, | ||
| defaultCommand: "view", | ||
| aliases: { show: "view" }, | ||
| docs: { | ||
| brief: "View Sentry events", | ||
| brief: "View and list Sentry events", | ||
| fullDescription: | ||
| "View detailed event data from Sentry. " + | ||
| "Use 'sentry event view <event-id>' to view a specific event.", | ||
| "View and list event data from Sentry.\n\n" + | ||
| "Use 'sentry event view <event-id>' to view a specific event.\n" + | ||
| "Use 'sentry event list <issue-id>' to list events for an issue.", | ||
| hideRoute: {}, | ||
| }, | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| /** | ||
| * sentry event list | ||
| * | ||
| * List events for a specific Sentry issue. | ||
| * This is the top-level event listing command — functionally equivalent to | ||
| * `sentry issue events` but living in the `event` route. The `sentry events` | ||
| * plural alias points here. | ||
| */ | ||
|
|
||
| import type { SentryContext } from "../../context.js"; | ||
| import { listIssueEvents } from "../../lib/api-client.js"; | ||
| import { | ||
| advancePaginationState, | ||
| buildPaginationContextKey, | ||
| hasPreviousPage, | ||
| resolveCursor, | ||
| } from "../../lib/db/pagination.js"; | ||
| import { ContextError } from "../../lib/errors.js"; | ||
| import { CommandOutput } from "../../lib/formatters/output.js"; | ||
| import { buildListCommand, paginationHint } from "../../lib/list-command.js"; | ||
| import { withProgress } from "../../lib/polling.js"; | ||
| import { IssueEventSchema } from "../../types/index.js"; | ||
| import { | ||
| buildCommandHint, | ||
| issueIdPositional, | ||
| resolveIssue, | ||
| } from "../issue/utils.js"; | ||
| import { | ||
| appendEventsFlags, | ||
| EVENTS_ALIASES, | ||
| EVENTS_FLAGS, | ||
| type EventsFlags, | ||
| formatEventsHuman, | ||
| jsonTransformEvents, | ||
| } from "./shared-events.js"; | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
| // Constants | ||
| // --------------------------------------------------------------------------- | ||
|
|
||
| /** Command name used in issue resolution error messages */ | ||
| const COMMAND_NAME = "list"; | ||
|
|
||
| /** Base command prefix for error hints */ | ||
| const COMMAND_BASE = "sentry event"; | ||
|
|
||
| /** Command key for pagination cursor storage */ | ||
| const PAGINATION_KEY = "event-list"; | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
| // Pagination hints | ||
| // --------------------------------------------------------------------------- | ||
|
|
||
| /** Build the CLI hint for fetching the next page, preserving active flags. */ | ||
| function nextPageHint( | ||
| issueArg: string, | ||
| flags: Pick<EventsFlags, "query" | "full" | "period"> | ||
| ): string { | ||
| return appendEventsFlags(`sentry event list ${issueArg} -c next`, flags); | ||
| } | ||
|
|
||
| /** Build the CLI hint for fetching the previous page, preserving active flags. */ | ||
| function prevPageHint( | ||
| issueArg: string, | ||
| flags: Pick<EventsFlags, "query" | "full" | "period"> | ||
| ): string { | ||
| return appendEventsFlags(`sentry event list ${issueArg} -c prev`, flags); | ||
| } | ||
|
|
||
| // --------------------------------------------------------------------------- | ||
| // Command definition | ||
| // --------------------------------------------------------------------------- | ||
|
|
||
| export const listCommand = buildListCommand("event", { | ||
| docs: { | ||
| brief: "List events for an issue", | ||
| fullDescription: | ||
| "List events belonging to a Sentry issue.\n\n" + | ||
| "Issue formats:\n" + | ||
| " @latest - Most recent unresolved issue\n" + | ||
| " @most_frequent - Issue with highest event frequency\n" + | ||
| " <org>/ID - Explicit org: sentry/EXTENSION-7\n" + | ||
| " <project>-suffix - Project + suffix: cli-G\n" + | ||
| " ID - Short ID: CLI-G\n" + | ||
| " numeric - Numeric ID: 123456789\n\n" + | ||
| "Examples:\n" + | ||
| " sentry event list CLI-G\n" + | ||
| " sentry event list @latest --limit 50\n" + | ||
| " sentry event list 123456789 --full\n" + | ||
| ' sentry event list CLI-G -q "user.email:foo@bar.com"\n' + | ||
| " sentry event list CLI-G --json", | ||
| }, | ||
| output: { | ||
| human: formatEventsHuman, | ||
| jsonTransform: jsonTransformEvents, | ||
| schema: IssueEventSchema, | ||
| }, | ||
| parameters: { | ||
| positional: issueIdPositional, | ||
| flags: EVENTS_FLAGS, | ||
| aliases: EVENTS_ALIASES, | ||
| }, | ||
| async *func(this: SentryContext, flags: EventsFlags, issueArg: string) { | ||
| const { cwd } = this; | ||
|
|
||
| // Resolve issue using shared resolution logic (supports @latest, short IDs, etc.) | ||
| const { org, issue } = await resolveIssue({ | ||
| issueArg, | ||
| cwd, | ||
| command: COMMAND_NAME, | ||
| commandBase: COMMAND_BASE, | ||
| }); | ||
|
|
||
| // Org is required for region-routed events endpoint | ||
| if (!org) { | ||
| throw new ContextError( | ||
| "Organization", | ||
| buildCommandHint(COMMAND_NAME, issueArg, COMMAND_BASE) | ||
| ); | ||
| } | ||
|
|
||
| // Build context key for pagination (keyed by issue ID + query-varying params) | ||
| const contextKey = buildPaginationContextKey( | ||
| "event-list", | ||
| `${org}/${issue.id}`, | ||
| { q: flags.query, period: flags.period } | ||
| ); | ||
| const { cursor, direction } = resolveCursor( | ||
| flags.cursor, | ||
| PAGINATION_KEY, | ||
| contextKey | ||
| ); | ||
|
|
||
| const { data: events, nextCursor } = await withProgress( | ||
| { | ||
| message: `Fetching events for ${issue.shortId} (up to ${flags.limit})...`, | ||
| json: flags.json, | ||
| }, | ||
| () => | ||
| listIssueEvents(org, issue.id, { | ||
| limit: flags.limit, | ||
| query: flags.query, | ||
| full: flags.full, | ||
| cursor, | ||
| statsPeriod: flags.period, | ||
| }) | ||
| ); | ||
|
|
||
| // Update pagination state (handles both advance and truncation) | ||
| advancePaginationState(PAGINATION_KEY, contextKey, direction, nextCursor); | ||
| const hasPrev = hasPreviousPage(PAGINATION_KEY, contextKey); | ||
|
|
||
| const hasMore = !!nextCursor; | ||
|
|
||
| // Build footer hint based on result state | ||
| const nav = paginationHint({ | ||
| hasMore, | ||
| hasPrev, | ||
| prevHint: prevPageHint(issueArg, flags), | ||
| nextHint: nextPageHint(issueArg, flags), | ||
| }); | ||
| let hint: string | undefined; | ||
| if (events.length === 0 && nav) { | ||
| hint = `No events on this page. ${nav}`; | ||
| } else if (events.length > 0) { | ||
| const countText = `Showing ${events.length} event${events.length === 1 ? "" : "s"}.`; | ||
| hint = nav | ||
| ? `${countText} ${nav}` | ||
| : `${countText} Use 'sentry event view <EVENT_ID>' to view full event details.`; | ||
| } | ||
|
|
||
| yield new CommandOutput({ | ||
| events, | ||
| hasMore, | ||
| hasPrev, | ||
| nextCursor, | ||
| issueShortId: issue.shortId, | ||
| issueId: issue.id, | ||
| }); | ||
| return { hint }; | ||
| }, | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.