diff --git a/.eslintrc b/.eslintrc index 8c709b599f..fbcf4c5e89 100644 --- a/.eslintrc +++ b/.eslintrc @@ -22,6 +22,7 @@ "jsx-a11y/no-static-element-interactions": 1, "jsx-a11y/href-no-hash": 0, "jsx-a11y/label-has-for": 0, + "jsx-a11y/interactive-supports-focus": 0, /* react */ "react/jsx-filename-extension": 0, diff --git a/src/components/App/App.css b/src/components/App/App.css index 5981c33b50..42af4a05c7 100644 --- a/src/components/App/App.css +++ b/src/components/App/App.css @@ -24,6 +24,21 @@ THE SOFTWARE. height: 100%; } +.u-no-float { + float: none; +} + +.u-cursor-pointer { + cursor: pointer; +} + +/* override semantic UI webkit scrollbar styling (keep the other scroll styling) */ +body ::-webkit-scrollbar { + -webkit-appearance: none; + width: 7px; + height: 7px; +} + a { color: #11939A; } @@ -70,7 +85,7 @@ a:hover { } .ui.compact.table td { - padding: 0.1em 0.5em; + padding: 0.2em 0.5em; } .ui.table td.light-grey { diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail.js b/src/components/TracePage/TraceTimelineViewer/SpanDetail.js deleted file mode 100644 index 4bcd4d772b..0000000000 --- a/src/components/TracePage/TraceTimelineViewer/SpanDetail.js +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) 2017 Uber Technologies, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import PropTypes from 'prop-types'; -import React from 'react'; -import { withState } from 'recompose'; - -import jsonMarkup from 'json-markup'; -import _ from 'lodash'; -import { formatDuration } from './utils'; - -const collapseEnhancer = withState('open', 'onToggleOpen', false); - -function CollapsePanel(props) { - const { header, onToggleOpen, children, open } = props; - return ( -
- onToggleOpen(!open)}> - - {header} - - {open && -
- {children} -
} -
- ); -} - -CollapsePanel.propTypes = { - header: PropTypes.node.isRequired, - onToggleOpen: PropTypes.func.isRequired, - children: PropTypes.element.isRequired, - open: PropTypes.bool.isRequired, -}; - -const CollapsePanelStatefull = collapseEnhancer(CollapsePanel); - -function ExpandableDataTable(props) { - const { data, label, open, onToggleOpen } = props; - return ( -
-
onToggleOpen(!open)} - className="overflow-hidden nowrap" - style={{ - cursor: 'pointer', - textOverflow: 'ellipsis', - }} - > - - - {label} - : - - {!open && - - {data.map((row, i) => - - - {row.key}= - - {row.value.toString()} - - )} - } -
- {open && -
- - - {data.map((row, i) => { - let json; - try { - json = JSON.parse(row.value); - } catch (e) { - json = row.value; - } - return ( - // `i` is necessary in the key because row.key can repeat - - - - - ); - })} - -
- {row.key} - -
-
-
} -
- ); -} - -ExpandableDataTable.defaultProps = { - open: false, -}; -ExpandableDataTable.propTypes = { - open: PropTypes.bool, - data: PropTypes.arrayOf( - PropTypes.shape({ - key: PropTypes.string, - type: PropTypes.string, - value: PropTypes.value, - }) - ), - label: PropTypes.string, - onToggleOpen: PropTypes.func, -}; -const ExpandableDataTableStatefull = collapseEnhancer(ExpandableDataTable); - -function Logs({ logs, traceStartTime, open, onToggleOpen }) { - return ( -
- onToggleOpen(!open)} style={{ opacity: 1 }}> - - Logs ({logs.length}) - - {open && -
- {_.sortBy(logs, 'timestamp').map((log, i) => - // `i` is necessary in the key because timestamps can repeat - - )} -
- **Log timestamps are relative to the start time of the full trace. -
-
} -
- ); -} - -Logs.propTypes = { - open: PropTypes.bool, - onToggleOpen: PropTypes.func, - logs: PropTypes.arrayOf( - PropTypes.shape({ - timestamp: PropTypes.number, - fields: PropTypes.array, - }) - ), - traceStartTime: PropTypes.number, -}; - -const LogsStatefull = withState('open', 'onToggleOpen', false)(Logs); - -export default function SpanDetail(props) { - const { span, trace } = props; - return ( -
-
-

- {span.operationName} -

-
-
- Service: - - {span.process.serviceName} - -
-
- Duration: - - {formatDuration(span.duration)} - -
-
- Start Time: - - {formatDuration(span.relativeStartTime)} - -
-
-
-
-
-
- - {span.process && - span.process.tags && - } -
- {span.logs && - span.logs.length > 0 && - } -
- - - - - - -
spanID - {span.spanID} -
-
-
-
-
- ); -} -SpanDetail.propTypes = { - span: PropTypes.object, - trace: PropTypes.object, -}; diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.css b/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.css new file mode 100644 index 0000000000..25de81043e --- /dev/null +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.css @@ -0,0 +1,67 @@ +/* +Copyright (c) 2017 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +.AccordianKeyValues { + margin: 0.3em 0; + text-overflow: ellipsis; +} + +.AccordianKeyValues.is-compact { + margin: 0; +} + +.AccordianKeyValues--header { + cursor: pointer; + overflow: hidden; + margin: 0 1px; + padding: 0.25em 0.1em; + text-overflow: ellipsis; + white-space: nowrap; +} + +.AccordianKeyValues--header:hover { + background: #eee; +} + +.AccordianKeyValues--header.is-high-contrast:hover { + background: #ddd; +} + +.AccordianKeyValues--summary { + display: inline; + list-style: none; + padding: 0; +} + +.AccordianKeyValues--summaryItem { + display: inline; + margin-left: 0.7em; +} + +.AccordianKeyValues--summaryLabel { + color: #777; +} + +.AccordianKeyValues--summaryDelim { + color: #aaa; + padding: 0 0.1em; +} diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.js b/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.js new file mode 100644 index 0000000000..cb970414cc --- /dev/null +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.js @@ -0,0 +1,88 @@ +// @flow +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import React from 'react'; + +import KeyValuesTable from './KeyValuesTable'; +import toggleEnhancer from './toggle-enhancer'; + +import './AccordianKeyValues.css'; + +type KeyValuesSummaryProps = { + data: { key: string, value: any }[], +}; + +function KeyValuesSummary(props: KeyValuesSummaryProps) { + const { data } = props; + return ( +
    + {data.map((item, i) => + // `i` is necessary in the key because item.key can repeat + // eslint-disable-next-line react/no-array-index-key +
  • + + {item.key} + + = + {String(item.value)} +
  • + )} +
+ ); +} + +type AccordianKeyValuesProps = { + compact?: boolean, + data: { key: string, value: any }[], + highContrast?: boolean, + isOpen: boolean, + label: string, + onToggle: () => void, +}; + +function AccordianKeyValues(props: AccordianKeyValuesProps) { + const { compact, data, highContrast, isOpen, label, onToggle } = props; + return ( +
+
+ + + {label} + : + + {!isOpen && } +
+ {isOpen && } +
+ ); +} + +AccordianKeyValues.defaultProps = { + compact: false, + highContrast: false, +}; + +export default toggleEnhancer(AccordianKeyValues); diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.css b/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.css new file mode 100644 index 0000000000..4ceee0f60f --- /dev/null +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.css @@ -0,0 +1,27 @@ +/* +Copyright (c) 2017 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +.AccordianLogs--footer { + color: #888; + display: block; + margin: 0.3em 0 -0.75em; +} diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.js b/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.js new file mode 100644 index 0000000000..7df695c7fd --- /dev/null +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.js @@ -0,0 +1,76 @@ +// @flow +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import React from 'react'; +import _sortBy from 'lodash/sortBy'; + +import AccordianKeyValues from './AccordianKeyValues'; +import toggleEnhancer from './toggle-enhancer'; +import { formatDuration } from '../utils'; + +import './AccordianLogs.css'; + +type LogMessage = { + timestamp: number, + fields: { key: string, value: any }[], +}; + +type AccordianLogsProps = { + isOpen: boolean, + logs: LogMessage[], + onToggle: () => void, + timestamp: number, +}; + +function AccordianLogs(props: AccordianLogsProps) { + const { logs, timestamp, isOpen, onToggle } = props; + return ( +
+ + + Logs ({logs.length}) + + {isOpen && +
+ {_sortBy(logs, 'timestamp').map((log, i) => + + )} + + **Log timestamps are relative to the start time of the full trace. + +
} +
+ ); +} + +export default toggleEnhancer(AccordianLogs); diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.css b/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.css new file mode 100644 index 0000000000..3099ce4bbd --- /dev/null +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.css @@ -0,0 +1,42 @@ +/* +Copyright (c) 2017 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +.KeyValueTable { + border: 1px solid #ddd; + margin-bottom: 0.7em; + max-height: 300px; + overflow: auto; +} + +/* border is on .KeyValueTable instead (the wrapper) */ +.KeyValueTable > .ui.table { + border: none; +} + +.KeyValueTable--body { + vertical-align: baseline; +} + +.KeyValueTable--keyColumn { + width: 150px; + color: #888; +} diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.js b/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.js new file mode 100644 index 0000000000..2d3b14413b --- /dev/null +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail/KeyValuesTable.js @@ -0,0 +1,61 @@ +// @flow +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import React from 'react'; +import jsonMarkup from 'json-markup'; + +import './KeyValuesTable.css'; + +function parseOrPass(value) { + try { + return JSON.parse(value); + } catch (_) { + return value; + } +} + +type KeyValuesTableProps = { + data: { key: string, value: any }[], +}; + +export default function KeyValuesTable(props: KeyValuesTableProps) { + const { data } = props; + return ( +
+ + + {data.map((row, i) => + // `i` is necessary in the key because row.key can repeat + // eslint-disable-next-line react/no-array-index-key + + + + + )} + +
+ {row.key} + +
+
+
+ ); +} diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css b/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css new file mode 100644 index 0000000000..878c461fb7 --- /dev/null +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.css @@ -0,0 +1,41 @@ +/* +Copyright (c) 2017 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +.SpanDetail--debugInfo { + display: block; + letter-spacing: 0.25px; + margin: 0.5em 0 -0.75em; + text-align: right; +} + +.SpanDetail--debugLabel::before { + color: #bbb; + content: attr(data-label); +} + +.SpanDetail--debugValue { + color: #888; +} + +.SpanDetail--debugValue:hover { + color: #333; +} diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.js b/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.js new file mode 100644 index 0000000000..ff2264d35b --- /dev/null +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail/index.js @@ -0,0 +1,81 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import React from 'react'; + +import AccordianKeyValues from './AccordianKeyValues'; +import AccordianLogs from './AccordianLogs'; +import { formatDuration } from '../utils'; +import type { XformedSpan, XformedTrace } from '../transforms'; + +import './index.css'; + +type SpanDetailProps = { + span: XformedSpan, + trace: XformedTrace, +}; + +export default function SpanDetail(props: SpanDetailProps) { + const { span, trace } = props; + return ( +
+
+

+ {span.operationName} +

+
+
+ Service: + + {span.process.serviceName} + +
+
+ Duration: + + {formatDuration(span.duration)} + +
+
+ Start Time: + + {formatDuration(span.relativeStartTime)} + +
+
+
+
+
+
+ + {span.process && + span.process.tags && + } +
+ {span.logs && span.logs.length > 0 && } + + + {' '} + {span.spanID} + +
+
+ ); +} diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail/toggle-enhancer.js b/src/components/TracePage/TraceTimelineViewer/SpanDetail/toggle-enhancer.js new file mode 100644 index 0000000000..1fe3980f01 --- /dev/null +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail/toggle-enhancer.js @@ -0,0 +1,30 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import { compose, withHandlers, withState } from 'recompose'; + +export default compose( + withState('isOpen', 'setOpen', false), + withHandlers({ + onToggle: props => () => { + props.setOpen(!props.isOpen); + }, + }) +); diff --git a/src/components/TracePage/TraceTimelineViewer/transforms.js b/src/components/TracePage/TraceTimelineViewer/transforms.js index 94bfd389c1..ccb61d2cab 100644 --- a/src/components/TracePage/TraceTimelineViewer/transforms.js +++ b/src/components/TracePage/TraceTimelineViewer/transforms.js @@ -1,3 +1,4 @@ +// @flow // Copyright (c) 2017 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -25,23 +26,50 @@ import { getTraceSpansAsMap, getTraceTimestamp, } from '../../../selectors/trace'; +import type { Process, Span } from '../../../types'; -const cache = new Map(); +type SpanWithProcess = Span & { process: Process }; -export function transformTrace(trace) { - if (cache.has(trace.traceID)) { - return cache.get(trace.traceID); +export type XformedSpan = SpanWithProcess & { + depth: number, + hasChildren: boolean, + relativeStartTime: number, +}; + +type TracePartial = { + processes: { [string]: Process }, + traceID: string, +}; + +export type XformedTrace = TracePartial & { + duration: number, + endTime: number, + spans: XformedSpan[], + startTime: number, +}; + +const cache: Map = new Map(); + +// eslint-disable-next-line import/prefer-default-export +export function transformTrace(trace: TracePartial & { spans: SpanWithProcess[] }): XformedTrace { + const cached = cache.get(trace.traceID); + if (cached) { + return cached; } const traceStartTime = getTraceTimestamp(trace); const traceEndTime = getTraceEndTimestamp(trace); - const spanMap = getTraceSpansAsMap(trace); + const spanMap: Map = getTraceSpansAsMap(trace); const tree = getTraceSpanIdsAsTree(trace); - const spans = []; + const spans: XformedSpan[] = []; + tree.walk((spanID, node, depth) => { if (spanID === '__root__') { return; } - const span = spanMap.get(spanID); + const span: ?SpanWithProcess = spanMap.get(spanID); + if (!span) { + return; + } spans.push({ ...span, relativeStartTime: span.startTime - traceStartTime, @@ -50,8 +78,12 @@ export function transformTrace(trace) { }); }); const transform = { - ...trace, spans, + // can't use spread operator for intersection types + // repl: https://goo.gl/4Z23MJ + // issue: https://github.com/facebook/flow/issues/1511 + processes: trace.processes, + traceID: trace.traceID, duration: getTraceDuration(trace), startTime: traceStartTime, endTime: traceEndTime,