// 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 React from 'react'; import { css } from 'emotion'; import TimelineHeaderRow from './TimelineHeaderRow'; import VirtualizedTraceView from './VirtualizedTraceView'; import { merge as mergeShortcuts } from '../keyboard-shortcuts'; import { Accessors } from '../ScrollManager'; import { TUpdateViewRangeTimeFunction, ViewRange, ViewRangeTimeUpdate } from './types'; import { TNil } from '../types'; import { TraceSpan, Trace, TraceLog, TraceKeyValuePair, TraceLink } from '../types/trace'; import TTraceTimeline from '../types/TTraceTimeline'; import { autoColor, createStyle, Theme, withTheme } from '../Theme'; import ExternalLinkContext from '../url/externalLinkContext'; type TExtractUiFindFromStateReturn = { uiFind: string | undefined; }; const getStyles = createStyle((theme: Theme) => { 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')}; } `, }; }); type TProps = TExtractUiFindFromStateReturn & { registerAccessors: (accessors: Accessors) => void; findMatchesIDs: Set | TNil; scrollToFirstVisibleSpan: () => void; traceTimeline: TTraceTimeline; trace: Trace; updateNextViewRangeTime: (update: ViewRangeTimeUpdate) => void; updateViewRangeTime: TUpdateViewRangeTimeFunction; viewRange: ViewRange; focusSpan: (uiFind: string) => void; createLinkToExternalSpan: (traceID: string, spanID: string) => string; setSpanNameColumnWidth: (width: number) => void; collapseAll: (spans: TraceSpan[]) => void; collapseOne: (spans: TraceSpan[]) => void; expandAll: () => void; expandOne: (spans: TraceSpan[]) => void; childrenToggle: (spanID: string) => void; clearShouldScrollToFirstUiFindMatch: () => void; detailLogItemToggle: (spanID: string, log: TraceLog) => void; detailLogsToggle: (spanID: string) => void; detailWarningsToggle: (spanID: string) => void; detailStackTracesToggle: (spanID: string) => void; detailReferencesToggle: (spanID: string) => void; detailProcessToggle: (spanID: string) => void; detailTagsToggle: (spanID: string) => void; detailToggle: (spanID: string) => void; setTrace: (trace: Trace | TNil, uiFind: string | TNil) => void; addHoverIndentGuideId: (spanID: string) => void; removeHoverIndentGuideId: (spanID: string) => void; linksGetter: (span: TraceSpan, items: TraceKeyValuePair[], itemIndex: number) => TraceLink[]; theme: Theme; createSpanLink?: ( span: TraceSpan ) => { href: string; onClick?: (e: React.MouseEvent) => void; content: React.ReactNode }; scrollElement?: Element; }; 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 { 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); }; collapseOne = () => { this.props.collapseOne(this.props.trace.spans); }; expandAll = () => { this.props.expandAll(); }; expandOne = () => { this.props.expandOne(this.props.trace.spans); }; render() { const { setSpanNameColumnWidth, updateNextViewRangeTime, updateViewRangeTime, viewRange, createLinkToExternalSpan, traceTimeline, theme, ...rest } = this.props; const { trace } = rest; const styles = getStyles(theme); return (
ref && this.setState({ height: ref.getBoundingClientRect().height })} >
); } } export default withTheme(UnthemedTraceTimelineViewer);