From 42edfbf3608783bae72bae8638fb6597766993a2 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Sat, 10 Dec 2022 16:59:08 +0200 Subject: [PATCH 1/5] Adjust routing to make it possible to embed it inside the VS Code extension Add vscodeApi instance and environment global variables for VS Code injection --- packages/jaeger-ui/public/index.html | 8 +++++ packages/jaeger-ui/src/api/jaeger.js | 2 +- .../jaeger-ui/src/components/App/index.js | 7 +++++ .../components/Monitor/EmptyState/index.tsx | 4 ++- .../src/components/SearchTracePage/index.js | 29 +++++++++++++++++-- packages/jaeger-ui/typings/custom.d.ts | 5 ++++ 6 files changed, 51 insertions(+), 4 deletions(-) diff --git a/packages/jaeger-ui/public/index.html b/packages/jaeger-ui/public/index.html index 9a0f706b81..c4e67fa138 100644 --- a/packages/jaeger-ui/public/index.html +++ b/packages/jaeger-ui/public/index.html @@ -35,6 +35,14 @@ return JAEGER_VERSION; } +
diff --git a/packages/jaeger-ui/src/api/jaeger.js b/packages/jaeger-ui/src/api/jaeger.js index 0283e4179e..eb42982308 100644 --- a/packages/jaeger-ui/src/api/jaeger.js +++ b/packages/jaeger-ui/src/api/jaeger.js @@ -76,7 +76,7 @@ function getJSON(url, options = {}) { }); } -export const DEFAULT_API_ROOT = prefixUrl('/api/'); +export const DEFAULT_API_ROOT = window.VS_CODE_SETTINGS.apiBaseUrl ? `${window.VS_CODE_SETTINGS.apiBaseUrl}/api/` : prefixUrl('/api/'); export const ANALYTICS_ROOT = prefixUrl('/analytics/'); export const DEFAULT_DEPENDENCY_LOOKBACK = moment.duration(1, 'weeks').asMilliseconds(); diff --git a/packages/jaeger-ui/src/components/App/index.js b/packages/jaeger-ui/src/components/App/index.js index 32da62c2fa..9fecf249c3 100644 --- a/packages/jaeger-ui/src/components/App/index.js +++ b/packages/jaeger-ui/src/components/App/index.js @@ -54,6 +54,13 @@ export default class JaegerUIApp extends Component { } render() { + // Navigate to URL provided by VS Code + if (window.VS_CODE_SETTINGS.startPath) { + const urlToNavigate = window.VS_CODE_SETTINGS.startPath; + window.VS_CODE_SETTINGS.startPath = ""; + history.push(urlToNavigate); + } + return ( diff --git a/packages/jaeger-ui/src/components/Monitor/EmptyState/index.tsx b/packages/jaeger-ui/src/components/Monitor/EmptyState/index.tsx index 46b6e81a0e..adc6af1087 100644 --- a/packages/jaeger-ui/src/components/Monitor/EmptyState/index.tsx +++ b/packages/jaeger-ui/src/components/Monitor/EmptyState/index.tsx @@ -29,6 +29,8 @@ export default class MonitorATMEmptyState extends React.PureComponent { } render() { + const monitorImgUrl = window.VS_CODE_SETTINGS.staticPath ? new URL(monitorImg, window.VS_CODE_SETTINGS.staticPath).href : monitorImg; + return ( @@ -36,7 +38,7 @@ export default class MonitorATMEmptyState extends React.PureComponent { jaeger-monitor-tab-preview diff --git a/packages/jaeger-ui/src/components/SearchTracePage/index.js b/packages/jaeger-ui/src/components/SearchTracePage/index.js index df2c1811e5..cb34f1b90a 100644 --- a/packages/jaeger-ui/src/components/SearchTracePage/index.js +++ b/packages/jaeger-ui/src/components/SearchTracePage/index.js @@ -41,6 +41,29 @@ import JaegerLogo from '../../img/jaeger-logo.svg'; const TabPane = Tabs.TabPane; +// Sanitize query params to filter out ones provided by VS Code +const sanitizeQueryParams = (params) => { + const VS_CODE_PARAMS = [ + "id", + "origin", + "swVersion", + "extensionId", + "platform", + "vscode-resource-base-authority", + "parentOrigin" + ]; + + const filteredParams = {}; + + Object.keys(params).forEach((key) => { + if (!VS_CODE_PARAMS.includes(key)) { + filteredParams[key] = params[key] + } + }) + + return filteredParams; +}; + // export for tests export class SearchTracePageImpl extends Component { componentDidMount() { @@ -97,6 +120,7 @@ export class SearchTracePageImpl extends Component { const hasTraceResults = traceResults && traceResults.length > 0; const showErrors = errors && !loadingTraces; const showLogo = isHomepage && !hasTraceResults && !loadingTraces && !errors; + const logoUrl = window.VS_CODE_SETTINGS.staticPath ? new URL(JaegerLogo, window.VS_CODE_SETTINGS.staticPath).href : JaegerLogo; return ( {!embedded && ( @@ -147,7 +171,7 @@ export class SearchTracePageImpl extends Component { presentation )} @@ -241,6 +265,7 @@ const stateServicesXformer = memoizeOne(stateServices => { export function mapStateToProps(state) { const { embedded, router, services: stServices, traceDiff } = state; const query = getUrlState(router.location.search); + const sanitizedQuery = sanitizeQueryParams(query); const isHomepage = !Object.keys(query).length; const { query: queryOfResults, traces, maxDuration, traceError, loadingTraces } = stateTraceXformer( state.trace @@ -268,7 +293,7 @@ export function mapStateToProps(state) { errors: errors.length ? errors : null, maxTraceDuration: maxDuration, sortTracesBy: sortBy, - urlQueryParams: Object.keys(query).length > 0 ? query : null, + urlQueryParams: Object.keys(sanitizedQuery).length > 0 ? sanitizedQuery : null, }; } diff --git a/packages/jaeger-ui/typings/custom.d.ts b/packages/jaeger-ui/typings/custom.d.ts index f8bd4fe180..29ff8384fe 100644 --- a/packages/jaeger-ui/typings/custom.d.ts +++ b/packages/jaeger-ui/typings/custom.d.ts @@ -23,6 +23,11 @@ declare interface Window { // For getting ui config getJaegerUiConfig?: () => Record; getJaegerVersion?: () => Record; + VS_CODE_SETTINGS: { + apiBaseUrl: string; + startPath: string; + staticPath: string; + } } // For inlined envvars From 2d34b1b3bac3afbad4a285f96239f1c69dd209f4 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Tue, 13 Dec 2022 02:48:31 +0200 Subject: [PATCH 2/5] Add post messaging between VS Code extension and Jaeger UI Send spans for location resolution on Trace page load Handle location availability for spans, showing corresponding icon Add navigation to code for span --- packages/jaeger-ui/public/index.html | 11 + .../TraceTimelineViewer/SpanBarRow.css | 9 +- .../TraceTimelineViewer/SpanBarRow.tsx | 33 ++- .../TraceTimelineViewer/SpanDetail/index.tsx | 254 ++++++++++-------- .../src/components/TracePage/index.tsx | 9 + packages/jaeger-ui/src/img/code.svg | 1 + packages/jaeger-ui/typings/custom.d.ts | 3 + 7 files changed, 209 insertions(+), 111 deletions(-) create mode 100644 packages/jaeger-ui/src/img/code.svg diff --git a/packages/jaeger-ui/public/index.html b/packages/jaeger-ui/public/index.html index c4e67fa138..e5aeeadf01 100644 --- a/packages/jaeger-ui/public/index.html +++ b/packages/jaeger-ui/public/index.html @@ -42,6 +42,17 @@ startPath: "", staticPath: "", }; + + // Store list of trace spans with resolved location globally + var spansWithResolvedLocation = {}; + + window.addEventListener("message", (e) => { + const message = e.data; + switch (message.command) { + case "setSpansWithResolvedLocation": + spansWithResolvedLocation = message.data; + } + }); diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css index 0fef447ef0..ba6c5384d2 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css @@ -81,7 +81,7 @@ limitations under the License. outline: none; overflow: hidden; padding-left: 4px; - padding-right: 0.25em; + padding-right: 15px; position: relative; text-overflow: ellipsis; } @@ -123,6 +123,13 @@ limitations under the License. color: #000; } +.code-location { + position: absolute; + height: 70%; + top: 15%; + right: 5px; +} + .span-svc-name { padding: 0 0.25rem 0 0.5rem; font-size: 1.05em; diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx index 199fd0abf3..ce3a9d3c9f 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx @@ -27,6 +27,8 @@ import Ticks from './Ticks'; import { TNil } from '../../../types'; import { Span } from '../../../types/trace'; +import codeIcon from '../../../img/code.svg'; + import './SpanBarRow.css'; type SpanBarRowProps = { @@ -61,6 +63,10 @@ type SpanBarRowProps = { focusSpan: (spanID: string) => void; }; +type SpanBarRowState = { + hasResolvedLocation: boolean; +} + /** * This was originally a stateless function, but changing to a PureComponent * reduced the render time of expanding a span row detail by ~50%. This is @@ -69,7 +75,14 @@ type SpanBarRowProps = { * handlers to the onClick props. E.g. for now, the PureComponent is more * performance than the stateless function. */ -export default class SpanBarRow extends React.PureComponent { +export default class SpanBarRow extends React.PureComponent { + constructor(props: SpanBarRowProps) { + super(props); + this.state = { + hasResolvedLocation: window.spansWithResolvedLocation[props.span.spanID] + } + } + static defaultProps = { className: '', rpc: null, @@ -83,6 +96,21 @@ export default class SpanBarRow extends React.PureComponent { this.props.onChildrenToggled(this.props.span.spanID); }; + updateResolvedLocation = (e:{ data: { command: string, data: Record }}) => { + const message = e.data; + if (message.command === "setSpansWithResolvedLocation") { + this.setState({ hasResolvedLocation: message.data[this.props.span.spanID] }) + } + } + + componentDidMount(): void { + window.addEventListener('message', this.updateResolvedLocation); + } + + componentWillUnmount(): void { + window.removeEventListener('message', this.updateResolvedLocation); + } + render() { const { className, @@ -122,6 +150,8 @@ export default class SpanBarRow extends React.PureComponent { hintSide = 'right'; } + const codeIconUrl = window.VS_CODE_SETTINGS.staticPath ? new URL(codeIcon, window.VS_CODE_SETTINGS.staticPath).href : codeIcon; + return ( { )} {rpc ? rpc.operationName : operationName} + {this.state.hasResolvedLocation && } {span.references && span.references.length > 1 && ( void; }; -export default function SpanDetail(props: SpanDetailProps) { - const { - detailState, - linksGetter, - logItemToggle, - logsToggle, - processToggle, - span, - tagsToggle, - traceStartTime, - warningsToggle, - referencesToggle, - focusSpan, - } = props; - const { isTagsOpen, isProcessOpen, logs: logsState, isWarningsOpen, isReferencesOpen } = detailState; - const { - operationName, - process, - duration, - relativeStartTime, - spanID, - logs, - tags, - warnings, - references, - } = span; - const overviewItems = [ - { - key: 'svc', - label: 'Service:', - value: process.serviceName, - }, - { - key: 'duration', - label: 'Duration:', - value: formatDuration(duration), - }, - { - key: 'start', - label: 'Start Time:', - value: formatDuration(relativeStartTime), - }, - ]; - const deepLinkCopyText = `${window.location.origin}${window.location.pathname}?uiFind=${spanID}`; +type SpanDetailState = { + hasResolvedLocation: boolean; +} - return ( -
-
-

{operationName}

- -
- +export default class SpanDetail extends React.Component { + constructor(props: SpanDetailProps) { + super(props); + this.state = { + hasResolvedLocation: window.spansWithResolvedLocation[props.span.spanID] + } + } + + updateResolvedLocation = (e:{ data: { command: string, data: Record }}) => { + const message = e.data; + if (message.command === "setSpansWithResolvedLocation") { + this.setState({ hasResolvedLocation: message.data[this.props.span.spanID] }) + } + } + + componentDidMount(): void { + window.addEventListener('message', this.updateResolvedLocation); + } + + componentWillUnmount(): void { + window.removeEventListener('message', this.updateResolvedLocation); + } + + render() { + const { + detailState, + linksGetter, + logItemToggle, + logsToggle, + processToggle, + span, + tagsToggle, + traceStartTime, + warningsToggle, + referencesToggle, + focusSpan, + } = this.props; + const { isTagsOpen, isProcessOpen, logs: logsState, isWarningsOpen, isReferencesOpen } = detailState; + const { + operationName, + process, + duration, + relativeStartTime, + spanID, + logs, + tags, + warnings, + references, + } = span; + const overviewItems = [ + { + key: 'svc', + label: 'Service:', + value: process.serviceName, + }, + { + key: 'duration', + label: 'Duration:', + value: formatDuration(duration), + }, + { + key: 'start', + label: 'Start Time:', + value: formatDuration(relativeStartTime), + }, + ]; + const deepLinkCopyText = `${window.location.origin}${window.location.pathname}?uiFind=${spanID}`; + + const handleGoToCodeLinkClick = (e: React.MouseEvent) => { + window.vscode && window.vscode.postMessage({ + command: "goToSpanLocation", + data: span + }); + } + + return (
-
- tagsToggle(spanID)} +
+

{operationName}

+ {this.state.hasResolvedLocation && Go to code} + - {process.tags && ( +
+ +
+
processToggle(spanID)} + isOpen={isTagsOpen} + onToggle={() => tagsToggle(spanID)} + /> + {process.tags && ( + processToggle(spanID)} + /> + )} +
+ {logs && logs.length > 0 && ( + logsToggle(spanID)} + onItemToggle={logItem => logItemToggle(spanID, logItem)} + timestamp={traceStartTime} /> )} -
- {logs && logs.length > 0 && ( - logsToggle(spanID)} - onItemToggle={logItem => logItemToggle(spanID, logItem)} - timestamp={traceStartTime} - /> - )} - {warnings && warnings.length > 0 && ( - Warnings} - data={warnings} - isOpen={isWarningsOpen} - onToggle={() => warningsToggle(spanID)} - /> - )} - {references && - references.length > 0 && - (references.length > 1 || references[0].refType !== 'CHILD_OF') && ( - referencesToggle(spanID)} - focusSpan={focusSpan} + {warnings && warnings.length > 0 && ( + Warnings} + data={warnings} + isOpen={isWarningsOpen} + onToggle={() => warningsToggle(spanID)} /> )} - - {spanID} - - + {references && + references.length > 0 && + (references.length > 1 || references[0].refType !== 'CHILD_OF') && ( + referencesToggle(spanID)} + focusSpan={focusSpan} + /> + )} + + {spanID} + + +
-
- ); + ); + } } diff --git a/packages/jaeger-ui/src/components/TracePage/index.tsx b/packages/jaeger-ui/src/components/TracePage/index.tsx index 2101bf4be3..23acf3a860 100644 --- a/packages/jaeger-ui/src/components/TracePage/index.tsx +++ b/packages/jaeger-ui/src/components/TracePage/index.tsx @@ -187,6 +187,15 @@ export class TracePageImpl extends React.PureComponent { componentDidUpdate({ id: prevID }: TProps) { const { id, trace } = this.props; + // Get all the trace spans and send it to VS Code extension + // to verify if they have resolved location + if (window.vscode && trace && trace.state && trace.state === fetchedState.DONE) { + window.vscode.postMessage({ + command: "getTraceSpansLocations", + data: trace.data + }); + } + this._scrollManager.setTrace(trace && trace.data); this.setHeaderHeight(this._headerElm); diff --git a/packages/jaeger-ui/src/img/code.svg b/packages/jaeger-ui/src/img/code.svg new file mode 100644 index 0000000000..657d3b5bd9 --- /dev/null +++ b/packages/jaeger-ui/src/img/code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/jaeger-ui/typings/custom.d.ts b/packages/jaeger-ui/typings/custom.d.ts index 29ff8384fe..ac28f2c601 100644 --- a/packages/jaeger-ui/typings/custom.d.ts +++ b/packages/jaeger-ui/typings/custom.d.ts @@ -23,6 +23,8 @@ declare interface Window { // For getting ui config getJaegerUiConfig?: () => Record; getJaegerVersion?: () => Record; + vscode?: Record; + spansWithResolvedLocation: Record; VS_CODE_SETTINGS: { apiBaseUrl: string; startPath: string; @@ -52,3 +54,4 @@ declare module 'json-markup'; declare module 'react-vis-force'; declare module 'tween-functions'; declare module '*.png' { export default '' as string; } +declare module "*.svg" { export default '' as string; } From d3e09e32477e282c3b9c325b6dd51798d5ca5226 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Tue, 13 Dec 2022 11:37:47 +0200 Subject: [PATCH 3/5] Add global variable for embedded mode Adjust styles for span code navigation link --- packages/jaeger-ui/public/index.html | 1 + .../TraceTimelineViewer/SpanDetail/index.css | 10 ++++++++++ .../TraceTimelineViewer/SpanDetail/index.tsx | 13 +++++++++++-- packages/jaeger-ui/src/reducers/embedded.tsx | 11 +++++++++-- packages/jaeger-ui/typings/custom.d.ts | 1 + 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/jaeger-ui/public/index.html b/packages/jaeger-ui/public/index.html index e5aeeadf01..979216fda0 100644 --- a/packages/jaeger-ui/public/index.html +++ b/packages/jaeger-ui/public/index.html @@ -41,6 +41,7 @@ apiBaseUrl: "", startPath: "", staticPath: "", + embeddedMode: false, }; // Store list of trace spans with resolved location globally diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css index b77a545cd7..8b75e512c2 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css @@ -14,6 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ +.SpanDetail--operationNameLink { + font-weight: 500; + display: block; + font-size: 1.5em; + margin-block-start: 0.83em; + margin-block-end: 0.83em; + margin-inline-start: 0px; + margin-inline-end: 0px; +} + .SpanDetail--divider { background: #ddd; } diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.tsx b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.tsx index 0d36b2d4a4..edfcb83da2 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.tsx +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.tsx @@ -23,6 +23,7 @@ import DetailState from './DetailState'; import { formatDuration } from '../utils'; import CopyIcon from '../../../common/CopyIcon'; import LabeledList from '../../../common/LabeledList'; +import { Link as RouterLink } from 'react-router-dom'; import { TNil } from '../../../../types'; import { KeyValuePair, Link, Log, Span } from '../../../../types/trace'; @@ -116,6 +117,7 @@ export default class SpanDetail extends React.Component) => { + e.preventDefault(); window.vscode && window.vscode.postMessage({ command: "goToSpanLocation", data: span @@ -125,8 +127,15 @@ export default class SpanDetail extends React.Component
-

{operationName}

- {this.state.hasResolvedLocation && Go to code} + {this.state.hasResolvedLocation ? + + {operationName} + :

{operationName}

+ } Date: Tue, 13 Dec 2022 17:15:06 +0200 Subject: [PATCH 4/5] Add importance marker to the spans --- .../TraceTimelineViewer/SpanBarRow.css | 11 ++++-- .../TraceTimelineViewer/SpanBarRow.tsx | 36 ++++++++++++++++--- .../TraceTimelineViewer/SpanDetail/index.tsx | 26 ++++++++++---- .../src/components/TracePage/index.tsx | 17 +++++++-- .../jaeger-ui/src/img/exclamation-mark.svg | 11 ++++++ packages/jaeger-ui/typings/custom.d.ts | 2 +- 6 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 packages/jaeger-ui/src/img/exclamation-mark.svg diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css index ba6c5384d2..d9fecb971b 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css @@ -81,7 +81,7 @@ limitations under the License. outline: none; overflow: hidden; padding-left: 4px; - padding-right: 15px; + padding-right: 40px; position: relative; text-overflow: ellipsis; } @@ -123,7 +123,14 @@ limitations under the License. color: #000; } -.code-location { +.importance-icon { + position: absolute; + height: 60%; + top: 20%; + right: 25px; +} + +.code-location-icon { position: absolute; height: 70%; top: 15%; diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx index ce3a9d3c9f..bc86ba5306 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx @@ -28,9 +28,15 @@ import { TNil } from '../../../types'; import { Span } from '../../../types/trace'; import codeIcon from '../../../img/code.svg'; +import exclamationMarkIcon from '../../../img/exclamation-mark.svg'; import './SpanBarRow.css'; +type SpanInfo = { + hasResolvedLocation: boolean, + importance?: number +} + type SpanBarRowProps = { className?: string; color: string; @@ -65,6 +71,7 @@ type SpanBarRowProps = { type SpanBarRowState = { hasResolvedLocation: boolean; + importance?: number; } /** @@ -78,8 +85,9 @@ type SpanBarRowState = { export default class SpanBarRow extends React.PureComponent { constructor(props: SpanBarRowProps) { super(props); + const span = window.spansWithResolvedLocation[props.span.spanID] this.state = { - hasResolvedLocation: window.spansWithResolvedLocation[props.span.spanID] + hasResolvedLocation: Boolean(span) && span.hasResolvedLocation } } @@ -96,10 +104,14 @@ export default class SpanBarRow extends React.PureComponent }}) => { + updateResolvedLocation = (e:{ data: { command: string, data: Record }}) => { const message = e.data; if (message.command === "setSpansWithResolvedLocation") { - this.setState({ hasResolvedLocation: message.data[this.props.span.spanID] }) + const span = message.data[this.props.span.spanID]; + this.setState({ + hasResolvedLocation: span.hasResolvedLocation, + importance: span.importance + }); } } @@ -111,6 +123,17 @@ export default class SpanBarRow extends React.PureComponent {rpc ? rpc.operationName : operationName} - {this.state.hasResolvedLocation && } + { + typeof this.state.importance === "number" && [1,2].includes(this.state.importance) && + {this.getImportanceAltText(this.state.importance)} + } + {this.state.hasResolvedLocation && } {span.references && span.references.length > 1 && ( void; }; +type SpanInfo = { + hasResolvedLocation: boolean, + importance?: number +} + type SpanDetailState = { hasResolvedLocation: boolean; } @@ -51,15 +56,16 @@ type SpanDetailState = { export default class SpanDetail extends React.Component { constructor(props: SpanDetailProps) { super(props); + const span = window.spansWithResolvedLocation[props.span.spanID] this.state = { - hasResolvedLocation: window.spansWithResolvedLocation[props.span.spanID] + hasResolvedLocation: Boolean(span) && span.hasResolvedLocation } } - updateResolvedLocation = (e:{ data: { command: string, data: Record }}) => { + updateResolvedLocation = (e:{ data: { command: string, data: Record }}) => { const message = e.data; if (message.command === "setSpansWithResolvedLocation") { - this.setState({ hasResolvedLocation: message.data[this.props.span.spanID] }) + this.setState({ hasResolvedLocation: message.data[this.props.span.spanID].hasResolvedLocation }) } } @@ -118,10 +124,16 @@ export default class SpanDetail extends React.Component) => { e.preventDefault(); - window.vscode && window.vscode.postMessage({ - command: "goToSpanLocation", - data: span - }); + const tag = span.tags.find((tag: any) => tag.key === "otel.library.name"); + if (tag && window.vscode) { + window.vscode.postMessage({ + command: "goToSpanLocation", + data: { + name: span.operationName, + instrumentationLibrary: tag && tag.value + } + }); + } } return ( diff --git a/packages/jaeger-ui/src/components/TracePage/index.tsx b/packages/jaeger-ui/src/components/TracePage/index.tsx index 23acf3a860..7e2071526d 100644 --- a/packages/jaeger-ui/src/components/TracePage/index.tsx +++ b/packages/jaeger-ui/src/components/TracePage/index.tsx @@ -189,10 +189,23 @@ export class TracePageImpl extends React.PureComponent { // Get all the trace spans and send it to VS Code extension // to verify if they have resolved location - if (window.vscode && trace && trace.state && trace.state === fetchedState.DONE) { + if ( + window.vscode && + trace && + trace.data && + trace.state && + trace.state === fetchedState.DONE + ) { window.vscode.postMessage({ command: "getTraceSpansLocations", - data: trace.data + data: trace.data.spans.map(span => { + const tag = span.tags.find(tag => tag.key === "otel.library.name"); + + return { + id: span.spanID, + name: span.operationName, + instrumentationLibrary: tag && tag.value + }}).filter(span => span.instrumentationLibrary) }); } diff --git a/packages/jaeger-ui/src/img/exclamation-mark.svg b/packages/jaeger-ui/src/img/exclamation-mark.svg new file mode 100644 index 0000000000..3c258ff749 --- /dev/null +++ b/packages/jaeger-ui/src/img/exclamation-mark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/packages/jaeger-ui/typings/custom.d.ts b/packages/jaeger-ui/typings/custom.d.ts index 3a1fe9a1ad..ff2f66864e 100644 --- a/packages/jaeger-ui/typings/custom.d.ts +++ b/packages/jaeger-ui/typings/custom.d.ts @@ -24,7 +24,7 @@ declare interface Window { getJaegerUiConfig?: () => Record; getJaegerVersion?: () => Record; vscode?: Record; - spansWithResolvedLocation: Record; + spansWithResolvedLocation: Record; VS_CODE_SETTINGS: { apiBaseUrl: string; startPath: string; From c0d408ebdf02b550d5fde359c1ea946b520161cd Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Tue, 13 Dec 2022 17:56:09 +0200 Subject: [PATCH 5/5] Fix importance marker Adjust styles --- .../components/TracePage/TraceTimelineViewer/SpanBarRow.tsx | 5 +++-- .../TracePage/TraceTimelineViewer/SpanDetail/index.css | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx index bc86ba5306..f666e9fb6d 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.tsx @@ -87,7 +87,8 @@ export default class SpanBarRow extends React.PureComponent {rpc ? rpc.operationName : operationName} { - typeof this.state.importance === "number" && [1,2].includes(this.state.importance) && + typeof this.state.importance === "number" && [1,2].includes(this.state.importance) && this.state.hasResolvedLocation && {this.getImportanceAltText(this.state.importance)} } {this.state.hasResolvedLocation && } diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css index 8b75e512c2..a2c04c7c1b 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css @@ -18,10 +18,6 @@ limitations under the License. font-weight: 500; display: block; font-size: 1.5em; - margin-block-start: 0.83em; - margin-block-end: 0.83em; - margin-inline-start: 0px; - margin-inline-end: 0px; } .SpanDetail--divider {