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 (
-
- );
-}
-
-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 (
-
- );
-}
-
-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,