数据表
部队布局不利于人们经常做的三件事:读取精确值、按比例进行选择以及确定从哪里开始。 UI.table 从画布底部拆分出数据停靠点,以回答所有三个问题 - 图表的行、可排序和可选择。
循环是表格查找,画布理解,侧边栏阅读:
- 该表打开时按请求排序,因此最繁忙的服务是第一行。
- 单击任何标题重新排序;再次单击可反转。
- 单击一行以选择它,
Ctrl+Click添加一个,或Shift+Click获取范围按照显示的顺序 — 然后使用侧边栏的批量操作对批次进行操作。 - 相反,在画布上用橡皮筋绑住一组,匹配的行就会亮起。
- 缩小标题行的范围 - 控件跟随列:输入 Service,从 Kind 中选择,在 Requests / day 上设置界限。这永远不会触及画布:图表自己的过滤器与过滤器面板保持一致,因此两者无法冲突。
- Nodes / Edges 切换列出的内容。 CSV 和 JSON 准确写出屏幕上的内容 - 这个选项卡、这些列、这种排序、这个过滤器。
该扩展坞还列出了图形当前隐藏的节点,其中Visibility列说明是过滤器还是手动隐藏负责 - 因此“隐藏的23个节点”是您可以检查而不是信任的东西。
拖动分隔线以调整其大小,或使用 V 形将其折叠到标题栏。两者都不会移动图形:模拟根据容器而不是画布调整自身,因此镶边打开和关闭永远不会改变布局。
有关完整选项集,请参阅数据表。
js
// import { ColorPaletteMapper, tableColumns } from 'pivotick'
//
// The data dock comes with `mode: 'full'`, folded to its header bar — click the chevron
// or press Shift+T. `open: true` below starts it expanded instead. Everything here is
// optional; `UI: { mode: 'full' }` alone gets you a dock.
//
// Columns are derived when you don't declare any: the graph-aware ones lead (Label,
// Degree, Visibility) and the data keys follow, ordered by how many nodes carry them.
// They are declared here instead, to put `requests` on the right and give three columns
// a row filter — one of each kind, since the control follows the column's `type`.
// `tableColumns` holds the graph-aware ones — clone one to relabel it.
const options = {
UI: {
mode: 'full',
// Full mode's minimap would sit in the corner this card wants for the dock,
// and the dock is the subject — see the Minimap card for that one.
minimap: false,
// Top-left, because this embed is 560px tall and the dock takes 42% of it: the
// canvas that's left is shorter than the mode rail, so the bottom-left corner has
// no column to give. A bottom-left legend would shrink to its header here.
legend: { position: 'top-left' },
table: {
open: true,
height: 0.42,
// Busiest first — the question you actually arrive with.
sort: { key: 'requests', direction: 'desc' },
columns: [
{ ...tableColumns.label, label: 'Service', filterable: true },
{ key: 'kind', label: 'Kind', type: 'select', filterable: true },
{ key: 'owner', label: 'Owner', type: 'select' },
{ key: 'tier', label: 'Tier', type: 'select' },
{ key: 'requests', label: 'Requests / day', type: 'numberRange', align: 'right', filterable: true },
{ ...tableColumns.degree, label: 'Links' },
],
},
},
// Colour by the same `kind` the table shows, so a row and a dot can be matched by
// eye. Declaring `nodeTypeAccessor` is also what earns the canvas its legend.
render: {
nodeTypeAccessor: (node) => node.getData().kind,
defaultNodeStyle: {
color: (node) => palette.getColor(node.getData().kind),
},
},
}js
const data = {
nodes: [
{ id: 'api', data: { label: 'api-gateway', kind: 'service', owner: 'Platform', requests: 48200, tier: 'edge' } },
{ id: 'auth', data: { label: 'auth-service', kind: 'service', owner: 'Identity', requests: 31400, tier: 'core' } },
{ id: 'billing', data: { label: 'billing-service', kind: 'service', owner: 'Payments', requests: 8600, tier: 'core' } },
{ id: 'search', data: { label: 'search-service', kind: 'service', owner: 'Discovery', requests: 22750, tier: 'core' } },
{ id: 'users-db', data: { label: 'users-db', kind: 'datastore', owner: 'Identity', requests: 39900, tier: 'data' } },
{ id: 'orders-db', data: { label: 'orders-db', kind: 'datastore', owner: 'Payments', requests: 12300, tier: 'data' } },
{ id: 'index', data: { label: 'search-index', kind: 'datastore', owner: 'Discovery', requests: 20100, tier: 'data' } },
{ id: 'cache', data: { label: 'edge-cache', kind: 'datastore', owner: 'Platform', requests: 51000, tier: 'edge' } },
{ id: 'mailer', data: { label: 'mailer', kind: 'worker', owner: 'Payments', requests: 1450, tier: 'async' } },
{ id: 'reindexer', data: { label: 'reindexer', kind: 'worker', owner: 'Discovery', requests: 980, tier: 'async' } },
],
edges: [
{ from: 'api', to: 'auth', data: { label: 'authenticates' } },
{ from: 'api', to: 'search', data: { label: 'queries' } },
{ from: 'api', to: 'billing', data: { label: 'charges' } },
{ from: 'api', to: 'cache', data: { label: 'reads' } },
{ from: 'auth', to: 'users-db', data: { label: 'reads' } },
{ from: 'billing', to: 'orders-db', data: { label: 'writes' } },
{ from: 'billing', to: 'mailer', data: { label: 'enqueues' } },
{ from: 'search', to: 'index', data: { label: 'reads' } },
{ from: 'reindexer', to: 'index', data: { label: 'writes' } },
{ from: 'reindexer', to: 'orders-db', data: { label: 'reads' } },
],
}