From 2052309c7b9edf4f2e4189d388380f3dc3a35a9a Mon Sep 17 00:00:00 2001 From: Staffan Friberg Date: Mon, 7 Jan 2019 22:23:10 -0600 Subject: [PATCH 01/11] Log Markers on Spans Signed-off-by: Staffan Friberg --- .../TracePage/TraceTimelineViewer/SpanBar.css | 32 +++++++++++++++ .../TracePage/TraceTimelineViewer/SpanBar.js | 40 ++++++++++++++++++- .../TraceTimelineViewer/SpanBarRow.js | 23 ++++++++--- .../SpanDetail/AccordianLogs.css | 1 + .../VirtualizedTraceView.js | 40 +++++++++---------- .../TracePage/TraceTimelineViewer/utils.js | 24 ++++++----- .../TraceTimelineViewer/utils.test.js | 16 ++++---- 7 files changed, 132 insertions(+), 44 deletions(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.css b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.css index f52b8fcd73..0eb7eefa34 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.css +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.css @@ -66,3 +66,35 @@ limitations under the License. .span-row:hover .SpanBar--label { color: #000; } + +.SpanBar--logMarker { + background-color: rgba(0, 0, 0, 0.5); + cursor: pointer; + height: 60%; + min-width: 1px; + position: absolute; + top: 20%; +} + +.SpanBar--logMarker:hover { + background-color: #000; +} + +.SpanBar--logMarker::before, +.SpanBar--logMarker::after { + content: ''; + position: absolute; + top: 0; + bottom: 0; + right: 0; + border: 1px solid transparent; +} + +.SpanBar--logMarker::after { + left: 0; +} + +/* Tweak the popover aesthetics - unfortunate but necessary */ +.SpanBar--logHint .ant-popover-inner-content { + padding: 0.25rem; +} diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js index efeb7ebd3a..3f4372a1c4 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js @@ -15,7 +15,10 @@ // limitations under the License. import React from 'react'; +import { Popover } from 'antd'; import { onlyUpdateForKeys, compose, withState, withProps } from 'recompose'; +import type { Log } from '../../../types/trace'; +import AccordianLogs from './SpanDetail/AccordianLogs'; import './SpanBar.css'; @@ -33,6 +36,7 @@ type SpanBarProps = { }, setLongLabel: () => void, setShortLabel: () => void, + logs: { view: { start: number, end: number }, logs: Log[], start: number }[], }; function toPercent(value: number) { @@ -40,7 +44,18 @@ function toPercent(value: number) { } function SpanBar(props: SpanBarProps) { - const { viewEnd, viewStart, color, label, hintSide, onClick, setLongLabel, setShortLabel, rpc } = props; + const { + viewEnd, + viewStart, + color, + label, + hintSide, + onClick, + setLongLabel, + setShortLabel, + rpc, + logs, + } = props; return (
{label}
+
+ {logs.map(l => ( + {}} + onItemToggle={() => {}} + timestamp={l.start} + /> + } + > +
+ + ))} +
{rpc && (
{ start: number, end: number }, + trace: Trace, span: Span, - viewEnd: number, - viewStart: number, }; /** @@ -86,12 +88,15 @@ export default class SpanBarRow extends React.PureComponent { numTicks, rpc, showErrorIcon, + getViewedBounds, + trace, span, - viewEnd, - viewStart, } = this.props; const { duration, hasChildren: isParent, operationName, process: { serviceName } } = span; const label = formatDuration(duration); + const viewBounds = getViewedBounds(span.startTime, span.startTime + span.duration); + const viewStart = viewBounds.start; + const viewEnd = viewBounds.end; const labelDetail = `${serviceName}::${operationName}`; let longLabel; @@ -103,6 +108,13 @@ export default class SpanBarRow extends React.PureComponent { longLabel = `${label} | ${labelDetail}`; hintSide = 'right'; } + + const logs = _values( + _groupBy(span.logs.map(l => ({ view: getViewedBounds(l.timestamp, l.timestamp), log: l })), v => + Math.floor(v.view.start * 100) + ) + ).map(v => ({ view: v[0].view, logs: v.map(l => l.log), start: trace.startTime })); + return ( { shortLabel={label} longLabel={longLabel} hintSide={hintSide} + logs={logs} /> diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.css b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.css index fe63cea6d6..4af98f1b45 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.css +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.css @@ -16,6 +16,7 @@ limitations under the License. .AccordianLogs { border: 1px solid #d8d8d8; + position: relative; } .AccordianLogs--header { diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/VirtualizedTraceView.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/VirtualizedTraceView.js index bd840a8f3c..e5196f92e7 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/VirtualizedTraceView.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/VirtualizedTraceView.js @@ -24,7 +24,7 @@ import ListView from './ListView'; import SpanBarRow from './SpanBarRow'; import DetailState from './SpanDetail/DetailState'; import SpanDetailRow from './SpanDetailRow'; -import { findServerChildSpan, getViewedBounds, isErrorSpan, spanContainsErredSpan } from './utils'; +import { createViewedBoundsFunc, findServerChildSpan, isErrorSpan, spanContainsErredSpan } from './utils'; import getLinks from '../../../model/link-patterns'; import type { Accessors } from '../ScrollManager'; import type { Log, Span, Trace, KeyValuePair } from '../../../types/trace'; @@ -125,6 +125,7 @@ export class VirtualizedTraceViewImpl extends React.PureComponent { start: number, end: number }; constructor(props: VirtualizedTraceViewProps) { super(props); @@ -132,6 +133,13 @@ export class VirtualizedTraceViewImpl extends React.PureComponent
); diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.js index 3674db6176..e5c366dd80 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.js @@ -13,29 +13,35 @@ // limitations under the License. /** - * Given a range (`min`, `max`), finds the position of a sub-range (`start`, - * `end`) factoring in a zoom (`viewStart`, `viewEnd`). The result is returned - * as a `{ start, end }` object with values ranging in [0, 1]. + * Given a range (`min`, `max`) and factoring in a zoom (`viewStart`, `viewEnd`) + * a function is created that will find the position of a sub-range (`start`, `end`). + * The calling the generated method will return the result as a `{ start, end }` + * object with values ranging in [0, 1]. * * @param {number} min The start of the outer range. * @param {number} max The end of the outer range. - * @param {number} start The start of the sub-range. - * @param {number} end The end of the sub-range. * @param {number} viewStart The start of the zoom, on a range of [0, 1], * relative to the `min`, `max`. * @param {number} viewEnd The end of the zoom, on a range of [0, 1], * relative to the `min`, `max`. - * @return {Object} The resultant range. + * @returns {(number, number) => Object} Created view bounds function */ -export function getViewedBounds({ min, max, start, end, viewStart, viewEnd }) { +export function createViewedBoundsFunc({ min, max, viewStart, viewEnd }) { const duration = max - min; const viewMin = min + viewStart * duration; const viewMax = max - (1 - viewEnd) * duration; const viewWindow = viewMax - viewMin; - return { + + /** + * View bounds function + * @param {number} start The start of the sub-range. + * @param {number} end The end of the sub-range. + * @return {Object} The resultant range. + */ + return (start, end) => ({ start: (start - viewMin) / viewWindow, end: (end - viewMin) / viewWindow, - }; + }); } /** diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.test.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.test.js index c8961f5e2b..0fbcb793d3 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.test.js @@ -14,7 +14,7 @@ import { findServerChildSpan, - getViewedBounds, + createViewedBoundsFunc, isClientSpan, isErrorSpan, isServerSpan, @@ -27,29 +27,29 @@ import traceGenerator from '../../../demo/trace-generators'; describe('TraceTimelineViewer/utils', () => { describe('getViewedBounds()', () => { it('works for the full range', () => { - const args = { min: 1, max: 2, start: 1, end: 2, viewStart: 0, viewEnd: 1 }; - const { start, end } = getViewedBounds(args); + const args = { min: 1, max: 2, viewStart: 0, viewEnd: 1 }; + const { start, end } = createViewedBoundsFunc(args)(1, 2); expect(start).toBe(0); expect(end).toBe(1); }); it('works for a sub-range with a full view', () => { - const args = { min: 1, max: 2, start: 1.25, end: 1.75, viewStart: 0, viewEnd: 1 }; - const { start, end } = getViewedBounds(args); + const args = { min: 1, max: 2, viewStart: 0, viewEnd: 1 }; + const { start, end } = createViewedBoundsFunc(args)(1.25, 1.75); expect(start).toBe(0.25); expect(end).toBe(0.75); }); it('works for a sub-range that fills the view', () => { - const args = { min: 1, max: 2, start: 1.25, end: 1.75, viewStart: 0.25, viewEnd: 0.75 }; - const { start, end } = getViewedBounds(args); + const args = { min: 1, max: 2, viewStart: 0.25, viewEnd: 0.75 }; + const { start, end } = createViewedBoundsFunc(args)(1.25, 1.75); expect(start).toBe(0); expect(end).toBe(1); }); it('works for a sub-range that within a sub-view', () => { const args = { min: 100, max: 200, start: 130, end: 170, viewStart: 0.1, viewEnd: 0.9 }; - const { start, end } = getViewedBounds(args); + const { start, end } = createViewedBoundsFunc(args)(130, 170); expect(start).toBe(0.25); expect(end).toBe(0.75); }); From 0478c8f9d6c96f821523986b740a7b34a9fb9314 Mon Sep 17 00:00:00 2001 From: Staffan Friberg Date: Mon, 7 Jan 2019 23:14:24 -0600 Subject: [PATCH 02/11] Make tests pass with empty logs for now Signed-off-by: Staffan Friberg --- .../TracePage/TraceTimelineViewer/SpanBar.test.js | 1 + .../TracePage/TraceTimelineViewer/SpanBarRow.test.js | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js index 6e3e6b82ba..e555b6f6c9 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js @@ -33,6 +33,7 @@ describe('', () => { viewEnd: 0.75, color: '#000', }, + logs: [], }; it('renders without exploding', () => { diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js index 936a249fb2..26adaf53f9 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js @@ -41,6 +41,10 @@ describe('', () => { serviceName: 'rpc-service-name', }, showErrorIcon: false, + getViewedBounds: () => [0, 1], + trace: { + startTime: 0, + }, span: { duration: 'test-duration', hasChildren: true, @@ -48,9 +52,8 @@ describe('', () => { serviceName: 'service-name', }, spanID, + logs: [], }, - viewEnd: 1, - viewStart: 0, }; let wrapper; From 0a99c0a4b16f7ab869035bd7e16b62a50d064ea0 Mon Sep 17 00:00:00 2001 From: Staffan Friberg Date: Tue, 8 Jan 2019 09:29:02 -0600 Subject: [PATCH 03/11] Simple test that log markers are created Signed-off-by: Staffan Friberg --- .../TraceTimelineViewer/SpanBarRow.test.js | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js index 26adaf53f9..c072dccace 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js @@ -14,6 +14,7 @@ import React from 'react'; import { mount } from 'enzyme'; +import { Popover } from 'antd'; import SpanBarRow from './SpanBarRow'; import SpanTreeOffset from './SpanTreeOffset'; @@ -41,7 +42,16 @@ describe('', () => { serviceName: 'rpc-service-name', }, showErrorIcon: false, - getViewedBounds: () => [0, 1], + getViewedBounds: s => { + // Log entries + if (s === 10) { + return { start: 0.1, end: 0.1 }; + } else if (s === 20) { + return { start: 0.2, end: 0.2 }; + } + // Span value + return { start: 0, end: 1 }; + }, trace: { startTime: 0, }, @@ -52,7 +62,23 @@ describe('', () => { serviceName: 'service-name', }, spanID, - logs: [], + logs: [ + { + timestamp: 10, + fields: [{ key: 'message', value: 'oh the log message' }, { key: 'something', value: 'else' }], + }, + { + timestamp: 10, + fields: [ + { key: 'message', value: 'oh the second log message' }, + { key: 'something', value: 'different' }, + ], + }, + { + timestamp: 20, + fields: [{ key: 'message', value: 'oh the next log message' }, { key: 'more', value: 'stuff' }], + }, + ], }, }; @@ -81,4 +107,9 @@ describe('', () => { wrapper.find(SpanTreeOffset).prop('onClick')(); expect(onChildrenToggled.mock.calls).toEqual([[spanID]]); }); + + it('log markers count', () => { + // 3 log entries, two grouped together with the same timestamp + expect(wrapper.find(Popover).length).toEqual(2); + }); }); From a8749ee03238f33227da73584a7610e3d4325747 Mon Sep 17 00:00:00 2001 From: Staffan Friberg Date: Tue, 8 Jan 2019 21:52:57 -0600 Subject: [PATCH 04/11] Push trace separately all they way down to SpanBar Signed-off-by: Staffan Friberg --- .../components/TracePage/TraceTimelineViewer/SpanBar.js | 8 +++++--- .../TracePage/TraceTimelineViewer/SpanBarRow.js | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js index 3f4372a1c4..513495b954 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js @@ -17,7 +17,7 @@ import React from 'react'; import { Popover } from 'antd'; import { onlyUpdateForKeys, compose, withState, withProps } from 'recompose'; -import type { Log } from '../../../types/trace'; +import type { Log, Trace } from '../../../types/trace'; import AccordianLogs from './SpanDetail/AccordianLogs'; import './SpanBar.css'; @@ -36,7 +36,8 @@ type SpanBarProps = { }, setLongLabel: () => void, setShortLabel: () => void, - logs: { view: { start: number, end: number }, logs: Log[], start: number }[], + trace: Trace, + logs: { view: { start: number, end: number }, logs: Log[] }[], }; function toPercent(value: number) { @@ -54,6 +55,7 @@ function SpanBar(props: SpanBarProps) { setLongLabel, setShortLabel, rpc, + trace, logs, } = props; @@ -91,7 +93,7 @@ function SpanBar(props: SpanBarProps) { openedItems={new Set([])} onToggle={() => {}} onItemToggle={() => {}} - timestamp={l.start} + timestamp={trace.startTime} /> } > diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js index 54ba6a05fc..3837c87f32 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js @@ -113,7 +113,7 @@ export default class SpanBarRow extends React.PureComponent { _groupBy(span.logs.map(l => ({ view: getViewedBounds(l.timestamp, l.timestamp), log: l })), v => Math.floor(v.view.start * 100) ) - ).map(v => ({ view: v[0].view, logs: v.map(l => l.log), start: trace.startTime })); + ).map(v => ({ view: v[0].view, logs: v.map(l => l.log) })); return ( { shortLabel={label} longLabel={longLabel} hintSide={hintSide} + trace={trace} logs={logs} /> From 9ee80a5317e2fba4b151f176dc4af2d09838325c Mon Sep 17 00:00:00 2001 From: Staffan Friberg Date: Wed, 9 Jan 2019 09:50:44 -0600 Subject: [PATCH 05/11] Send Span all the way to SpanBar instead of Logs Signed-off-by: Staffan Friberg --- .../TracePage/TraceTimelineViewer/SpanBar.js | 23 +++++++---- .../TraceTimelineViewer/SpanBar.test.js | 39 ++++++++++++++++++- .../TraceTimelineViewer/SpanBarRow.js | 11 +----- .../TraceTimelineViewer/SpanBarRow.test.js | 38 +----------------- 4 files changed, 58 insertions(+), 53 deletions(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js index 513495b954..9fe61c0ae8 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js @@ -16,8 +16,11 @@ import React from 'react'; import { Popover } from 'antd'; +import _groupBy from 'lodash/groupBy'; +import _values from 'lodash/values'; + import { onlyUpdateForKeys, compose, withState, withProps } from 'recompose'; -import type { Log, Trace } from '../../../types/trace'; +import type { Span, Trace } from '../../../types/trace'; import AccordianLogs from './SpanDetail/AccordianLogs'; import './SpanBar.css'; @@ -29,6 +32,7 @@ type SpanBarProps = { onClick: (SyntheticMouseEvent) => void, viewEnd: number, viewStart: number, + getViewedBounds: (number, number) => { start: number, end: number }, rpc: { viewStart: number, viewEnd: number, @@ -37,7 +41,7 @@ type SpanBarProps = { setLongLabel: () => void, setShortLabel: () => void, trace: Trace, - logs: { view: { start: number, end: number }, logs: Log[] }[], + span: Span, }; function toPercent(value: number) { @@ -48,6 +52,7 @@ function SpanBar(props: SpanBarProps) { const { viewEnd, viewStart, + getViewedBounds, color, label, hintSide, @@ -56,7 +61,7 @@ function SpanBar(props: SpanBarProps) { setShortLabel, rpc, trace, - logs, + span, } = props; return ( @@ -79,15 +84,19 @@ function SpanBar(props: SpanBarProps) {
{label}
- {logs.map(l => ( + {_values( + _groupBy(span.logs.map(l => ({ view: getViewedBounds(l.timestamp, l.timestamp), log: l })), v => + Math.floor(v.view.start * 100) + ) + ).map(v => ( l.log)} linksGetter={null} isOpen openedItems={new Set([])} @@ -97,7 +106,7 @@ function SpanBar(props: SpanBarProps) { /> } > -
+
))}
diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js index e555b6f6c9..ef3cd08d37 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js @@ -14,6 +14,7 @@ import React from 'react'; import { mount } from 'enzyme'; +import { Popover } from 'antd'; import SpanBar from './SpanBar'; @@ -28,12 +29,42 @@ describe('', () => { hintSide: 'right', viewEnd: 1, viewStart: 0, + getViewedBounds: s => { + // Log entries + if (s === 10) { + return { start: 0.1, end: 0.1 }; + } else if (s === 20) { + return { start: 0.2, end: 0.2 }; + } + return { error: 'error' }; + }, rpc: { viewStart: 0.25, viewEnd: 0.75, color: '#000', }, - logs: [], + trace: { + startTime: 0, + }, + span: { + logs: [ + { + timestamp: 10, + fields: [{ key: 'message', value: 'oh the log message' }, { key: 'something', value: 'else' }], + }, + { + timestamp: 10, + fields: [ + { key: 'message', value: 'oh the second log message' }, + { key: 'something', value: 'different' }, + ], + }, + { + timestamp: 20, + fields: [{ key: 'message', value: 'oh the next log message' }, { key: 'more', value: 'stuff' }], + }, + ], + }, }; it('renders without exploding', () => { @@ -47,4 +78,10 @@ describe('', () => { onMouseOut(); expect(labelElm.text()).toBe(shortLabel); }); + + it('log markers count', () => { + // 3 log entries, two grouped together with the same timestamp + const wrapper = mount(); + expect(wrapper.find(Popover).length).toEqual(2); + }); }); diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js index 3837c87f32..04d07e7f85 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js @@ -18,8 +18,6 @@ import * as React from 'react'; import IoAlert from 'react-icons/lib/io/alert'; import IoArrowRightA from 'react-icons/lib/io/arrow-right-a'; -import _groupBy from 'lodash/groupBy'; -import _values from 'lodash/values'; import TimelineRow from './TimelineRow'; import { formatDuration } from './utils'; import SpanTreeOffset from './SpanTreeOffset'; @@ -109,12 +107,6 @@ export default class SpanBarRow extends React.PureComponent { hintSide = 'right'; } - const logs = _values( - _groupBy(span.logs.map(l => ({ view: getViewedBounds(l.timestamp, l.timestamp), log: l })), v => - Math.floor(v.view.start * 100) - ) - ).map(v => ({ view: v[0].view, logs: v.map(l => l.log) })); - return ( { rpc={rpc} viewStart={viewStart} viewEnd={viewEnd} + getViewedBounds={getViewedBounds} color={color} shortLabel={label} longLabel={longLabel} hintSide={hintSide} trace={trace} - logs={logs} + span={span} /> diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js index c072dccace..39cd5af596 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.test.js @@ -14,7 +14,6 @@ import React from 'react'; import { mount } from 'enzyme'; -import { Popover } from 'antd'; import SpanBarRow from './SpanBarRow'; import SpanTreeOffset from './SpanTreeOffset'; @@ -42,19 +41,7 @@ describe('', () => { serviceName: 'rpc-service-name', }, showErrorIcon: false, - getViewedBounds: s => { - // Log entries - if (s === 10) { - return { start: 0.1, end: 0.1 }; - } else if (s === 20) { - return { start: 0.2, end: 0.2 }; - } - // Span value - return { start: 0, end: 1 }; - }, - trace: { - startTime: 0, - }, + getViewedBounds: () => ({ start: 0, end: 1 }), span: { duration: 'test-duration', hasChildren: true, @@ -62,23 +49,7 @@ describe('', () => { serviceName: 'service-name', }, spanID, - logs: [ - { - timestamp: 10, - fields: [{ key: 'message', value: 'oh the log message' }, { key: 'something', value: 'else' }], - }, - { - timestamp: 10, - fields: [ - { key: 'message', value: 'oh the second log message' }, - { key: 'something', value: 'different' }, - ], - }, - { - timestamp: 20, - fields: [{ key: 'message', value: 'oh the next log message' }, { key: 'more', value: 'stuff' }], - }, - ], + logs: [], }, }; @@ -107,9 +78,4 @@ describe('', () => { wrapper.find(SpanTreeOffset).prop('onClick')(); expect(onChildrenToggled.mock.calls).toEqual([[spanID]]); }); - - it('log markers count', () => { - // 3 log entries, two grouped together with the same timestamp - expect(wrapper.find(Popover).length).toEqual(2); - }); }); From dd98cc3f43b33d1ef9d527bfd18a50390c5ec311 Mon Sep 17 00:00:00 2001 From: Staffan Friberg Date: Fri, 11 Jan 2019 17:34:25 -0600 Subject: [PATCH 06/11] PR comments Signed-off-by: Staffan Friberg --- .../TracePage/TraceTimelineViewer/SpanBar.js | 14 ++++++++------ .../TracePage/TraceTimelineViewer/SpanBar.test.js | 4 +--- .../TracePage/TraceTimelineViewer/SpanBarRow.js | 11 ++++++----- .../TraceTimelineViewer/VirtualizedTraceView.js | 8 +++++--- .../TracePage/TraceTimelineViewer/utils.js | 1 + .../TracePage/TraceTimelineViewer/utils.test.js | 2 +- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js index 9fe61c0ae8..214e2fa9dd 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js @@ -18,11 +18,13 @@ import React from 'react'; import { Popover } from 'antd'; import _groupBy from 'lodash/groupBy'; import _values from 'lodash/values'; - import { onlyUpdateForKeys, compose, withState, withProps } from 'recompose'; -import type { Span, Trace } from '../../../types/trace'; + import AccordianLogs from './SpanDetail/AccordianLogs'; +import type { ViewedBoundsFunctionType } from './utils'; +import type { Span } from '../../../types/trace'; + import './SpanBar.css'; type SpanBarProps = { @@ -32,7 +34,7 @@ type SpanBarProps = { onClick: (SyntheticMouseEvent) => void, viewEnd: number, viewStart: number, - getViewedBounds: (number, number) => { start: number, end: number }, + getViewedBounds: ViewedBoundsFunctionType, rpc: { viewStart: number, viewEnd: number, @@ -40,7 +42,7 @@ type SpanBarProps = { }, setLongLabel: () => void, setShortLabel: () => void, - trace: Trace, + traceStartTime: number, span: Span, }; @@ -60,7 +62,7 @@ function SpanBar(props: SpanBarProps) { setLongLabel, setShortLabel, rpc, - trace, + traceStartTime, span, } = props; @@ -102,7 +104,7 @@ function SpanBar(props: SpanBarProps) { openedItems={new Set([])} onToggle={() => {}} onItemToggle={() => {}} - timestamp={trace.startTime} + timestamp={traceStartTime} /> } > diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js index ef3cd08d37..2dbcdcd4db 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.test.js @@ -43,9 +43,7 @@ describe('', () => { viewEnd: 0.75, color: '#000', }, - trace: { - startTime: 0, - }, + tracestartTime: 0, span: { logs: [ { diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js index 04d07e7f85..cf86ee85fd 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.js @@ -24,7 +24,8 @@ import SpanTreeOffset from './SpanTreeOffset'; import SpanBar from './SpanBar'; import Ticks from './Ticks'; -import type { Span, Trace } from '../../../types/trace'; +import type { ViewedBoundsFunctionType } from './utils'; +import type { Span } from '../../../types/trace'; import './SpanBarRow.css'; @@ -46,8 +47,8 @@ type SpanBarRowProps = { serviceName: string, }, showErrorIcon: boolean, - getViewedBounds: (number, number) => { start: number, end: number }, - trace: Trace, + getViewedBounds: ViewedBoundsFunctionType, + traceStartTime: number, span: Span, }; @@ -87,7 +88,7 @@ export default class SpanBarRow extends React.PureComponent { rpc, showErrorIcon, getViewedBounds, - trace, + traceStartTime, span, } = this.props; const { duration, hasChildren: isParent, operationName, process: { serviceName } } = span; @@ -164,7 +165,7 @@ export default class SpanBarRow extends React.PureComponent { shortLabel={label} longLabel={longLabel} hintSide={hintSide} - trace={trace} + traceStartTime={traceStartTime} span={span} /> diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/VirtualizedTraceView.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/VirtualizedTraceView.js index e5196f92e7..b7b2bd74bf 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/VirtualizedTraceView.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/VirtualizedTraceView.js @@ -26,9 +26,11 @@ import DetailState from './SpanDetail/DetailState'; import SpanDetailRow from './SpanDetailRow'; import { createViewedBoundsFunc, findServerChildSpan, isErrorSpan, spanContainsErredSpan } from './utils'; import getLinks from '../../../model/link-patterns'; +import colorGenerator from '../../../utils/color-generator'; + +import type { ViewedBoundsFunctionType } from './utils'; import type { Accessors } from '../ScrollManager'; import type { Log, Span, Trace, KeyValuePair } from '../../../types/trace'; -import colorGenerator from '../../../utils/color-generator'; import './VirtualizedTraceView.css'; @@ -125,7 +127,7 @@ export class VirtualizedTraceViewImpl extends React.PureComponent { start: number, end: number }; + getViewedBounds: ViewedBoundsFunctionType; constructor(props: VirtualizedTraceViewProps) { super(props); @@ -316,7 +318,7 @@ export class VirtualizedTraceViewImpl extends React.PureComponent
diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.js index e5c366dd80..ae677b72ac 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.js @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +export type ViewedBoundsFunctionType = (number, number) => { start: number, end: number }; /** * Given a range (`min`, `max`) and factoring in a zoom (`viewStart`, `viewEnd`) * a function is created that will find the position of a sub-range (`start`, `end`). diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.test.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.test.js index 0fbcb793d3..c68d845dc0 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/utils.test.js @@ -48,7 +48,7 @@ describe('TraceTimelineViewer/utils', () => { }); it('works for a sub-range that within a sub-view', () => { - const args = { min: 100, max: 200, start: 130, end: 170, viewStart: 0.1, viewEnd: 0.9 }; + const args = { min: 100, max: 200, viewStart: 0.1, viewEnd: 0.9 }; const { start, end } = createViewedBoundsFunc(args)(130, 170); expect(start).toBe(0.25); expect(end).toBe(0.75); From bdceca61b552d4aedbda63c35cd05a7b1c08793d Mon Sep 17 00:00:00 2001 From: Joe Farro Date: Sat, 12 Jan 2019 03:05:22 -0500 Subject: [PATCH 07/11] Update changelog for PR 309 Signed-off-by: Joe Farro --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 480aa3dff9..46026c74ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ * **Trace detail:** Add indent guides to trace timeline view ([#172](https://github.com/jaegertracing/jaeger-ui/issues/172)) ([@everett980](https://github.com/everett980) in [#297](https://github.com/jaegertracing/jaeger-ui/pull/297)) +* **Trace detail:** Log Markers on Spans ([Fix #119](https://github.com/jaegertracing/jaeger-ui/issues/119)) ([@sfriberg](https://github.com/sfriberg) in [#309](https://github.com/jaegertracing/jaeger-ui/pull/309)) + * **Search:** Add popover and prevent submit if duration params are invalid ([#244](https://github.com/jaegertracing/jaeger-ui/issues/244)) ([@everett980](https://github.com/everett980) in [#291](https://github.com/jaegertracing/jaeger-ui/pull/291)) * **Menu configuration:** Ability to open additional menu links in same tab (Resolves [#275](https://github.com/jaegertracing/jaeger-ui/issues/275)) ([@zablvit](https://github.com/zablvit) in [#278](https://github.com/jaegertracing/jaeger-ui/pull/278)) From c5432e1e23c60a7ab53e9479ccbdccb3fad16b31 Mon Sep 17 00:00:00 2001 From: Joe Farro Date: Sun, 13 Jan 2019 16:25:39 -0500 Subject: [PATCH 08/11] CSS fix for logMarker hover at t0 Signed-off-by: Joe Farro --- .../components/TracePage/TraceTimelineViewer/SpanBarRow.css | 2 +- .../TimelineHeaderRow/TimelineColumnResizer.css | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css index e67045c64e..0fef447ef0 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBarRow.css @@ -67,7 +67,7 @@ limitations under the License. .span-row.is-expanded .span-name-wrapper { background: #f0f0f0; - outline: 1px solid #ddd; + box-shadow: 0 1px 0 #ddd; } .span-row.is-expanded .span-name-wrapper.is-matching-filter { diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/TimelineHeaderRow/TimelineColumnResizer.css b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/TimelineHeaderRow/TimelineColumnResizer.css index e3ee42d720..8af3140f11 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/TimelineHeaderRow/TimelineColumnResizer.css +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/TimelineHeaderRow/TimelineColumnResizer.css @@ -31,9 +31,10 @@ limitations under the License. border-left: 2px solid transparent; cursor: col-resize; height: 5000px; + margin-left: -1px; position: absolute; top: 0; - width: 5px; + width: 1px; } .TimelineColumnResizer--dragger:hover { @@ -61,7 +62,7 @@ limitations under the License. top: 0; bottom: 0; left: -8px; - right: -5px; + right: 0; content: ' '; } From f79ad5393cd9ea144eb2cc69ca06e213f1075dcd Mon Sep 17 00:00:00 2001 From: Staffan Friberg Date: Mon, 14 Jan 2019 17:15:19 -0600 Subject: [PATCH 09/11] Disable clicking Signed-off-by: Staffan Friberg --- .../components/TracePage/TraceTimelineViewer/SpanBar.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js index 214e2fa9dd..4e2a94f096 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js @@ -85,7 +85,12 @@ function SpanBar(props: SpanBarProps) { >
{label}
-
+
{ + ev.stopPropagation(); + }} + > {_values( _groupBy(span.logs.map(l => ({ view: getViewedBounds(l.timestamp, l.timestamp), log: l })), v => Math.floor(v.view.start * 100) From c3e3601fae0a93d07914041c1d7a79491744f616 Mon Sep 17 00:00:00 2001 From: Joe Farro Date: Fri, 15 Feb 2019 18:10:05 -0500 Subject: [PATCH 10/11] Tweaks to UX for span log markers Hover on log markers opens popover Click on log markers toggles span details Log marker popover is not interactive Signed-off-by: Joe Farro --- .../TracePage/TraceTimelineViewer/SpanBar.css | 4 ++ .../TracePage/TraceTimelineViewer/SpanBar.js | 31 ++++------ .../SpanDetail/AccordianKeyValues.js | 26 +++++--- .../SpanDetail/AccordianLogs.js | 60 ++++++++++++------- 4 files changed, 74 insertions(+), 47 deletions(-) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.css b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.css index 0eb7eefa34..36da603c1c 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.css +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.css @@ -94,6 +94,10 @@ limitations under the License. left: 0; } +.SpanBar--logHint { + pointer-events: none; +} + /* Tweak the popover aesthetics - unfortunate but necessary */ .SpanBar--logHint .ant-popover-inner-content { padding: 0.25rem; diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js index 4e2a94f096..c0cb8b7a43 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js @@ -17,7 +17,6 @@ import React from 'react'; import { Popover } from 'antd'; import _groupBy from 'lodash/groupBy'; -import _values from 'lodash/values'; import { onlyUpdateForKeys, compose, withState, withProps } from 'recompose'; import AccordianLogs from './SpanDetail/AccordianLogs'; @@ -47,7 +46,7 @@ type SpanBarProps = { }; function toPercent(value: number) { - return `${value * 100}%`; + return `${(value * 100).toFixed(1)}%`; } function SpanBar(props: SpanBarProps) { @@ -65,6 +64,10 @@ function SpanBar(props: SpanBarProps) { traceStartTime, span, } = props; + // group logs based on timestamps + const logGroups = _groupBy(span.logs, log => + toPercent(getViewedBounds(log.timestamp, log.timestamp).start) + ); return (
{label}
-
{ - ev.stopPropagation(); - }} - > - {_values( - _groupBy(span.logs.map(l => ({ view: getViewedBounds(l.timestamp, l.timestamp), log: l })), v => - Math.floor(v.view.start * 100) - ) - ).map(v => ( +
+ {Object.keys(logGroups).map(positionKey => ( l.log)} - linksGetter={null} + interactive={false} isOpen - openedItems={new Set([])} - onToggle={() => {}} - onItemToggle={() => {}} + logs={logGroups[positionKey]} timestamp={traceStartTime} /> } > -
+
))}
diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.js index 02bdc6ccfd..8bbea5dd3a 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianKeyValues.js @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import React from 'react'; +import * as React from 'react'; import cx from 'classnames'; import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down'; import IoIosArrowRight from 'react-icons/lib/io/ios-arrow-right'; @@ -29,10 +29,11 @@ type AccordianKeyValuesProps = { className?: ?string, data: KeyValuePair[], highContrast?: boolean, + interactive?: boolean, isOpen: boolean, label: string, linksGetter: ?(KeyValuePair[], number) => Link[], - onToggle: () => void, + onToggle: null | (() => void), }; // export for tests @@ -61,9 +62,20 @@ KeyValuesSummary.defaultProps = { }; export default function AccordianKeyValues(props: AccordianKeyValuesProps) { - const { className, data, highContrast, isOpen, label, linksGetter, onToggle } = props; + const { className, data, highContrast, interactive, isOpen, label, linksGetter, onToggle } = props; const isEmpty = !Array.isArray(data) || !data.length; const iconCls = cx('u-align-icon', { 'AccordianKeyValues--emptyIcon': isEmpty }); + let arrow: React.Node | null = null; + let headerProps: Object | null = null; + if (interactive) { + arrow = isOpen ? : ; + headerProps = { + 'aria-checked': isOpen, + onClick: isEmpty ? null : onToggle, + role: 'switch', + }; + } + return (
- {isOpen ? : } + {arrow} {label} {isOpen || ':'} @@ -90,4 +100,6 @@ export default function AccordianKeyValues(props: AccordianKeyValuesProps) { AccordianKeyValues.defaultProps = { className: null, highContrast: false, + interactive: true, + onToggle: null, }; diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.js index 5a1837f482..83d113ac84 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanDetail/AccordianLogs.js @@ -14,7 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import React from 'react'; +import * as React from 'react'; +import cx from 'classnames'; import _sortBy from 'lodash/sortBy'; import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down'; import IoIosArrowRight from 'react-icons/lib/io/ios-arrow-right'; @@ -26,29 +27,40 @@ import type { Log, KeyValuePair, Link } from '../../../../types/trace'; import './AccordianLogs.css'; type AccordianLogsProps = { + interactive?: boolean, isOpen: boolean, - linksGetter: ?(KeyValuePair[], number) => Link[], + linksGetter?: ?(KeyValuePair[], number) => Link[], logs: Log[], - onItemToggle: Log => void, - onToggle: () => void, - openedItems: Set, + onItemToggle?: Log => void, + onToggle?: () => void, + openedItems?: Set, timestamp: number, }; export default function AccordianLogs(props: AccordianLogsProps) { - const { isOpen, linksGetter, logs, openedItems, onItemToggle, onToggle, timestamp } = props; + const { interactive, isOpen, linksGetter, logs, openedItems, onItemToggle, onToggle, timestamp } = props; + let arrow: React.Node | null = null; + let HeaderComponent = 'span'; + let headerProps: Object | null = null; + if (interactive) { + arrow = isOpen ? ( + + ) : ( + + ); + HeaderComponent = 'a'; + headerProps = { + 'aria-checked': isOpen, + onClick: onToggle, + role: 'switch', + }; + } return (
- - {isOpen ? : } - Logs ({logs.length}) - + + {arrow} Logs ({logs.length}) + {isOpen && (
{_sortBy(logs, 'timestamp').map((log, i) => ( @@ -57,13 +69,13 @@ export default function AccordianLogs(props: AccordianLogsProps) { // eslint-disable-next-line react/no-array-index-key key={`${log.timestamp}-${i}`} className={i < logs.length - 1 ? 'ub-mb1' : null} - // compact - highContrast - isOpen={openedItems.has(log)} - linksGetter={linksGetter} data={log.fields || []} + highContrast + interactive={interactive} + isOpen={openedItems ? openedItems.has(log) : false} label={`${formatDuration(log.timestamp - timestamp)}`} - onToggle={() => onItemToggle(log)} + linksGetter={linksGetter} + onToggle={interactive && onItemToggle ? () => onItemToggle(log) : null} /> ))} @@ -74,3 +86,11 @@ export default function AccordianLogs(props: AccordianLogsProps) {
); } + +AccordianLogs.defaultProps = { + interactive: true, + linksGetter: undefined, + onItemToggle: undefined, + onToggle: undefined, + openedItems: undefined, +}; From 86c0c978012d182f67652b6302a0434dc0d3fb7d Mon Sep 17 00:00:00 2001 From: Joe Farro Date: Thu, 21 Feb 2019 14:59:06 -0500 Subject: [PATCH 11/11] Fix changelog, missing "@ flow" and log-marker spacing Signed-off-by: Joe Farro --- CHANGELOG.md | 8 +++++-- .../TracePage/TraceTimelineViewer/SpanBar.js | 8 ++++--- .../TracePage/TraceTimelineViewer/utils.js | 22 ++++++++++++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f0928b189..043235a2b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Releases +## Next (Unreleased) + +### Enhancements + +* **Trace detail:** Log Markers on Spans ([Fix #119](https://github.com/jaegertracing/jaeger-ui/issues/119)) ([@sfriberg](https://github.com/sfriberg) in [#309](https://github.com/jaegertracing/jaeger-ui/pull/309)) + ## v1.0.1 (February 15, 2019) ### Fixes @@ -29,8 +35,6 @@ * **Trace detail:** Add indent guides to trace timeline view ([#172](https://github.com/jaegertracing/jaeger-ui/issues/172)) ([@everett980](https://github.com/everett980) in [#297](https://github.com/jaegertracing/jaeger-ui/pull/297)) -* **Trace detail:** Log Markers on Spans ([Fix #119](https://github.com/jaegertracing/jaeger-ui/issues/119)) ([@sfriberg](https://github.com/sfriberg) in [#309](https://github.com/jaegertracing/jaeger-ui/pull/309)) - * **Search:** Add popover and prevent submit if duration params are invalid ([#244](https://github.com/jaegertracing/jaeger-ui/issues/244)) ([@everett980](https://github.com/everett980) in [#291](https://github.com/jaegertracing/jaeger-ui/pull/291)) * **Trace comparison:** Add link to timeline view from comparison view and selection ([@everett980](https://github.com/everett980) in [#313](https://github.com/jaegertracing/jaeger-ui/pull/313)) diff --git a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js index c0cb8b7a43..64d3fbe77e 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceTimelineViewer/SpanBar.js @@ -65,9 +65,11 @@ function SpanBar(props: SpanBarProps) { span, } = props; // group logs based on timestamps - const logGroups = _groupBy(span.logs, log => - toPercent(getViewedBounds(log.timestamp, log.timestamp).start) - ); + const logGroups = _groupBy(span.logs, log => { + const posPercent = getViewedBounds(log.timestamp, log.timestamp).start; + // round to the nearest 0.2% + return toPercent(Math.round(posPercent * 500) / 500); + }); return (
{ start: number, end: number }; /** * Given a range (`min`, `max`) and factoring in a zoom (`viewStart`, `viewEnd`) @@ -27,7 +31,13 @@ export type ViewedBoundsFunctionType = (number, number) => { start: number, end: * relative to the `min`, `max`. * @returns {(number, number) => Object} Created view bounds function */ -export function createViewedBoundsFunc({ min, max, viewStart, viewEnd }) { +export function createViewedBoundsFunc(viewRange: { + min: number, + max: number, + viewStart: number, + viewEnd: number, +}) { + const { min, max, viewStart, viewEnd } = viewRange; const duration = max - min; const viewMin = min + viewStart * duration; const viewMax = max - (1 - viewEnd) * duration; @@ -39,7 +49,7 @@ export function createViewedBoundsFunc({ min, max, viewStart, viewEnd }) { * @param {number} end The end of the sub-range. * @return {Object} The resultant range. */ - return (start, end) => ({ + return (start: number, end: number) => ({ start: (start - viewMin) / viewWindow, end: (end - viewMin) / viewWindow, }); @@ -54,7 +64,7 @@ export function createViewedBoundsFunc({ min, max, viewStart, viewEnd }) { * items. * @return {boolean} True if a match was found. */ -export function spanHasTag(key, value, span) { +export function spanHasTag(key: string, value: any, span: Span) { if (!Array.isArray(span.tags) || !span.tags.length) { return false; } @@ -66,7 +76,7 @@ export const isServerSpan = spanHasTag.bind(null, 'span.kind', 'server'); const isErrorBool = spanHasTag.bind(null, 'error', true); const isErrorStr = spanHasTag.bind(null, 'error', 'true'); -export const isErrorSpan = span => isErrorBool(span) || isErrorStr(span); +export const isErrorSpan = (span: Span) => isErrorBool(span) || isErrorStr(span); /** * Returns `true` if at least one of the descendants of the `parentSpanIndex` @@ -79,7 +89,7 @@ export const isErrorSpan = span => isErrorBool(span) || isErrorStr(span); * the parent span will be checked. * @return {boolean} Returns `true` if a descendant contains an error tag. */ -export function spanContainsErredSpan(spans, parentSpanIndex) { +export function spanContainsErredSpan(spans: Span[], parentSpanIndex: number) { const { depth } = spans[parentSpanIndex]; let i = parentSpanIndex + 1; for (; i < spans.length && spans[i].depth > depth; i++) { @@ -93,7 +103,7 @@ export function spanContainsErredSpan(spans, parentSpanIndex) { /** * Expects the first span to be the parent span. */ -export function findServerChildSpan(spans) { +export function findServerChildSpan(spans: Span[]) { if (spans.length <= 1 || !isClientSpan(spans[0])) { return false; }