Skip to content

Commit 35f5ab6

Browse files
fix: don't recursively parse JSON data
1 parent b47492d commit 35f5ab6

6 files changed

Lines changed: 24 additions & 12 deletions

File tree

static/app/views/explore/components/traceItemAttributes/attributesTreeValue.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,25 @@ import {isUrl} from 'sentry/utils/string/isUrl';
99
import {AnnotatedAttributeTooltip} from 'sentry/views/explore/components/annotatedAttributeTooltip';
1010
import {getAttributeItem} from 'sentry/views/explore/components/traceItemAttributes/utils';
1111
import {TraceItemMetaInfo} from 'sentry/views/explore/utils';
12-
import {tryParseJson} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/utils';
1312

1413
import type {
1514
AttributesFieldRender,
1615
AttributesTreeContent,
1716
AttributesTreeRowConfig,
1817
} from './attributesTree';
1918

19+
function tryParseJson(value: unknown) {
20+
if (typeof value !== 'string') {
21+
return undefined;
22+
}
23+
24+
try {
25+
return JSON.parse(value) as unknown;
26+
} catch {
27+
return undefined;
28+
}
29+
}
30+
2031
export function AttributesTreeValue<RendererExtra extends RenderFunctionBaggage>({
2132
config,
2233
content,
@@ -60,6 +71,7 @@ export function AttributesTreeValue<RendererExtra extends RenderFunctionBaggage>
6071
);
6172
}
6273
}
74+
6375
const parsedJson = tryParseJson(content.value);
6476
if (typeof parsedJson === 'object' && parsedJson !== null) {
6577
return (

static/app/views/performance/newTraceDetails/traceDrawer/details/highlightedAttributes.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
} from 'sentry/views/insights/pages/agents/utils/query';
2121
import {Referrer} from 'sentry/views/insights/pages/agents/utils/referrers';
2222
import {SpanFields} from 'sentry/views/insights/types';
23-
import {tryParseJson} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/utils';
23+
import {tryParseJsonRecursive} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/utils';
2424

2525
type HighlightedAttribute = {
2626
name: string;
@@ -41,15 +41,15 @@ function getAIToolDefinitions(
4141
): any[] | null {
4242
const toolDefinitions = attributes['gen_ai.tool.definitions'];
4343
if (toolDefinitions) {
44-
const parsed = tryParseJson(toolDefinitions.toString());
44+
const parsed = tryParseJsonRecursive(toolDefinitions.toString());
4545
if (Array.isArray(parsed)) {
4646
return parsed;
4747
}
4848
}
4949

5050
const availableTools = attributes['gen_ai.request.available_tools'];
5151
if (availableTools) {
52-
const parsed = tryParseJson(availableTools.toString());
52+
const parsed = tryParseJsonRecursive(availableTools.toString());
5353
if (Array.isArray(parsed)) {
5454
return parsed;
5555
}

static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/aiInput.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {AIContentRenderer} from 'sentry/views/performance/newTraceDetails/traceD
2222
import {TraceDrawerComponents} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/styles';
2323
import {
2424
parseJsonWithFix,
25-
tryParseJson,
25+
tryParseJsonRecursive,
2626
} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/utils';
2727
import type {EapSpanNode} from 'sentry/views/performance/newTraceDetails/traceModels/traceTreeNode/eapSpanNode';
2828
import type {SpanNode} from 'sentry/views/performance/newTraceDetails/traceModels/traceTreeNode/spanNode';
@@ -106,7 +106,7 @@ function parseAIMessages(messages: string): AIMessage[] | string {
106106
if (!message.role || !message.content) {
107107
return null;
108108
}
109-
const parsedContent = tryParseJson(message.content);
109+
const parsedContent = tryParseJsonRecursive(message.content);
110110
return {
111111
role: message.role,
112112
content:

static/app/views/performance/newTraceDetails/traceDrawer/details/span/eapSections/attributes.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import {
3535
findSpanAttributeValue,
3636
getTraceAttributesTreeActions,
3737
sortAttributes,
38-
tryParseJson,
38+
tryParseJsonRecursive,
3939
} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/utils';
4040
import type {EapSpanNode} from 'sentry/views/performance/newTraceDetails/traceModels/traceTreeNode/eapSpanNode';
4141
import type {UptimeCheckNode} from 'sentry/views/performance/newTraceDetails/traceModels/traceTreeNode/uptimeCheckNode';
@@ -49,7 +49,7 @@ const HIDDEN_ATTRIBUTES = ['is_segment', 'project_id', 'received'];
4949
const TRUNCATED_TEXT_ATTRIBUTES = ['gen_ai.response.text', 'gen_ai.embeddings.input'];
5050

5151
const jsonRenderer = (props: CustomRenderersProps) => {
52-
const value = tryParseJson(props.item.value);
52+
const value = tryParseJsonRecursive(props.item.value);
5353
return <StructuredData value={value} withAnnotatedText maxDefaultDepth={0} />;
5454
};
5555

static/app/views/performance/newTraceDetails/traceDrawer/details/styles.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import {getIsAiNode} from 'sentry/views/insights/pages/agents/utils/aiTraceNodes
5959
import {getIsMCPNode} from 'sentry/views/insights/pages/mcp/utils/mcpTraceNodes';
6060
import {traceAnalytics} from 'sentry/views/performance/newTraceDetails/traceAnalytics';
6161
import {useDrawerContainerRef} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/drawerContainerRefContext';
62-
import {tryParseJson} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/utils';
62+
import {tryParseJsonRecursive} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/utils';
6363
import {
6464
makeTraceContinuousProfilingLink,
6565
makeTransactionProfilingLink,
@@ -1319,7 +1319,7 @@ function MultilineJSON({
13191319
const {hoverProps, isHovered} = useHover({});
13201320
const theme = useTheme();
13211321

1322-
const json = useMemo(() => tryParseJson(value), [value]);
1322+
const json = useMemo(() => tryParseJsonRecursive(value), [value]);
13231323

13241324
// Ensure root ('$') is always expanded, while children follow maxDefaultDepth rules
13251325
const computedExpandedPaths = useMemo(() => {

static/app/views/performance/newTraceDetails/traceDrawer/details/utils.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ export function getTraceAttributesTreeActions(
247247
/**
248248
* Attempts to parse a JSON string, recursively unwrapping double-stringified arrays.
249249
*/
250-
export function tryParseJson(value: unknown): unknown {
250+
export function tryParseJsonRecursive(value: unknown): unknown {
251251
if (typeof value !== 'string') {
252252
return value;
253253
}
@@ -256,7 +256,7 @@ export function tryParseJson(value: unknown): unknown {
256256
if (!Array.isArray(parsedValue)) {
257257
return parsedValue;
258258
}
259-
return parsedValue.map((item: unknown): unknown => tryParseJson(item));
259+
return parsedValue.map((item: unknown): unknown => tryParseJsonRecursive(item));
260260
} catch {
261261
return value;
262262
}

0 commit comments

Comments
 (0)