mirror of
https://github.com/wassname/ray.git
synced 2026-06-28 02:01:24 +08:00
Expose extra node info from raylet stats (#6511)
This commit is contained in:
committed by
Philipp Moritz
parent
ce1c9a87a7
commit
6cb34b699e
@@ -87,6 +87,19 @@ export interface NodeInfoResponse {
|
||||
|
||||
export const getNodeInfo = () => get<NodeInfoResponse>("/api/node_info", {});
|
||||
|
||||
export interface RayletInfoResponse {
|
||||
[ip: string]: {
|
||||
extraInfo?: string;
|
||||
workersStats: {
|
||||
isDriver?: boolean;
|
||||
pid: number;
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
export const getRayletInfo = () =>
|
||||
get<RayletInfoResponse>("/api/raylet_info", {});
|
||||
|
||||
export interface ErrorsResponse {
|
||||
[pid: string]: Array<{
|
||||
message: string;
|
||||
|
||||
@@ -9,7 +9,7 @@ import TableRow from "@material-ui/core/TableRow";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { getNodeInfo } from "../../../api";
|
||||
import { getNodeInfo, getRayletInfo } from "../../../api";
|
||||
import { StoreState } from "../../../store";
|
||||
import { dashboardActions } from "../state";
|
||||
import LastUpdated from "./LastUpdated";
|
||||
@@ -38,7 +38,8 @@ const styles = (theme: Theme) =>
|
||||
});
|
||||
|
||||
const mapStateToProps = (state: StoreState) => ({
|
||||
nodeInfo: state.dashboard.nodeInfo
|
||||
nodeInfo: state.dashboard.nodeInfo,
|
||||
rayletInfo: state.dashboard.rayletInfo
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dashboardActions;
|
||||
@@ -50,8 +51,11 @@ class NodeInfo extends React.Component<
|
||||
> {
|
||||
refreshNodeInfo = async () => {
|
||||
try {
|
||||
const nodeInfo = await getNodeInfo();
|
||||
this.props.setNodeInfo(nodeInfo);
|
||||
const [nodeInfo, rayletInfo] = await Promise.all([
|
||||
getNodeInfo(),
|
||||
getRayletInfo()
|
||||
]);
|
||||
this.props.setNodeInfoAndRayletInfo({ nodeInfo, rayletInfo });
|
||||
this.props.setError(null);
|
||||
} catch (error) {
|
||||
this.props.setError(error.toString());
|
||||
@@ -65,9 +69,9 @@ class NodeInfo extends React.Component<
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes, nodeInfo } = this.props;
|
||||
const { classes, nodeInfo, rayletInfo } = this.props;
|
||||
|
||||
if (nodeInfo === null) {
|
||||
if (nodeInfo === null || rayletInfo === null) {
|
||||
return (
|
||||
<Typography className={classes.root} color="textSecondary">
|
||||
Loading...
|
||||
@@ -144,6 +148,7 @@ class NodeInfo extends React.Component<
|
||||
<NodeRowGroup
|
||||
key={client.ip}
|
||||
node={client}
|
||||
raylet={client.ip in rayletInfo ? rayletInfo[client.ip] : null}
|
||||
logCounts={logCounts[client.ip]}
|
||||
errorCounts={errorCounts[client.ip]}
|
||||
initialExpanded={nodeInfo.clients.length <= 4}
|
||||
|
||||
@@ -7,7 +7,7 @@ import AddIcon from "@material-ui/icons/Add";
|
||||
import RemoveIcon from "@material-ui/icons/Remove";
|
||||
import classNames from "classnames";
|
||||
import React from "react";
|
||||
import { NodeInfoResponse } from "../../../api";
|
||||
import { NodeInfoResponse, RayletInfoResponse } from "../../../api";
|
||||
import { NodeCPU, WorkerCPU } from "./features/CPU";
|
||||
import { NodeDisk, WorkerDisk } from "./features/Disk";
|
||||
import { makeNodeErrors, makeWorkerErrors } from "./features/Errors";
|
||||
@@ -35,6 +35,10 @@ const styles = (theme: Theme) =>
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: "1.5em",
|
||||
verticalAlign: "middle"
|
||||
},
|
||||
extraInfo: {
|
||||
fontFamily: "SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace",
|
||||
whiteSpace: "pre-wrap"
|
||||
}
|
||||
});
|
||||
|
||||
@@ -43,6 +47,7 @@ type Node = ArrayType<NodeInfoResponse["clients"]>;
|
||||
|
||||
interface Props {
|
||||
node: Node;
|
||||
raylet: RayletInfoResponse[keyof RayletInfoResponse] | null;
|
||||
logCounts: {
|
||||
perWorker: { [pid: string]: number };
|
||||
total: number;
|
||||
@@ -73,7 +78,7 @@ class NodeRowGroup extends React.Component<
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes, node, logCounts, errorCounts } = this.props;
|
||||
const { classes, node, raylet, logCounts, errorCounts } = this.props;
|
||||
const { expanded } = this.state;
|
||||
|
||||
const features = [
|
||||
@@ -114,17 +119,31 @@ class NodeRowGroup extends React.Component<
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
{expanded &&
|
||||
node.workers.map((worker, index: number) => (
|
||||
<TableRow hover key={index}>
|
||||
<TableCell className={classes.cell} />
|
||||
{features.map(({ WorkerFeature }, index) => (
|
||||
<TableCell className={classes.cell} key={index}>
|
||||
<WorkerFeature node={node} worker={worker} />
|
||||
{expanded && (
|
||||
<React.Fragment>
|
||||
{raylet !== null && raylet.extraInfo !== undefined && (
|
||||
<TableRow hover>
|
||||
<TableCell className={classes.cell} />
|
||||
<TableCell
|
||||
className={classNames(classes.cell, classes.extraInfo)}
|
||||
colSpan={features.length}
|
||||
>
|
||||
{raylet.extraInfo}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableRow>
|
||||
)}
|
||||
{node.workers.map((worker, index: number) => (
|
||||
<TableRow hover key={index}>
|
||||
<TableCell className={classes.cell} />
|
||||
{features.map(({ WorkerFeature }, index) => (
|
||||
<TableCell className={classes.cell} key={index}>
|
||||
<WorkerFeature node={node} worker={worker} />
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</React.Fragment>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { NodeInfoResponse, RayConfigResponse } from "../../api";
|
||||
import {
|
||||
NodeInfoResponse,
|
||||
RayConfigResponse,
|
||||
RayletInfoResponse
|
||||
} from "../../api";
|
||||
|
||||
const name = "dashboard";
|
||||
|
||||
interface State {
|
||||
rayConfig: RayConfigResponse | null;
|
||||
nodeInfo: NodeInfoResponse | null;
|
||||
rayletInfo: RayletInfoResponse | null;
|
||||
lastUpdatedAt: number | null;
|
||||
error: string | null;
|
||||
}
|
||||
@@ -13,6 +18,7 @@ interface State {
|
||||
const initialState: State = {
|
||||
rayConfig: null,
|
||||
nodeInfo: null,
|
||||
rayletInfo: null,
|
||||
lastUpdatedAt: null,
|
||||
error: null
|
||||
};
|
||||
@@ -24,8 +30,15 @@ const slice = createSlice({
|
||||
setRayConfig: (state, action: PayloadAction<RayConfigResponse>) => {
|
||||
state.rayConfig = action.payload;
|
||||
},
|
||||
setNodeInfo: (state, action: PayloadAction<NodeInfoResponse>) => {
|
||||
state.nodeInfo = action.payload;
|
||||
setNodeInfoAndRayletInfo: (
|
||||
state,
|
||||
action: PayloadAction<{
|
||||
nodeInfo: NodeInfoResponse;
|
||||
rayletInfo: RayletInfoResponse;
|
||||
}>
|
||||
) => {
|
||||
state.nodeInfo = action.payload.nodeInfo;
|
||||
state.rayletInfo = action.payload.rayletInfo;
|
||||
state.lastUpdatedAt = Date.now();
|
||||
},
|
||||
setError: (state, action: PayloadAction<string | null>) => {
|
||||
|
||||
Reference in New Issue
Block a user