Skip to content
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

Redesign Trace Timeline #2736

Merged
merged 89 commits into from
Oct 21, 2019
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
2ec84f2
Add TraceTimeline
tacigar Aug 3, 2019
3f690f3
Update css
tacigar Aug 3, 2019
69dfa0e
Set offset for tree rendering
tacigar Aug 4, 2019
b3eda10
Add TraceTree
tacigar Aug 5, 2019
29b05c4
Add SpanDetail
tacigar Aug 5, 2019
8a4b9ca
Enable to click span row
tacigar Aug 5, 2019
efbeaaa
Add expand button
tacigar Aug 5, 2019
8b7fbc1
Add expand buttons
tacigar Aug 5, 2019
ee9b960
Implement expand button
tacigar Aug 6, 2019
f1f7f40
Fix css bug
tacigar Aug 6, 2019
7b21001
Add TraceTimelineHeader
tacigar Aug 6, 2019
4f489d2
Add duration info to TraceTimeline
tacigar Aug 6, 2019
63e61f9
Add MiniMap
tacigar Aug 9, 2019
78c58f8
Update SpanAnnotation design
tacigar Aug 15, 2019
ddef53c
Improve UX of Annotation
tacigar Aug 15, 2019
ebba749
makeStyles -> withStyles
tacigar Aug 15, 2019
78c4592
Add unit tests for SpanAnnotation
tacigar Aug 15, 2019
ac75314
Add testing-library/jest-dom/extend-expect
tacigar Aug 15, 2019
6f85c03
Add unit tests for SpanAnnotations
tacigar Aug 15, 2019
304d0a9
Add unit tests for SpanTags
tacigar Aug 15, 2019
0d2bcdb
Update unit tests for SpanAnnotation
tacigar Aug 15, 2019
09c3aa6
Add unit tests for SpanDetail
tacigar Aug 15, 2019
11ff7fc
Unuse TraceMiniMap
tacigar Aug 15, 2019
a4ce2f8
makeStyles -> withStyles
tacigar Aug 16, 2019
0e35170
Refactor TimeMarker
tacigar Aug 16, 2019
767b44a
Add unit tests for TimeMarker
tacigar Aug 16, 2019
22b17f9
Add unit tests for TraceTimelineHeader
tacigar Aug 16, 2019
81c96ba
Refactor and Simplify TraceTimeline
tacigar Aug 16, 2019
27f67c7
Remove unused code
tacigar Aug 16, 2019
57ace80
Add key props to elements of TraceTree
tacigar Aug 19, 2019
f7b9b26
Change timestamp format of annotation
tacigar Aug 19, 2019
6574c50
Refactor SpanDetail
tacigar Aug 19, 2019
bef72be
Add some comments
tacigar Aug 19, 2019
c628591
Fix SpanAnnotation bug
tacigar Aug 19, 2019
afb46ea
Remove TraceMiniMap
tacigar Aug 19, 2019
fb9fe8b
Refactor TraceTree a little
tacigar Aug 19, 2019
f6009e3
Use theme.spacing for table cell padding
tacigar Sep 17, 2019
54caf11
Update handleSpanToggleButtonClick
tacigar Sep 17, 2019
a9491dc
Refactor TraceTree
tacigar Sep 17, 2019
57941de
Reroot trace tree when a span is clicked twice
tacigar Sep 24, 2019
883aec2
Disable reroot feature if the trace does not have a root span
tacigar Sep 24, 2019
917f282
Refactor TraceSummary and TraceTimeline
tacigar Sep 26, 2019
befe92d
Implement reset-reroot button
tacigar Sep 26, 2019
608428f
Change background color of the span row which is focused
tacigar Sep 26, 2019
cf7c14b
Zoom up when rerooted
tacigar Sep 26, 2019
5df8b9e
Set minimum valud for span's bar width
tacigar Sep 26, 2019
6775b9e
Give default value span bar's width
tacigar Sep 26, 2019
b92fb1a
Add right margin for timeline
tacigar Sep 26, 2019
61f3cd3
Update comments
tacigar Sep 27, 2019
5543f4b
Fix bugs of reroot feature
tacigar Sep 27, 2019
1d7773c
Open and close span detail
tacigar Sep 27, 2019
6a5b1f7
Implement Expand/Collapse buttons
tacigar Sep 27, 2019
61b38cc
Fix detailed span prop type
tacigar Sep 27, 2019
2fea74e
Fix a bug related to span with the same annotation value
tacigar Sep 27, 2019
d8a4cef
Fix bugs of duplicated key of annotations
tacigar Sep 27, 2019
b6be6f3
Fix bugs of duplicated key of tags
tacigar Sep 27, 2019
e7f292c
Fix unit test a bit
tacigar Sep 27, 2019
c768196
Fix up-control bombs bug
tacigar Sep 30, 2019
69993bb
Don't change the span bar width when collapse/expand spans
tacigar Sep 30, 2019
1549eb8
Avoid re-rendering trace timeline if not needed
tacigar Oct 1, 2019
78c4613
<React.Fragment> -> <>
tacigar Oct 1, 2019
1289126
Rename formatTimestampMillis to formatTimestampMicros
tacigar Oct 1, 2019
1ba74b7
TMP
tacigar Oct 2, 2019
4b1fb78
Implement service name badges
tacigar Oct 2, 2019
ead555f
Implement bar
tacigar Oct 2, 2019
feddb37
Change text position
tacigar Oct 3, 2019
ad08176
Fix service name badge position
tacigar Oct 3, 2019
d8c1bf6
Fix timeMarker's position
tacigar Oct 3, 2019
fb33ab2
Fix disabled collapse/expand button bugs
tacigar Oct 3, 2019
0870e4c
Refactor
tacigar Oct 3, 2019
fe8c791
Remove unnecessary lines
tacigar Oct 3, 2019
09b04e6
Partial import lodash
tacigar Oct 4, 2019
7e355cb
Open span detail when span clicked
tacigar Oct 4, 2019
6acd0f8
Don't show reroot button if the trace is not rerooted
tacigar Oct 4, 2019
7360d82
Unreroot when the current root span is doulbe-clicked
tacigar Oct 4, 2019
226a3f6
Add key props
tacigar Oct 4, 2019
871f41d
Swap + and -
tacigar Oct 4, 2019
90edc6f
Remove unused files
tacigar Oct 4, 2019
0c608fe
Add timemarker to timeline
tacigar Oct 4, 2019
bd6fa74
Remove opacity
tacigar Oct 4, 2019
8c843eb
Merge package-lock.json
tacigar Oct 4, 2019
d4298d6
Don't write colors directly on DOM elements
tacigar Oct 4, 2019
fc6723a
Simplify styling
tacigar Oct 21, 2019
6d38ebf
Use React.memo in TracePage
tacigar Oct 21, 2019
13ebb34
Enhance readability
tacigar Oct 21, 2019
8540b20
Reset reroot -> Reset root
tacigar Oct 21, 2019
3848bb1
Show root span ID
tacigar Oct 21, 2019
7452dfe
Reduce props warning
tacigar Oct 21, 2019
bb9e746
Fix bug
tacigar Oct 21, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions zipkin-lens/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions zipkin-lens/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@babel/preset-env": "^7.5.4",
"@babel/preset-react": "^7.0.0",
"@fortawesome/fontawesome-free": "^5.4.1",
"@testing-library/jest-dom": "^4.0.0",
"@testing-library/react": "^8.0.8",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^24.8.0",
Expand Down
2 changes: 0 additions & 2 deletions zipkin-lens/src/components/App/Layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ const Layout = ({ children }) => (
flexDirection="column"
height="100vh"
width="100%"
pl={3}
pr={3}
overflow="auto"
>
{children}
Expand Down
72 changes: 40 additions & 32 deletions zipkin-lens/src/components/DiscoverPage/DiscoverPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,8 @@ const useStyles = makeStyles(theme => ({
minHeight: '2rem',
},
contentPaper: {
flex: '0 1 100%',
marginTop: '1.5rem',
marginBottom: '1rem',
overflow: 'auto',
width: '100%',
height: '100%',
},
}));

