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
83 changes: 39 additions & 44 deletions AGENTS.md

Large diffs are not rendered by default.

24 changes: 23 additions & 1 deletion src/commands/event/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { openInBrowser } from "../../lib/browser.js";
import { buildCommand } from "../../lib/command.js";
import { ApiError, ContextError, ResolutionError } from "../../lib/errors.js";
import { formatEventDetails } from "../../lib/formatters/index.js";
import { filterFields } from "../../lib/formatters/json.js";
import { CommandOutput } from "../../lib/formatters/output.js";
import {
applyFreshFlag,
Expand Down Expand Up @@ -77,6 +78,27 @@ function formatEventView(data: EventViewData): string {
return parts.join("\n");
}

/**
* Transform event view data for JSON output.
*
* Flattens the event as the primary object so that `--fields eventID,title`
* works directly on event properties. The `trace` enrichment data is
* attached as a nested key, accessible via `--fields trace.traceId`.
*
* Without this transform, `--fields eventID` would return `{}` because
* the raw yield shape is `{ event, trace }` and `eventID` lives inside `event`.
*/
function jsonTransformEventView(
data: EventViewData,
fields?: string[]
): unknown {
const { event, trace } = data;
const result: Record<string, unknown> = { ...event, trace };
if (fields && fields.length > 0) {
return filterFields(result, fields);
}
return result;
}
/** Usage hint for ContextError messages */
const USAGE_HINT = "sentry event view <org>/<project> <event-id>";

Expand Down Expand Up @@ -387,7 +409,7 @@ export const viewCommand = buildCommand({
},
output: {
human: formatEventView,
jsonExclude: ["spanTreeLines"],
jsonTransform: jsonTransformEventView,
},
parameters: {
positional: {
Expand Down
27 changes: 26 additions & 1 deletion src/commands/issue/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
isPlainOutput,
muted,
} from "../../lib/formatters/index.js";
import { filterFields } from "../../lib/formatters/json.js";
import { CommandOutput } from "../../lib/formatters/output.js";
import {
applyFreshFlag,
Expand Down Expand Up @@ -84,6 +85,30 @@ function formatIssueView(data: IssueViewData): string {
return parts.join("\n");
}

/**
* Transform issue view data for JSON output.
*
* Flattens the issue as the primary object so that `--fields shortId,title`
* works directly on issue properties. The `event` and `trace` enrichment
* data are attached as nested keys, accessible via `--fields event.id`
* or `--fields trace.traceId`.
*
* Without this transform, `--fields shortId` would return `{}` because
* the raw yield shape is `{ issue, event, trace }` and `shortId` lives
* inside `issue`.
*/
function jsonTransformIssueView(
data: IssueViewData,
fields?: string[]
): unknown {
const { issue, event, trace } = data;
const result: Record<string, unknown> = { ...issue, event, trace };
if (fields && fields.length > 0) {
return filterFields(result, fields);
}
return result;
}

export const viewCommand = buildCommand({
docs: {
brief: "View details of a specific issue",
Expand All @@ -104,7 +129,7 @@ export const viewCommand = buildCommand({
},
output: {
human: formatIssueView,
jsonExclude: ["spanTreeLines"],
jsonTransform: jsonTransformIssueView,
},
parameters: {
positional: issueIdPositional,
Expand Down
25 changes: 24 additions & 1 deletion src/commands/trace/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
formatSimpleSpanTree,
formatTraceSummary,
} from "../../lib/formatters/index.js";
import { filterFields } from "../../lib/formatters/json.js";
import { CommandOutput } from "../../lib/formatters/output.js";
import {
applyFreshFlag,
Expand Down Expand Up @@ -117,6 +118,28 @@ export function formatTraceView(data: TraceViewData): string {
return parts.join("\n");
}

/**
* Transform trace view data for JSON output.
*
* Flattens the summary as the primary object so that `--fields traceId,duration`
* works directly on summary properties. The raw `spans` array is preserved as
* a nested key, accessible via `--fields spans`.
*
* Without this transform, `--fields traceId` would return `{}` because
* the raw yield shape is `{ summary, spans }` and `traceId` lives inside `summary`.
*/
function jsonTransformTraceView(
data: TraceViewData,
fields?: string[]
): unknown {
const { summary, spans } = data;
const result: Record<string, unknown> = { ...summary, spans };
if (fields && fields.length > 0) {
return filterFields(result, fields);
}
return result;
}

export const viewCommand = buildCommand({
docs: {
brief: "View details of a specific trace",
Expand All @@ -130,7 +153,7 @@ export const viewCommand = buildCommand({
},
output: {
human: formatTraceView,
jsonExclude: ["spanTreeLines"],
jsonTransform: jsonTransformTraceView,
},
parameters: {
positional: {
Expand Down
4 changes: 2 additions & 2 deletions test/commands/trace/view.func.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ describe("viewCommand.func", () => {

const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
const parsed = JSON.parse(output);
expect(parsed).toHaveProperty("summary");
expect(parsed).toHaveProperty("traceId");
expect(parsed).toHaveProperty("spans");
expect(parsed.summary.traceId).toBe("aaaa1111bbbb2222cccc3333dddd4444");
expect(parsed.traceId).toBe("aaaa1111bbbb2222cccc3333dddd4444");
expect(parsed.spans).toHaveLength(1);
});

Expand Down
3 changes: 2 additions & 1 deletion test/e2e/trace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ describe("sentry trace view", () => {

expect(result.exitCode).toBe(0);
const data = JSON.parse(result.stdout);
expect(data).toHaveProperty("summary");
// jsonTransform flattens summary to top level (no wrapper)
expect(data).toHaveProperty("traceId");
expect(data).toHaveProperty("spans");
});

Expand Down
Loading