diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.test.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.test.js index bddabc961e..853af163df 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.test.js @@ -46,9 +46,10 @@ describe('', () => { let wrapper; const data = [ - { key: 'span.kind', value: 'client' }, - { key: 'omg', value: 'mos-def' }, - { key: 'numericString', value: '12345678901234567890' }, + { key: 'span.kind', value: 'client', expected: 'client' }, + { key: 'omg', value: 'mos-def', expected: 'mos-def' }, + { key: 'numericString', value: '12345678901234567890', expected: '12345678901234567890' }, + { key: 'numeric', value: 123456789, expected: '123456789' }, { key: 'jsonkey', value: JSON.stringify({ hello: 'world' }) }, ]; @@ -138,7 +139,7 @@ describe('', () => { expect(el.length).toBe(data.length); el.forEach((valueDiv, i) => { if (data[i].key !== 'jsonkey') { - expect(valueDiv.html()).toMatch(`"${data[i].value}"`); + expect(valueDiv.html()).toMatch(data[i].expected); } }); }); diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.tsx b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.tsx index 2b316068d8..d325306080 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.tsx +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.tsx @@ -25,16 +25,42 @@ import './KeyValuesTable.css'; const jsonObjectOrArrayStartRegex = /^(\[|\{)/; -function parseIfComplexJson(value: any) { +function tryParseJson(value: string) { // if the value is a string representing actual json object or array, then use json-markup - if (typeof value === 'string' && jsonObjectOrArrayStartRegex.test(value)) { - // otherwise just return as is - try { - return JSON.parse(value); - // eslint-disable-next-line no-empty - } catch (_) {} + // otherwise just return as is + try { + return jsonObjectOrArrayStartRegex.test(value) ? JSON.parse(value) : value; + } catch (_) { + return value; } - return value; +} + +const stringMarkup = (value: string) => ( +
+ {value} +
+); + +function _jsonMarkup(value: any) { + const markup = { __html: jsonMarkup(value) }; + + return ( + // eslint-disable-next-line react/no-danger +
+ ); +} + +function formatValue(value: any) { + let content; + + if (typeof value === 'string') { + const parsed = tryParseJson(value); + content = typeof parsed === 'string' ? stringMarkup(parsed) : _jsonMarkup(parsed); + } else { + content = _jsonMarkup(value); + } + + return
{content}
; } export const LinkValue = (props: { href: string; title?: string; children: React.ReactNode }) => ( @@ -71,11 +97,7 @@ export default function KeyValuesTable(props: KeyValuesTableProps) { {data.map((row, i) => { - const markup = { - __html: jsonMarkup(parseIfComplexJson(row.value)), - }; - // eslint-disable-next-line react/no-danger - const jsonTable =
; + const jsonTable = formatValue(row.value); const links = linksGetter ? linksGetter(data, i) : null; let valueMarkup; if (links && links.length === 1) {