-
Notifications
You must be signed in to change notification settings - Fork 487
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Virtualized scrolling for trace detail view #68
Conversation
TODO - Test are currently in a bad state - Finish shifting to transformed trace, exclusively, instead of raw trace - Misc cleanup (unused / ordering of vars, imports, etc) is outstanding while changes are WIP - Continued refinement of trace-detail components, selectors and utils - Many styles will be moved to CSS - Will likely remove `model/trace-viewer.js` SpanGraph - Fix #49 - Span position in graph doesn not match its position in the detail - Ticks in span graph made to match trace detail (in number and formatting) - Span graph refactored to trim down files and DOM elements TracePageHeader - `trace` prop removed - Added props for various title values instead of deriving them from `trace` Trace Detail - Several components split out into separate files - `transformTrace` to use alread span tree to determine span depth Span Detail - Fix uber/jaeger #326: extraneous scrollbars in trace views - Fix: Some tags were not being rendered due to clashing keys (observed in a log message) - Tall content scrolls via entire table instead of single table cell - Horizontal scrolling for wide content (e.g. long log values) - Full width of the header is clickable for tags, process, and logs headers (instead of header text, only) - Service and endpoint are shown on mouseover anywhere in span bar row Misc - Several TraceTimelineViewer / utils removed - `TreeNode` `.walk()` method can now be used to calculate the depth, avoiding use of less efficient `.getPath()` - Removed several `console.error` warnings caused by React key issues
TODO - Test are currently in a bad state - Finish shifting to transformed trace, exclusively, instead of raw trace - Misc cleanup (unused / ordering of vars, imports, etc) is outstanding while changes are WIP - Continued refinement of trace-detail components, selectors and utils - Many styles will be moved to CSS - Will likely remove `model/trace-viewer.js` Span Bar / Detail - Label on span bars no longer off-screen - Clip or hide span bars when zoomed in (insted of flush left) - Add shadow to left / right boundary when span bar view is clipped - Darkened span name column to differentiate from span bar section - Span detail left column color coded by service - Clicking span detail left column collapses detail - Clicking anywhere left of parent span name toggles children visibility
Sub-page scrolling used for trace detail (TODO: revert this). This lays the ground work for using react-virtualized, but unfortunately has major perf issues, hence the TODO: revert. yarn upgrade --latest. Notable changes: - Removed react-sticky - react-router v4 - react-vis CSS needed to be included via a sym-link Misc tweaks: - Styling adjusted on trace mini-map - Scatterplot dots are sized based on number of spans - Scatterplot dots mouseover shows trace name
Add back the styling that adds an ellipsis to truncated span name text.
…60-react-virtualized
Outstanding: - Window scroller used https://bvaughn.github.io/react-virtualized/#/components/WindowScroller - Expanding span details - Collapsing / expanding children
Switching to use a props oriented ui state management for span details. This is necessary because the virtualized scroller removes and adds span details as it scrolls. The span detail components cannot retain their own state (e.g. tags table is expanded / collapsed, etc.) because they are not long-lived.
Changes Unknown when pulling f8dd6b8 on milestone1/issue-60-react-virtualized into ** on master**. |
Changes Unknown when pulling cd45e62 on milestone1/issue-60-react-virtualized into ** on master**. |
@@ -367,7 +375,8 @@ export default class ListView extends React.Component<ListViewProps> { | |||
const max = nodes.length; | |||
for (let i = 0; i < max; i++) { | |||
const node: HTMLElement = (nodes[i]: any); | |||
const itemKey = node.dataset.itemKey; | |||
// const itemKey = node.dataset.itemKey; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO(joe): remove this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
windowAddListenerSpy.mockRestore(); | ||
}); | ||
|
||
it('adds the onScroll listener to the root HTML element after it mounts', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO(joe): adds the listener to window
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Changes Unknown when pulling f45d360 on milestone1/issue-60-react-virtualized into ** on master**. |
Changes Unknown when pulling ff2ae49 on milestone1/issue-60-react-virtualized into ** on master**. |
/** | ||
* Indicates how far past the explicitly required height or y-values should | ||
* checked. | ||
* @type {number} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an FYI, I think flow types will give you this for free so you don't need to write it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Turns out jsDoc is dead to me, long live documentation.js. It's got a ton of problems, but it looks like you get a lot for free 👍
}; | ||
|
||
function KeyValuesSummary(props: KeyValuesSummaryProps) { | ||
const { data } = props; | ||
function getKVSummary(data: { key: string, value: any }[]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any advantage in changing this? Why not just make this a React function component? I'm still a fan of being explicit with variable names aka KeyValue
instead of KV
. Although I know you have some preference of short names that are declared within close scope.
<KVSummary data={..} />
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it's a lot more performant as a regular function which is invoked, but that's kind of minor considering these are relatively rare (requiring the details to be expanded).
I've reverted the change.
|
||
import type { Log } from '../../../../types'; | ||
|
||
// DetailState { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove comments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
style={{ borderColor: color }} | ||
/> | ||
</span> | ||
</div> | ||
</TimelineRow.Left> | ||
<TimelineRow.Right> | ||
<div className="p2 detail-info-wrapper" style={{ borderTopColor: color }}> | ||
<SpanDetail span={span} trace={trace} /> | ||
<SpanDetail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a higher level API that could be composed to these props is.
<SpanDetail trace={$Trace} spanID={$spanID} />
which can call this component you have
That way its a similar data model
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only thing needed from the trace was the start time, so I changed the param to traceStartTime
and kept the rest as-is. Most of them (*Toggle
) trigger actions.
detailToggle: string => void, | ||
findMatchesIDs: Set<string>, | ||
ticks: number[], | ||
trace?: XformedTrace, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, if the trace needs to be loaded it is undefined
until it is loaded.
// } | ||
// | ||
|
||
export function newInitialState(trace = null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a fan of this ducks approach
this.toggleSpanCollapse = this.toggleSpanCollapse.bind(this); | ||
this.toggleSpanSelect = this.toggleSpanSelect.bind(this); | ||
|
||
this.store = createStore(reducer, newInitialState(xformedTrace)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still a little iffy on this. I would just reuse the store and create a new namespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I've folded the state management into the top-level redux store.
if (textFilter === this.props.textFilter && xformedTrace === this.props.xformedTrace) { | ||
return; | ||
if (xformedTrace !== this.props.xformedTrace) { | ||
throw new Error('Component does not support changing the trace'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should this matter?
- JSDoc tweaks - documentation.js can infer types automatically - Move trace transform - Move trace tranform out of src/components/TracePage/TraceTimelineViewer/transforms and into src/model/transform-trace-data.js - Apply trace transform to data from HTTP response so the trace data stored in the state is always the enriched form
Changes Unknown when pulling 6059fed on milestone1/issue-60-react-virtualized into ** on master**. |
* Update prettier and wrap at 110 instead of 80 * WIP commit for refactoring trace detail view TODO - Test are currently in a bad state - Finish shifting to transformed trace, exclusively, instead of raw trace - Misc cleanup (unused / ordering of vars, imports, etc) is outstanding while changes are WIP - Continued refinement of trace-detail components, selectors and utils - Many styles will be moved to CSS - Will likely remove `model/trace-viewer.js` SpanGraph - Fix #49 - Span position in graph doesn not match its position in the detail - Ticks in span graph made to match trace detail (in number and formatting) - Span graph refactored to trim down files and DOM elements TracePageHeader - `trace` prop removed - Added props for various title values instead of deriving them from `trace` Trace Detail - Several components split out into separate files - `transformTrace` to use alread span tree to determine span depth Span Detail - Fix uber/jaeger jaegertracing#326: extraneous scrollbars in trace views - Fix: Some tags were not being rendered due to clashing keys (observed in a log message) - Tall content scrolls via entire table instead of single table cell - Horizontal scrolling for wide content (e.g. long log values) - Full width of the header is clickable for tags, process, and logs headers (instead of header text, only) - Service and endpoint are shown on mouseover anywhere in span bar row Misc - Several TraceTimelineViewer / utils removed - `TreeNode` `.walk()` method can now be used to calculate the depth, avoiding use of less efficient `.getPath()` - Removed several `console.error` warnings caused by React key issues * WIP commit for refactoring trace detail view TODO - Test are currently in a bad state - Finish shifting to transformed trace, exclusively, instead of raw trace - Misc cleanup (unused / ordering of vars, imports, etc) is outstanding while changes are WIP - Continued refinement of trace-detail components, selectors and utils - Many styles will be moved to CSS - Will likely remove `model/trace-viewer.js` Span Bar / Detail - Label on span bars no longer off-screen - Clip or hide span bars when zoomed in (insted of flush left) - Add shadow to left / right boundary when span bar view is clipped - Darkened span name column to differentiate from span bar section - Span detail left column color coded by service - Clicking span detail left column collapses detail - Clicking anywhere left of parent span name toggles children visibility * WIP refactor trace detail, split out css, start fixing tests * WIP refactor trace detail, tests working again * WIP refactor trace, yarn upgrade Sub-page scrolling used for trace detail (TODO: revert this). This lays the ground work for using react-virtualized, but unfortunately has major perf issues, hence the TODO: revert. yarn upgrade --latest. Notable changes: - Removed react-sticky - react-router v4 - react-vis CSS needed to be included via a sym-link Misc tweaks: - Styling adjusted on trace mini-map - Scatterplot dots are sized based on number of spans - Scatterplot dots mouseover shows trace name * WIP refactor trace, test maintenance * remove unused import * add license to css files * Revert sub-page scrolling for trace detail * Support URL prefix via homepage in package.json * Prevent collision of logs in log entries table * Add comments to new utils * WIP Use react-virtualized in trace detail view * Fix jaegertracing#59 - "Span Name" to "Service & Operation" * Fix unreleased regression - ellipsis on span name Add back the styling that adds an ellipsis to truncated span name text. * Address PR comment on search results scatter plot https://github.com/uber/jaeger-ui/pull/53#discussion_r134313013 * Misc cleanup from PR comment https://github.com/uber/jaeger-ui/pull/53#discussion_r134314020 * PR comment - Remove ms and use nano seconds https://github.com/uber/jaeger-ui/pull/53#discussion_r134316418 * PR comment - Adjust export, relates to recompose https://github.com/uber/jaeger-ui/pull/53#discussion_r134318188 * Reorganize span detail components * PR comment - Comment getTraceSpanIdsAsTree() https://github.com/uber/jaeger-ui/pull/53#discussion_r134321990 * PR comment - Add "SpanID:" label https://github.com/uber/jaeger-ui/pull/64#issuecomment-324080675 * WIP react-virtualized layout progress Outstanding: - Window scroller used https://bvaughn.github.io/react-virtualized/#/components/WindowScroller - Expanding span details - Collapsing / expanding children * WIP react-virtualized layout progress Switching to use a props oriented ui state management for span details. This is necessary because the virtualized scroller removes and adds span details as it scrolls. The span detail components cannot retain their own state (e.g. tags table is expanded / collapsed, etc.) because they are not long-lived. * PR comment - Flow typing for props https://github.com/uber/jaeger-ui/pull/64#discussion_r134792924 * WIP Switching react-virtualized to custom solution * fix file-header licenses * WIP Switching react-virtualized to custom solution * Add flow to ListView, comment ListView, Positions * Positions tests, fix edge-case bug in Positions * Fix comment issue from prettier * Unit tests for ListView, remove unused propType/* * Minor changes to a comment and a test case description * Unit tests for TraceTimelineViewer/duck * remove react-virtualized from package.json * PR feedback - JSDoc, move trace transform - JSDoc tweaks - documentation.js can infer types automatically - Move trace transform - Move trace tranform out of src/components/TracePage/TraceTimelineViewer/transforms and into src/model/transform-trace-data.js - Apply trace transform to data from HTTP response so the trace data stored in the state is always the enriched form * Use top-level redux store for traceTimeline state Signed-off-by: vvvprabhakar <[email protected]>
TODO
Description
Started with react-virtualized, but issues around flashes of un-rendered regions while scrolling and dynamically sized / periodically changing content lead to revival of old project that essentially does the same thing:
src/components/TracePage/TraceTimelineViewer/ListView/*
.ListView
is more optimized to our needs (and less versatile). These optimizations include:Performance
Flashes of un-rendered content
Performance on a 5,000 span trace
Sample size of 1.
Initial loading (in milliseconds)
Note: Ticket #61 (Use canvas instead of SVG for trace mini-map) will likely further improve initial loading.
Expanding details
Text search ("gopro")
Performance on a 42,000 span trace
Sample size of 1.
Initial loading (in milliseconds)
Expanding details
Text search ("gopro")