3
0
mirror of https://github.com/grafana/grafana.git synced 2025-02-25 18:55:37 -06:00
grafana/public/app/features/explore/TraceView/components/TraceTimelineViewer/index.tsx
Joey c9faaf7600
Tempo: Fix missing deep span link ()
* Fix span deep link not showing

* Update test
2023-11-13 11:10:19 +00:00

225 lines
7.2 KiB
TypeScript

// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { css } from '@emotion/css';
import React, { RefObject } from 'react';
import { GrafanaTheme2, LinkModel, TimeZone } from '@grafana/data';
import { config, reportInteraction } from '@grafana/runtime';
import { stylesFactory, withTheme2 } from '@grafana/ui';
import { autoColor } from '../Theme';
import { merge as mergeShortcuts } from '../keyboard-shortcuts';
import { SpanBarOptions } from '../settings/SpanBarSettings';
import { CriticalPathSection, SpanLinkFunc, TNil } from '../types';
import TTraceTimeline from '../types/TTraceTimeline';
import { TraceSpan, Trace, TraceLog, TraceKeyValuePair, TraceLink, TraceSpanReference } from '../types/trace';
import TimelineHeaderRow from './TimelineHeaderRow';
import VirtualizedTraceView from './VirtualizedTraceView';
import { TUpdateViewRangeTimeFunction, ViewRange, ViewRangeTimeUpdate } from './types';
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
return {
TraceTimelineViewer: css`
label: TraceTimelineViewer;
border-bottom: 1px solid ${autoColor(theme, '#bbb')};
& .json-markup {
line-height: 17px;
font-size: 13px;
font-family: monospace;
white-space: pre-wrap;
}
& .json-markup-key {
font-weight: bold;
}
& .json-markup-bool {
color: ${autoColor(theme, 'firebrick')};
}
& .json-markup-string {
color: ${autoColor(theme, 'teal')};
}
& .json-markup-null {
color: ${autoColor(theme, 'teal')};
}
& .json-markup-number {
color: ${autoColor(theme, 'blue', 'black')};
}
`,
};
});
export type TProps = {
findMatchesIDs: Set<string> | TNil;
traceTimeline: TTraceTimeline;
trace: Trace;
datasourceType: string;
spanBarOptions: SpanBarOptions | undefined;
updateNextViewRangeTime: (update: ViewRangeTimeUpdate) => void;
updateViewRangeTime: TUpdateViewRangeTimeFunction;
viewRange: ViewRange;
timeZone: TimeZone;
setSpanNameColumnWidth: (width: number) => void;
collapseAll: (spans: TraceSpan[]) => void;
collapseOne: (spans: TraceSpan[]) => void;
expandAll: () => void;
expandOne: (spans: TraceSpan[]) => void;
childrenToggle: (spanID: string) => void;
detailLogItemToggle: (spanID: string, log: TraceLog) => void;
detailLogsToggle: (spanID: string) => void;
detailWarningsToggle: (spanID: string) => void;
detailStackTracesToggle: (spanID: string) => void;
detailReferencesToggle: (spanID: string) => void;
detailReferenceItemToggle: (spanID: string, reference: TraceSpanReference) => void;
detailProcessToggle: (spanID: string) => void;
detailTagsToggle: (spanID: string) => void;
detailToggle: (spanID: string) => void;
addHoverIndentGuideId: (spanID: string) => void;
removeHoverIndentGuideId: (spanID: string) => void;
linksGetter: (span: TraceSpan, items: TraceKeyValuePair[], itemIndex: number) => TraceLink[];
theme: GrafanaTheme2;
createSpanLink?: SpanLinkFunc;
scrollElement?: Element;
focusedSpanId?: string;
focusedSpanIdForSearch: string;
showSpanFilterMatchesOnly: boolean;
showCriticalPathSpansOnly: boolean;
createFocusSpanLink: (traceId: string, spanId: string) => LinkModel;
topOfViewRef?: RefObject<HTMLDivElement>;
headerHeight: number;
criticalPath: CriticalPathSection[];
};
type State = {
// Will be set to real height of the component so it can be passed down to size some other elements.
height: number;
};
const NUM_TICKS = 5;
/**
* `TraceTimelineViewer` now renders the header row because it is sensitive to
* `props.viewRange.time.cursor`. If `VirtualizedTraceView` renders it, it will
* re-render the ListView every time the cursor is moved on the trace minimap
* or `TimelineHeaderRow`.
*/
export class UnthemedTraceTimelineViewer extends React.PureComponent<TProps, State> {
constructor(props: TProps) {
super(props);
this.state = { height: 0 };
}
componentDidMount() {
mergeShortcuts({
collapseAll: this.collapseAll,
expandAll: this.expandAll,
collapseOne: this.collapseOne,
expandOne: this.expandOne,
});
}
collapseAll = () => {
this.props.collapseAll(this.props.trace.spans);
reportInteraction('grafana_traces_traceID_expand_collapse_clicked', {
datasourceType: this.props.datasourceType,
grafana_version: config.buildInfo.version,
type: 'collapseAll',
});
};
collapseOne = () => {
this.props.collapseOne(this.props.trace.spans);
reportInteraction('grafana_traces_traceID_expand_collapse_clicked', {
datasourceType: this.props.datasourceType,
grafana_version: config.buildInfo.version,
type: 'collapseOne',
});
};
expandAll = () => {
this.props.expandAll();
reportInteraction('grafana_traces_traceID_expand_collapse_clicked', {
datasourceType: this.props.datasourceType,
grafana_version: config.buildInfo.version,
type: 'expandAll',
});
};
expandOne = () => {
this.props.expandOne(this.props.trace.spans);
reportInteraction('grafana_traces_traceID_expand_collapse_clicked', {
datasourceType: this.props.datasourceType,
grafana_version: config.buildInfo.version,
type: 'expandOne',
});
};
render() {
const {
setSpanNameColumnWidth,
updateNextViewRangeTime,
updateViewRangeTime,
viewRange,
traceTimeline,
theme,
topOfViewRef,
focusedSpanIdForSearch,
...rest
} = this.props;
const { trace } = rest;
const styles = getStyles(theme);
return (
<div
className={styles.TraceTimelineViewer}
ref={(ref: HTMLDivElement | null) => ref && this.setState({ height: ref.getBoundingClientRect().height })}
>
<TimelineHeaderRow
duration={trace.duration}
nameColumnWidth={traceTimeline.spanNameColumnWidth}
numTicks={NUM_TICKS}
onCollapseAll={this.collapseAll}
onCollapseOne={this.collapseOne}
onColummWidthChange={setSpanNameColumnWidth}
onExpandAll={this.expandAll}
onExpandOne={this.expandOne}
viewRangeTime={viewRange.time}
updateNextViewRangeTime={updateNextViewRangeTime}
updateViewRangeTime={updateViewRangeTime}
columnResizeHandleHeight={this.state.height}
/>
<VirtualizedTraceView
{...rest}
{...traceTimeline}
setSpanNameColumnWidth={setSpanNameColumnWidth}
currentViewRangeTime={viewRange.time.current}
topOfViewRef={topOfViewRef}
focusedSpanIdForSearch={focusedSpanIdForSearch}
datasourceType={this.props.datasourceType}
/>
</div>
);
}
}
export default withTheme2(UnthemedTraceTimelineViewer);