diff --git a/BUILD.bazel b/BUILD.bazel index 7f0884f348aa2..88088be4788d9 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -2735,6 +2735,7 @@ pyx_library( "//:global_state_accessor_lib", "//:ray_util", "//:raylet_lib", + "//:redis_client", "//:src/ray/ray_exported_symbols.lds", "//:src/ray/ray_version_script.lds", "//:stats_lib", diff --git a/ci/env/install-core-prerelease-dependencies.sh b/ci/env/install-core-prerelease-dependencies.sh index 5efa3ddfe3bff..3182878f9f99f 100755 --- a/ci/env/install-core-prerelease-dependencies.sh +++ b/ci/env/install-core-prerelease-dependencies.sh @@ -3,7 +3,8 @@ set -e # install all unbounded dependencies in setup.py for ray core -for dependency in attrs jsonschema aiosignal frozenlist requests grpcio protobuf +# TOOD(scv119) reenable grpcio once https://github.com/grpc/grpc/issues/31885 is fixed. +for dependency in attrs jsonschema aiosignal frozenlist requests protobuf do python -m pip install -U --pre --upgrade-strategy=eager $dependency done diff --git a/ci/pipeline/determine_tests_to_run.py b/ci/pipeline/determine_tests_to_run.py index 635a28d6694a0..7d10e80ad09f8 100644 --- a/ci/pipeline/determine_tests_to_run.py +++ b/ci/pipeline/determine_tests_to_run.py @@ -183,6 +183,7 @@ def get_commit_range(): RAY_CI_SERVE_AFFECTED = 1 RAY_CI_LINUX_WHEELS_AFFECTED = 1 RAY_CI_MACOS_WHEELS_AFFECTED = 1 + RAY_CI_JAVA_AFFECTED = 1 elif changed_file.startswith("python/ray/dashboard"): RAY_CI_DASHBOARD_AFFECTED = 1 # https://github.com/ray-project/ray/pull/15981 diff --git a/dashboard/client/src/App.tsx b/dashboard/client/src/App.tsx index c48be1456e9f8..302a9afe3985c 100644 --- a/dashboard/client/src/App.tsx +++ b/dashboard/client/src/App.tsx @@ -8,6 +8,7 @@ import Events from "./pages/event/Events"; import Loading from "./pages/exception/Loading"; import JobList, { NewIAJobsPage } from "./pages/job"; import { JobDetailChartsPage } from "./pages/job/JobDetail"; +import { JobDetailActorsPage } from "./pages/job/JobDetailActorPage"; import { JobDetailInfoPage } from "./pages/job/JobDetailInfoPage"; import { JobDetailLayout } from "./pages/job/JobDetailLayout"; import { DEFAULT_VALUE, MainNavContext } from "./pages/layout/mainNavContext"; @@ -205,11 +206,19 @@ const App = () => { - + } path="" /> + + + + } + path="actors" + /> } path="logs"> diff --git a/dashboard/client/src/common/CollapsibleSection.tsx b/dashboard/client/src/common/CollapsibleSection.tsx index 879ce6bf692c0..2f42d82ff7d6e 100644 --- a/dashboard/client/src/common/CollapsibleSection.tsx +++ b/dashboard/client/src/common/CollapsibleSection.tsx @@ -1,6 +1,8 @@ import { createStyles, makeStyles, Typography } from "@material-ui/core"; -import React, { PropsWithChildren, useState } from "react"; -import { RiArrowDownSLine, RiArrowUpSLine } from "react-icons/ri"; +import classNames from "classnames"; +import React, { PropsWithChildren, useEffect, useState } from "react"; +import { RiArrowDownSLine, RiArrowRightSLine } from "react-icons/ri"; +import { ClassNameProps } from "./props"; const useStyles = makeStyles((theme) => createStyles({ @@ -10,6 +12,7 @@ const useStyles = makeStyles((theme) => flexWrap: "nowrap", alignItems: "center", fontWeight: 500, + cursor: "pointer", }, icon: { marginRight: theme.spacing(1), @@ -17,25 +20,42 @@ const useStyles = makeStyles((theme) => height: 24, }, body: { - marginTop: theme.spacing(3), + marginTop: theme.spacing(1), + }, + bodyHidden: { + display: "none", }, }), ); -type CollapsibleSectionProps = PropsWithChildren<{ - title: string; - startExpanded?: boolean; - className?: string; -}>; +type CollapsibleSectionProps = PropsWithChildren< + { + title: string; + startExpanded?: boolean; + /** + * An optimization to not avoid re-rendering the contents of the collapsible section. + * When enabled, we will keep the content around when collapsing but hide it via css. + */ + keepRendered?: boolean; + } & ClassNameProps +>; export const CollapsibleSection = ({ title, startExpanded = false, className, children, + keepRendered, }: CollapsibleSectionProps) => { const classes = useStyles(); const [expanded, setExpanded] = useState(startExpanded); + const [rendered, setRendered] = useState(expanded); + + useEffect(() => { + if (expanded) { + setRendered(true); + } + }, [expanded]); const handleExpandClick = () => { setExpanded(!expanded); @@ -51,11 +71,19 @@ export const CollapsibleSection = ({ {expanded ? ( ) : ( - + )} {title} - {expanded &&
{children}
} + {(expanded || (keepRendered && rendered)) && ( +
+ {children} +
+ )} ); }; diff --git a/dashboard/client/src/components/TaskTable.tsx b/dashboard/client/src/components/TaskTable.tsx index e14055fa68a0c..c833cb1a2ae0b 100644 --- a/dashboard/client/src/components/TaskTable.tsx +++ b/dashboard/client/src/components/TaskTable.tsx @@ -13,9 +13,11 @@ import { import Autocomplete from "@material-ui/lab/Autocomplete"; import Pagination from "@material-ui/lab/Pagination"; import React, { useState } from "react"; +import { DurationText } from "../common/DurationText"; import rowStyles from "../common/RowStyles"; import { Task } from "../type/task"; import { useFilter } from "../util/hook"; +import StateCounter from "./StatesCounter"; import { StatusChip } from "./StatusChip"; const TaskTable = ({ @@ -36,7 +38,8 @@ const TaskTable = ({ { label: "ID" }, { label: "Name" }, { label: "Job Id" }, - { label: "Scheduling State" }, + { label: "State" }, + { label: "Duration" }, { label: "Function or Class Name" }, { label: "Node Id" }, { label: "Actor_id" }, @@ -59,12 +62,12 @@ const TaskTable = ({ /> e.scheduling_state)))} + options={Array.from(new Set(tasks.map((e) => e.state)))} onInputChange={(_: any, value: string) => { - changeFilter("scheduling_state", value.trim()); + changeFilter("state", value.trim()); }} renderInput={(params: TextFieldProps) => ( - + )} /> +
+ +
@@ -140,12 +146,15 @@ const TaskTable = ({ task_id, name, job_id, - scheduling_state, + state, func_or_class_name, node_id, actor_id, type, required_resources, + events, + start_time_ms, + end_time_ms, }) => ( @@ -161,7 +170,17 @@ const TaskTable = ({ {name ? name : "-"} {job_id} - + + + + {start_time_ms && start_time_ms > 0 ? ( + + ) : ( + "-" + )} {func_or_class_name} {node_id ? node_id : "-"} diff --git a/dashboard/client/src/pages/job/JobDetail.tsx b/dashboard/client/src/pages/job/JobDetail.tsx index cddca7c6761c9..8f0b6cdf1c21d 100644 --- a/dashboard/client/src/pages/job/JobDetail.tsx +++ b/dashboard/client/src/pages/job/JobDetail.tsx @@ -25,7 +25,13 @@ const useStyle = makeStyles((theme) => ({ }, })); -export const JobDetailChartsPage = () => { +type JobDetailChartsPageProps = { + newIA?: boolean; +}; + +export const JobDetailChartsPage = ({ + newIA = false, +}: JobDetailChartsPageProps) => { const classes = useStyle(); const { job, msg, params } = useJobDetail(); const jobId = params.id; diff --git a/dashboard/client/src/pages/job/JobDetailActorPage.tsx b/dashboard/client/src/pages/job/JobDetailActorPage.tsx new file mode 100644 index 0000000000000..c0fa8735850cb --- /dev/null +++ b/dashboard/client/src/pages/job/JobDetailActorPage.tsx @@ -0,0 +1,37 @@ +import { makeStyles } from "@material-ui/core"; +import React from "react"; + +import TitleCard from "../../components/TitleCard"; +import ActorList from "../actor/ActorList"; +import { MainNavPageInfo } from "../layout/mainNavContext"; +import { useJobDetail } from "./hook/useJobDetail"; + +const useStyle = makeStyles((theme) => ({ + root: { + padding: theme.spacing(2), + }, +})); + +export const JobDetailActorsPage = () => { + const classes = useStyle(); + const { job, params } = useJobDetail(); + + const pageInfo = job + ? { + title: "Actors", + id: "actors", + path: job.job_id ? `/new/jobs/${job.job_id}/actors` : undefined, + } + : { + title: "Actors", + id: "actors", + path: undefined, + }; + + return ( +
+ + {} +
+ ); +}; diff --git a/dashboard/client/src/pages/job/JobDetailLayout.tsx b/dashboard/client/src/pages/job/JobDetailLayout.tsx index 3c65ccc6b42a6..f87915e451308 100644 --- a/dashboard/client/src/pages/job/JobDetailLayout.tsx +++ b/dashboard/client/src/pages/job/JobDetailLayout.tsx @@ -1,5 +1,9 @@ import React from "react"; -import { RiInformationLine, RiLineChartLine } from "react-icons/ri"; +import { + RiGradienterLine, + RiInformationLine, + RiLineChartLine, +} from "react-icons/ri"; import { MainNavPageInfo } from "../layout/mainNavContext"; import { SideTabLayout, SideTabRouteLink } from "../layout/SideTabLayout"; import { useJobDetail } from "./hook/useJobDetail"; @@ -29,6 +33,12 @@ export const JobDetailLayout = () => { title="Charts" Icon={RiLineChartLine} /> + ); }; diff --git a/dashboard/client/src/pages/layout/MainNavLayout.tsx b/dashboard/client/src/pages/layout/MainNavLayout.tsx index 6a001a29eb3b7..85dabc6d97a35 100644 --- a/dashboard/client/src/pages/layout/MainNavLayout.tsx +++ b/dashboard/client/src/pages/layout/MainNavLayout.tsx @@ -88,13 +88,14 @@ const useMainNavBarStyles = makeStyles((theme) => boxShadow: "0px 1px 0px #D2DCE6", }, logo: { - width: 60, display: "flex", justifyContent: "center", + marginLeft: theme.spacing(2), + marginRight: theme.spacing(3), }, navItem: { - marginRight: theme.spacing(2), - fontSize: "1em", + marginRight: theme.spacing(6), + fontSize: "1rem", fontWeight: 500, color: "black", textDecoration: "none", @@ -211,15 +212,21 @@ const MainNavBreadcrumbs = () => { ); if (index === 0) { return ( - + {linkOrText} ); } else { return ( - {"/"} - + + {"/"} + + {linkOrText} diff --git a/dashboard/client/src/pages/log/Logs.tsx b/dashboard/client/src/pages/log/Logs.tsx index 6501a0c8b7786..7a36a1e23c64c 100644 --- a/dashboard/client/src/pages/log/Logs.tsx +++ b/dashboard/client/src/pages/log/Logs.tsx @@ -126,7 +126,7 @@ const Logs = (props: LogsProps) => { setEnd, } = useLogs(props); const { newIA } = props; - let href = newIA ? "#/new/log/" : "#/log/"; + let href = newIA ? "#/new/logs/" : "#/log/"; if (origin) { if (path) { diff --git a/dashboard/client/src/pages/metrics/Metrics.tsx b/dashboard/client/src/pages/metrics/Metrics.tsx index 554990b3250ef..8610f6961622e 100644 --- a/dashboard/client/src/pages/metrics/Metrics.tsx +++ b/dashboard/client/src/pages/metrics/Metrics.tsx @@ -20,9 +20,21 @@ const useStyles = makeStyles((theme) => display: "flex", flexDirection: "row", flexWrap: "wrap", + gap: theme.spacing(3), + }, + chart: { + flex: "1 0 448px", + maxWidth: "100%", + height: 300, + overflow: "hidden", + [theme.breakpoints.up("md")]: { + // Calculate max width based on 1/3 of the total width minus padding between cards + maxWidth: `calc((100% - ${theme.spacing(3)}px * 2) / 3)`, + }, }, grafanaEmbed: { - margin: theme.spacing(1), + width: "100%", + height: "100%", }, topBar: { position: "sticky", @@ -213,15 +225,15 @@ export const Metrics = () => {
{METRICS_CONFIG.map(({ title, path }) => ( -