Expand Down Expand Up @@ -266,37 +264,47 @@ const DiscoverPage = ({ history, location }) => {

return (
<React.Fragment>
<Box width="100%" display="flex" justifyContent="space-between">
<Box display="flex" alignItems="center">
<Typography variant="h5">
Discover
</Typography>
</Box>
<Box pr={4} display="flex" alignItems="center">
<TraceJsonUploader />
<TraceIdSearchInput />
<Box pl={3} pr={3}>
<Box width="100%" display="flex" justifyContent="space-between">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First time looking at lens code :)

Out of curiosity, have you thought about using Grid? Maybe it makes this sort of layout simpler.

<Box display="flex" alignItems="center">
<Typography variant="h5">
Discover
</Typography>
</Box>
<Box pr={3} display="flex" alignItems="center">
<TraceJsonUploader />
<TraceIdSearchInput />
</Box>
</Box>
<GlobalSearch findData={findData} />
</Box>
<GlobalSearch findData={findData} />
<Paper className={classes.contentPaper}>
<Box overflow="auto" width="100%" height="100%">
<AppBar position="static">
<Tabs
value={tabValue}
onChange={handleTabChange}
className={classes.tabs}
>
<Tab label="Traces" className={classes.tab} />
<Tab label="Dependencies" className={classes.tab} />
</Tabs>
</AppBar>
{ /* 2rem is the height of the Appbar. */}
<Box height="calc(100% - 2rem)">
{tabValue === tracesTab && <TracesTab />}
{tabValue === dependenciesTab && <DependenciesTab />}
<Box
flex="0 1 100%"
marginTop={1.5}
marginBottom={1}
marginRight={3}
marginLeft={3}
>
<Paper className={classes.contentPaper}>
<Box overflow="auto" width="100%" height="100%">
<AppBar position="static">
<Tabs
value={tabValue}
onChange={handleTabChange}
className={classes.tabs}
>
<Tab label="Traces" className={classes.tab} />
<Tab label="Dependencies" className={classes.tab} />
</Tabs>
</AppBar>
{ /* 2rem is the height of the Appbar. */}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we extract a constant for the height of app bar and then we don't even need a comment?

<Box height="calc(100% - 2rem)">
{tabValue === tracesTab && <TracesTab />}
{tabValue === dependenciesTab && <DependenciesTab />}
</Box>
</Box>
</Box>
</Paper>
</Paper>
</Box>
</React.Fragment>
);
};
Expand Down
81 changes: 81 additions & 0 deletions zipkin-lens/src/components/TracePage/SpanDetail/SpanAnnotation.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2015-2019 The OpenZipkin Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
import PropTypes from 'prop-types';
import React from 'react';
import moment from 'moment';
import { withStyles } from '@material-ui/styles';
import Box from '@material-ui/core/Box';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';

