-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Monitoring] CCR UI #23013
[Monitoring] CCR UI #23013
Changes from all commits
63e5dac
025f248
09f99e6
7a66a00
00f9706
f0145ef
6c25a27
42f9bdd
b1683f1
bafc945
b325eb2
8691dc5
f0bd7e3
0ca3b45
e9a4051
fac343b
1451a08
ffd5bf4
6b75c0d
e1181a5
41aa135
cadae6b
38e4a67
6bfb58f
195c58a
a179832
183accd
bc4e068
2c75c68
ca9cce4
e16515e
8cd1cbe
c46b2fc
36b8384
d22f966
d4cf306
0248638
d7b156c
0fdc024
94f06d9
8f86714
a4184fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Ccr that it renders normally 1`] = ` | ||
<EuiPage | ||
restrictWidth={false} | ||
> | ||
<EuiPageBody | ||
restrictWidth={false} | ||
> | ||
<EuiPageContent | ||
panelPaddingSize="l" | ||
> | ||
<EuiPageContentBody> | ||
<EuiInMemoryTable | ||
className="monitoringElasticsearchCcrListingTable" | ||
columns={ | ||
Array [ | ||
Object { | ||
"field": "index", | ||
"name": "Index", | ||
"render": [Function], | ||
"sortable": true, | ||
}, | ||
Object { | ||
"field": "follows", | ||
"name": "Follows", | ||
"sortable": true, | ||
}, | ||
Object { | ||
"field": "opsSynced", | ||
"name": "Ops synced", | ||
"sortable": true, | ||
}, | ||
Object { | ||
"field": "syncLagTime", | ||
"name": "Last fetch time", | ||
"render": [Function], | ||
"sortable": true, | ||
}, | ||
Object { | ||
"field": "syncLagOps", | ||
"name": "Sync Lag (ops)", | ||
"sortable": true, | ||
}, | ||
Object { | ||
"field": "error", | ||
"name": "Error", | ||
"render": [Function], | ||
"sortable": true, | ||
}, | ||
] | ||
} | ||
itemId="id" | ||
itemIdToExpandedRowMap={Object {}} | ||
items={ | ||
Array [ | ||
Object { | ||
"follows": "leader", | ||
"id": "follower", | ||
"index": "follower", | ||
"opsSynced": 400, | ||
"shards": Array [ | ||
Object { | ||
"opsSynced": 200, | ||
"shardId": 0, | ||
"syncLagOps": 2, | ||
"syncLagOpsFollower": 1, | ||
"syncLagOpsLeader": 1, | ||
"syncLagTime": 45000, | ||
}, | ||
Object { | ||
"opsSynced": 200, | ||
"shardId": 1, | ||
"syncLagOps": 1, | ||
"syncLagOpsFollower": 0, | ||
"syncLagOpsLeader": 1, | ||
"syncLagTime": 60000, | ||
}, | ||
], | ||
"syncLagOps": 5, | ||
"syncLagTime": 60000, | ||
}, | ||
Object { | ||
"error": "not_working_properly", | ||
"follows": "leader2", | ||
"id": "follower2", | ||
"index": "follower2", | ||
"opsSynced": 50, | ||
"shards": Array [ | ||
Object { | ||
"opsSynced": 20, | ||
"shardId": 1, | ||
"syncLagOps": 0, | ||
"syncLagOpsFollower": 0, | ||
"syncLagOpsLeader": 0, | ||
"syncLagTime": 11000, | ||
}, | ||
Object { | ||
"error": "not_working_properly", | ||
"opsSynced": 30, | ||
"shardId": 2, | ||
"syncLagOps": 5, | ||
"syncLagOpsFollower": 5, | ||
"syncLagOpsLeader": 0, | ||
"syncLagTime": 1000, | ||
}, | ||
], | ||
"syncLagOps": 1, | ||
"syncLagTime": 12000, | ||
}, | ||
] | ||
} | ||
pagination={false} | ||
responsive={true} | ||
sorting={ | ||
Object { | ||
"sort": Object { | ||
"direction": "asc", | ||
"field": "index", | ||
}, | ||
} | ||
} | ||
/> | ||
</EuiPageContentBody> | ||
</EuiPageContent> | ||
</EuiPageBody> | ||
</EuiPage> | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* [1] - We want the collapsed table (that shows the shard data) to be inline | ||
* with the columns from the main table so we need to remove the padding | ||
*/ | ||
.monitoringElasticsearchCcrListingTable .euiTableRow-isExpandedRow > .euiTableRowCell > .euiTableCellContent { | ||
padding: 0; /* [1] */ | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React, { Fragment, Component } from 'react'; | ||
import { | ||
EuiInMemoryTable, | ||
EuiLink, | ||
EuiPage, | ||
EuiPageBody, | ||
EuiPageContent, | ||
EuiPageContentBody, | ||
EuiIcon, | ||
EuiIconTip, | ||
EuiTextColor | ||
} from '@elastic/eui'; | ||
|
||
import './ccr.css'; | ||
|
||
function toSeconds(ms) { | ||
return Math.floor(ms / 1000) + 's'; | ||
} | ||
|
||
export class Ccr extends Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
itemIdToExpandedRowMap: {}, | ||
}; | ||
} | ||
|
||
toggleShards(index, shards) { | ||
const itemIdToExpandedRowMap = { | ||
...this.state.itemIdToExpandedRowMap | ||
}; | ||
|
||
if (itemIdToExpandedRowMap[index]) { | ||
delete itemIdToExpandedRowMap[index]; | ||
} else { | ||
let pagination = { | ||
initialPageSize: 5, | ||
pageSizeOptions: [5, 10, 20] | ||
}; | ||
|
||
if (shards.length <= pagination.initialPageSize) { | ||
pagination = false; | ||
} | ||
|
||
itemIdToExpandedRowMap[index] = ( | ||
<EuiInMemoryTable | ||
items={shards} | ||
columns={[ | ||
{ | ||
field: 'shardId', | ||
name: 'Shard', | ||
render: shardId => { | ||
return ( | ||
<EuiLink href={`#/elasticsearch/ccr/${index}/shard/${shardId}`}> | ||
{shardId} | ||
</EuiLink> | ||
); | ||
} | ||
}, | ||
{ | ||
render: () => null | ||
}, | ||
{ | ||
field: 'opsSynced', | ||
name: 'Ops synced' | ||
}, | ||
{ | ||
field: 'syncLagTime', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we later also clean up the field naming to be consistent with the Name? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea probably a good idea |
||
name: 'Last fetch time', | ||
render: syncLagTime => <span>{toSeconds(syncLagTime)}</span> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we will always be interested in seconds? It could also be larger or smaller I would assume? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. I'll address in a follow up |
||
}, | ||
{ | ||
field: 'syncLagOps', | ||
name: 'Sync Lag (ops)', | ||
render: (syncLagOps, data) => ( | ||
<span> | ||
{syncLagOps} | ||
| ||
<EuiIconTip | ||
size="m" | ||
type="iInCircle" | ||
content={( | ||
<Fragment> | ||
<span>Leader lag: {data.syncLagOpsLeader}</span> | ||
<br/> | ||
<span>Follower lag: {data.syncLagOpsFollower}</span> | ||
</Fragment> | ||
)} | ||
position="right" | ||
/> | ||
</span> | ||
) | ||
}, | ||
{ | ||
field: 'error', | ||
name: 'Error', | ||
render: error => ( | ||
<EuiTextColor color="danger"> | ||
{error} | ||
</EuiTextColor> | ||
) | ||
} | ||
]} | ||
sorting={true} | ||
pagination={pagination} | ||
/> | ||
); | ||
} | ||
this.setState({ itemIdToExpandedRowMap }); | ||
} | ||
|
||
renderTable() { | ||
const { data } = this.props; | ||
const items = data; | ||
|
||
let pagination = { | ||
initialPageSize: 5, | ||
pageSizeOptions: [5, 10, 20] | ||
}; | ||
|
||
if (items.length <= pagination.initialPageSize) { | ||
pagination = false; | ||
} | ||
|
||
const sorting = { | ||
sort: { | ||
field: 'index', | ||
direction: 'asc', | ||
}, | ||
}; | ||
|
||
return ( | ||
<EuiInMemoryTable | ||
className="monitoringElasticsearchCcrListingTable" | ||
columns={[ | ||
{ | ||
field: 'index', | ||
name: 'Index', | ||
sortable: true, | ||
render: (index, { shards }) => { | ||
const expanded = !!this.state.itemIdToExpandedRowMap[index]; | ||
return ( | ||
<EuiLink onClick={() => this.toggleShards(index, shards)}> | ||
{index} | ||
| ||
{ expanded ? <EuiIcon type="arrowUp" /> : <EuiIcon type="arrowDown" /> } | ||
</EuiLink> | ||
); | ||
} | ||
}, | ||
{ | ||
field: 'follows', | ||
sortable: true, | ||
name: 'Follows' | ||
}, | ||
{ | ||
field: 'opsSynced', | ||
sortable: true, | ||
name: 'Ops synced' | ||
}, | ||
{ | ||
field: 'syncLagTime', | ||
sortable: true, | ||
name: 'Last fetch time', | ||
render: syncLagTime => <span>{toSeconds(syncLagTime)}</span> | ||
}, | ||
{ | ||
field: 'syncLagOps', | ||
sortable: true, | ||
name: 'Sync Lag (ops)', | ||
}, | ||
{ | ||
field: 'error', | ||
sortable: true, | ||
name: 'Error', | ||
render: error => ( | ||
<EuiTextColor color="danger"> | ||
{error} | ||
</EuiTextColor> | ||
) | ||
} | ||
]} | ||
items={items} | ||
pagination={pagination} | ||
sorting={sorting} | ||
itemId="id" | ||
itemIdToExpandedRowMap={this.state.itemIdToExpandedRowMap} | ||
/> | ||
); | ||
} | ||
|
||
render() { | ||
return ( | ||
<EuiPage> | ||
<EuiPageBody> | ||
<EuiPageContent> | ||
<EuiPageContentBody> | ||
{this.renderTable()} | ||
</EuiPageContentBody> | ||
</EuiPageContent> | ||
</EuiPageBody> | ||
</EuiPage> | ||
); | ||
} | ||
} |
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.
For my understanding: How are these files exactly used / run?
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.
Some docs about that.
Basically, it renders a React component into a string then stores that string in a file. The next time the test is run, it renders the same React component and compares it to the file and if there is any change, it fails the test. You can however easily update this file if the change was intentional (the CI tool does it for you)
So this means any kind of visual change requires the dev to update the snapshots and thus be aware they are changing something with how the component is rendered.