-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pkg/ui: Add span details component to tracez_v2.
This PR adds the "span details" and "raw trace" screens to the new tracez_v2 page. Previously, only the "snapshot details (i.e. list spans) screen existed on that page. The detailed span information page is where users will go to dig in to the specifics of a span. In particular, we'll display accumulated data on child spans of that page, helping navigate to problem segments more easily. Note that this PR brings the v2 page up to feature parity with the v1 page. Though the redesign is not yet complete, we'll be able to turn down the v1 page after this lands. This PR also modifies the route structure a little to encapsulate better. Release note: None
- Loading branch information
Showing
12 changed files
with
991 additions
and
209 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
pkg/ui/workspaces/cluster-ui/src/tracez/snapshot/rawTraceComponent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
import { GetTraceResponse } from "src/api"; | ||
import Long from "long"; | ||
import { Loading } from "src/loading"; | ||
import React, { useEffect } from "react"; | ||
import classNames from "classnames/bind"; | ||
import styles from "../snapshot.module.scss"; | ||
const cx = classNames.bind(styles); | ||
|
||
export const RawTraceComponent: React.FC<{ | ||
nodeID: string; | ||
snapshotID: number; | ||
traceID: Long; | ||
rawTrace: GetTraceResponse; | ||
rawTraceLoading: boolean; | ||
rawTraceError?: Error; | ||
refreshRawTrace: (req: { | ||
nodeID: string; | ||
snapshotID: number; | ||
traceID: Long; | ||
}) => void; | ||
}> = props => { | ||
const { | ||
nodeID, | ||
snapshotID, | ||
traceID, | ||
rawTrace, | ||
rawTraceLoading, | ||
rawTraceError, | ||
refreshRawTrace, | ||
} = props; | ||
|
||
useEffect(() => { | ||
if (!(nodeID && snapshotID && traceID)) { | ||
return; | ||
} | ||
refreshRawTrace({ | ||
nodeID, | ||
snapshotID, | ||
traceID, | ||
}); | ||
}, [nodeID, snapshotID, traceID, refreshRawTrace]); | ||
|
||
return ( | ||
<Loading | ||
loading={rawTraceLoading} | ||
page={"raw trace"} | ||
error={rawTraceError} | ||
render={() => { | ||
return ( | ||
<> | ||
<section | ||
data-testid="raw-trace-component" | ||
className={cx("span-section")} | ||
> | ||
<pre>{rawTrace?.serialized_recording}</pre> | ||
</section> | ||
<div className={cx("bottom-padding")} /> | ||
</> | ||
); | ||
}} | ||
/> | ||
); | ||
}; |
161 changes: 161 additions & 0 deletions
161
pkg/ui/workspaces/cluster-ui/src/tracez/snapshot/snapshotComponent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
import { Helmet } from "react-helmet"; | ||
import { commonStyles } from "src/common"; | ||
import { PageConfig, PageConfigItem } from "src/pageConfig"; | ||
import { Button, Icon } from "@cockroachlabs/ui-components"; | ||
import { Dropdown } from "src/dropdown"; | ||
import { Loading } from "src/loading"; | ||
import { SpanTable } from "./spanTable"; | ||
import React, { useMemo } from "react"; | ||
import classNames from "classnames/bind"; | ||
import styles from "../snapshot.module.scss"; | ||
import { TimestampToMoment } from "src/util"; | ||
import { SortSetting } from "src/sortedtable"; | ||
import { | ||
GetTracingSnapshotResponse, | ||
ListTracingSnapshotsResponse, | ||
} from "src/api"; | ||
import { cockroach } from "@cockroachlabs/crdb-protobuf-client"; | ||
import Long from "long"; | ||
const cx = classNames.bind(styles); | ||
|
||
export const SnapshotComponent: React.FC<{ | ||
sort: SortSetting; | ||
changeSortSetting: (value: SortSetting) => void; | ||
nodes?: cockroach.server.status.statuspb.INodeStatus[]; | ||
nodeID: string; | ||
onNodeSelected: (_: string) => void; | ||
snapshots: ListTracingSnapshotsResponse; | ||
snapshotID: number; | ||
snapshot: GetTracingSnapshotResponse; | ||
onSnapshotSelected: (_: number) => void; | ||
isLoading: boolean; | ||
error: Error; | ||
spanDetailsURL: (_: Long) => string; | ||
takeAndLoadSnapshot: () => void; | ||
}> = props => { | ||
const { | ||
sort, | ||
changeSortSetting, | ||
nodes, | ||
nodeID, | ||
onNodeSelected, | ||
snapshots, | ||
snapshotID, | ||
snapshot, | ||
onSnapshotSelected, | ||
isLoading, | ||
error, | ||
spanDetailsURL, | ||
takeAndLoadSnapshot, | ||
} = props; | ||
|
||
const snapshotsAsJson = JSON.stringify(snapshots); | ||
|
||
const [snapshotItems, snapshotName] = useMemo(() => { | ||
if (!snapshots) { | ||
return [[], ""]; | ||
} | ||
let selectedName = ""; | ||
const items = snapshots.snapshots.map(snapshotInfo => { | ||
const id = snapshotInfo.snapshot_id.toNumber(); | ||
const time = TimestampToMoment(snapshotInfo.captured_at).format( | ||
"MMM D, YYYY [at] HH:mm:ss", | ||
); | ||
const out = { | ||
name: "Snapshot " + id + ": " + time, | ||
value: id, | ||
}; | ||
if (id === snapshotID) { | ||
selectedName = out.name; | ||
} | ||
return out; | ||
}); | ||
return [items, selectedName]; | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [snapshotsAsJson, snapshotID]); | ||
|
||
const [nodeItems, nodeName] = useMemo(() => { | ||
if (!nodes) { | ||
return [[], ""]; | ||
} | ||
let selectedName = ""; | ||
const items = nodes.map(node => { | ||
const id = node.desc.node_id.toString(); | ||
const out = { | ||
name: "Node " + id, | ||
value: id, | ||
}; | ||
if (id === nodeID) { | ||
selectedName = out.name; | ||
} | ||
return out; | ||
}); | ||
return [items, selectedName]; | ||
}, [nodes, nodeID]); | ||
|
||
return ( | ||
<div className={cx("snapshots-page")}> | ||
<Helmet title="Snapshots" /> | ||
<h3 | ||
data-testid="snapshot-component-title" | ||
className={commonStyles("base-heading")} | ||
> | ||
Snapshots | ||
</h3> | ||
<div> | ||
<PageConfig> | ||
<PageConfigItem> | ||
<Button onClick={takeAndLoadSnapshot} intent="secondary"> | ||
<Icon iconName="Download" /> Take snapshot | ||
</Button> | ||
</PageConfigItem> | ||
<PageConfigItem> | ||
<Dropdown items={nodeItems} onChange={onNodeSelected}> | ||
{nodeName} | ||
</Dropdown> | ||
</PageConfigItem> | ||
{snapshotItems.length > 0 && ( | ||
<PageConfigItem> | ||
<Dropdown<number> | ||
items={snapshotItems} | ||
onChange={onSnapshotSelected} | ||
> | ||
{snapshotName} | ||
</Dropdown> | ||
</PageConfigItem> | ||
)} | ||
</PageConfig> | ||
</div> | ||
<section className={cx("section")}> | ||
{snapshotID ? ( | ||
<Loading | ||
loading={isLoading} | ||
page={"snapshots"} | ||
error={error} | ||
render={() => ( | ||
<SpanTable | ||
snapshot={snapshot?.snapshot} | ||
setSort={changeSortSetting} | ||
sort={sort} | ||
spanDetailsURL={spanDetailsURL} | ||
/> | ||
)} | ||
/> | ||
) : ( | ||
"No snapshots found on this node." | ||
)} | ||
</section> | ||
<div className={cx("bottom-padding")} /> | ||
</div> | ||
); | ||
}; |
Oops, something went wrong.