import { spanAnnotationPropTypes } from '../../../prop-types';

const propTypes = {
annotation: spanAnnotationPropTypes.isRequired,
classes: PropTypes.shape({}).isRequired,
};

const style = {
cell: {
paddingTop: '8px',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Curious, isn't it better to use theme.spacing(1) in this case? Or anything that is equivalent to 8px if this UI is using custom Theme.

Makes it easier for global customization as well if there needs to be a global padding change in the future.

paddingBottom: '8px',
},
};

const SpanAnnotation = ({ annotation, classes }) => (
<Box>
<Box fontSize="1.1rem" mb={0.5}>
{annotation.value}
</Box>
<Paper>
<Table>
<TableBody data-testid="span-annotation--table-body">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not this PR, but it'd be good to strip these with https://www.npmjs.com/package/babel-plugin-react-remove-properties

zipkin UI has tons of DOM, so these extra attributes look like they can have significant enough impact on performance compared to other apps.

{
[
{
label: 'Start Time',
// moment.js only supports millisecond precision, however our timestamps have
// microsecond precision. So we use moment.js to generate the human readable time
// with just milliseconds and then append the last 3 digits of the timestamp
// which are the microseconds.
// NOTE: a.timestamp % 1000 would save a string conversion but drops
// leading zeros.
value: moment(annotation.timestamp / 1000).format('MM/DD HH:mm:ss.SSS')
+ annotation.timestamp.toString().slice(-3),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the result of this would be something like 08/18 16:13:02.123456? Since the fractional part of the second (123456) is longer than 3, I think we can do a small touch and use _ to improve readability (so it would be 02.123_456).

I believe it's common in several programming languages and is coming to JS too: https://github.com/tc39/proposal-numeric-separator#references

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I think it would be useful to extract this functionalitity to something like a global util of this package? (especially for its comment)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your advice!
Done 🙇

},
{ label: 'Relative Time', value: annotation.relativeTime },
{ label: 'Address', value: annotation.endpoint },
].map(e => (
<TableRow key={e.label}>
<TableCell className={classes.cell} data-testid="span-annotation--label">
{e.label}
</TableCell>
<TableCell className={classes.cell} data-testid="span-annotation--value">
{e.value}
</TableCell>
</TableRow>
))
}
</TableBody>
</Table>
</Paper>
</Box>
);

SpanAnnotation.propTypes = propTypes;

export default withStyles(style)(SpanAnnotation);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also how about adding React.memo to all the components? Avoiding rerendering is very important with all this DOM.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to think a little more about whether to use React.memo for all the components.
But using React.memo on the trace timeline clearly improved rendering performance.

Before

before-optimization

After

after-optimization

Thank you for your advice!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a nice improvement! I'm guessing there might be other good places like each individual trace (make sure not to rerender when expanding a trace) - but often it's just simplest to reason about to use memo as much as possible since

  • We have so many components anyways, adding the HoC isn't a significant impact
  • Either a component rerenders, meaning the computation of memo was a bit of a waste, or it doesn't meaning it was worth it. But even for very simple components the rerender (virtual DOM operations) should always be much more expensive then computing the memo.

But will leave it to you how much you add it :)

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2015-2019 The OpenZipkin Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
import React from 'react';
import { createShallow } from '@material-ui/core/test-utils';

import SpanAnnotation from './SpanAnnotation';

describe('<SpanAnnotation />', () => {
let shallow;

beforeEach(() => {
shallow = createShallow();
});

it('should render annotation data', () => {
const wrapper = shallow(
<SpanAnnotation.Naked
annotation={{
value: 'Server Start',
timestamp: 1543334627716006, // 11/28 01:03:47.716006
relativeTime: '700ms',
endpoint: '127.0.0.1',
}}
classes={{}}
/>,
);
const rows = wrapper.find('[data-testid="span-annotation--table-body"]');
expect(rows.childAt(0).find('[data-testid="span-annotation--label"]').text()).toBe('Start Time');
expect(rows.childAt(0).find('[data-testid="span-annotation--value"]').text()).toBe('11/28 01:03:47.716006');
expect(rows.childAt(1).find('[data-testid="span-annotation--label"]').text()).toBe('Relative Time');
expect(rows.childAt(1).find('[data-testid="span-annotation--value"]').text()).toBe('700ms');
expect(rows.childAt(2).find('[data-testid="span-annotation--label"]').text()).toBe('Address');
expect(rows.childAt(2).find('[data-testid="span-annotation--value"]').text()).toBe('127.0.0.1');
});
});
Loading