add docker chart tooltips
This commit is contained in:
1 parent
53f5b61e8e
commit
b75f895a1f
5 files changed
+90
-8
No files matched your search
@@ -1,15 +1,58 @@
|
||||
import { BaseChart } from "@/Components/design-elements";
|
||||
import { Area, AreaChart, CartesianGrid, ResponsiveContainer } from "recharts";
|
||||
import { BaseChart, BaseBox } from "@/Components/design-elements";
|
||||
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
// Types
|
||||
import type { DockerContainerStats } from "@/Types/Monitor";
|
||||
import type { TooltipProps } from "recharts";
|
||||
import type { NameType, ValueType } from "recharts/types/component/DefaultTooltipContent";
|
||||
import type { Theme } from "@mui/material/styles";
|
||||
import type { RootState } from "@/Types/state";
|
||||
|
||||
// Hooks
|
||||
import { useTheme } from "@mui/material";
|
||||
import { Fragment, useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
// Utils
|
||||
import { createGradient } from "@/Components/monitors/charts/ChartUtils";
|
||||
import { tooltipDateFormatLookup, formatDateWithTz } from "@/Utils/TimeUtils";
|
||||
import type { DateRange } from "@/Types/Query";
|
||||
|
||||
type DockerHistogramToolTipProps = TooltipProps<ValueType, NameType> & {
|
||||
dataKey: string;
|
||||
range: string;
|
||||
theme: Theme;
|
||||
uiTimezone: string;
|
||||
valueFormatter: (value: number) => string;
|
||||
labelKey: string;
|
||||
};
|
||||
|
||||
const DockerHistogramToolTip = ({
|
||||
dataKey,
|
||||
active,
|
||||
payload,
|
||||
range,
|
||||
theme,
|
||||
uiTimezone,
|
||||
valueFormatter,
|
||||
labelKey,
|
||||
}: DockerHistogramToolTipProps) => {
|
||||
const { t } = useTranslation();
|
||||
if (!payload) return null;
|
||||
if (!active) return null;
|
||||
const format = tooltipDateFormatLookup(range);
|
||||
const ts = payload[0].payload?._id ?? null;
|
||||
const dataPoint = payload[0].payload?.[dataKey] ?? null;
|
||||
|
||||
return (
|
||||
<BaseBox sx={{ py: theme.spacing(2), px: theme.spacing(4) }}>
|
||||
<Typography>{formatDateWithTz(ts, format, uiTimezone)}</Typography>
|
||||
<Typography>{t(labelKey, { value: valueFormatter(dataPoint) })}</Typography>
|
||||
</BaseBox>
|
||||
);
|
||||
};
|
||||
interface HistogramDockerContainerProps {
|
||||
title: string;
|
||||
rightTitle: string;
|
||||
@@ -17,6 +60,9 @@ interface HistogramDockerContainerProps {
|
||||
dataKey: string;
|
||||
strokeColor: string;
|
||||
gradientStartColor: string;
|
||||
range: DateRange;
|
||||
formatter: (value: number) => string;
|
||||
labelKey: string;
|
||||
}
|
||||
|
||||
export const HistogramDockerContainer = ({
|
||||
@@ -26,11 +72,14 @@ export const HistogramDockerContainer = ({
|
||||
dataKey,
|
||||
strokeColor,
|
||||
gradientStartColor,
|
||||
range,
|
||||
formatter,
|
||||
labelKey,
|
||||
}: HistogramDockerContainerProps) => {
|
||||
const uniqueId = useId();
|
||||
const theme = useTheme();
|
||||
const gradientId = `gradient-${uniqueId}`;
|
||||
|
||||
const uiTimezone = useSelector((state: RootState) => state.ui.timezone);
|
||||
return (
|
||||
<BaseChart
|
||||
icon="null"
|
||||
@@ -56,6 +105,19 @@ export const HistogramDockerContainer = ({
|
||||
endColor: "transparent",
|
||||
direction: "vertical",
|
||||
})}
|
||||
<Tooltip
|
||||
content={(props) => (
|
||||
<DockerHistogramToolTip
|
||||
{...props}
|
||||
range={range}
|
||||
theme={theme}
|
||||
uiTimezone={uiTimezone}
|
||||
dataKey={dataKey}
|
||||
valueFormatter={formatter}
|
||||
labelKey={labelKey}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Area
|
||||
dataKey={dataKey}
|
||||
type="monotone"
|
||||
|
||||
Whitespace-only changes.
@@ -17,6 +17,7 @@ import { formatPercentage } from "@/Utils/FormatUtils";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import { BaseBox } from "@/Components/design-elements";
|
||||
import { dedupeDockerPorts, getDockerMountLabel } from "@/Utils/MonitorUtils";
|
||||
import type { DateRange } from "@/Types/Query";
|
||||
|
||||
const getChartConfigs = (theme: Theme, t: TFunction, stats: DockerContainerStats) => [
|
||||
{
|
||||
@@ -24,20 +25,29 @@ const getChartConfigs = (theme: Theme, t: TFunction, stats: DockerContainerStats
|
||||
key: "avgCpuPct",
|
||||
color: theme.palette.success.main,
|
||||
rightTitle: formatPercentage(stats?.latest?.container.cpuPct || 0),
|
||||
formatter: formatPercentage,
|
||||
labelKey: "common.charts.histogram.avgCpuUsage",
|
||||
},
|
||||
{
|
||||
title: t("common.charts.labels.memoryUsage"),
|
||||
key: "avgMemoryUsedBytes",
|
||||
color: theme.palette.primary.main,
|
||||
rightTitle: prettyBytes(stats?.latest?.container.memoryUsedBytes || 0),
|
||||
formatter: prettyBytes,
|
||||
labelKey: "common.charts.histogram.avgMemoryUsage",
|
||||
},
|
||||
];
|
||||
|
||||
export const TabOverview = ({ stats }: { stats: DockerContainerStats }) => {
|
||||
export const TabOverview = ({
|
||||
stats,
|
||||
range,
|
||||
}: {
|
||||
stats: DockerContainerStats;
|
||||
range: DateRange;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const isSmall = useMediaQuery(theme.breakpoints.down("md"));
|
||||
|
||||
const { ports, mounts } = stats?.latest?.container ?? {};
|
||||
const dedupedPorts = dedupeDockerPorts(ports ?? []);
|
||||
return (
|
||||
@@ -58,6 +68,9 @@ export const TabOverview = ({ stats }: { stats: DockerContainerStats }) => {
|
||||
dataKey={config.key}
|
||||
strokeColor={config.color}
|
||||
gradientStartColor={config.color}
|
||||
range={range}
|
||||
formatter={config.formatter}
|
||||
labelKey={config.labelKey}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ const TAB_MAP = {
|
||||
logs: 1,
|
||||
} as const;
|
||||
|
||||
const DockerDetailsPage = ({ open = "logs" }: DockerContainerDetailsProps) => {
|
||||
const DockerDetailsPage = ({ open = "overview" }: DockerContainerDetailsProps) => {
|
||||
const [activeTab, setActiveTab] = useState<number>(TAB_MAP[open]);
|
||||
const [dateRange, setDateRange] = useState<DateRange>("recent");
|
||||
const { monitorId, containerName } = useParams<{
|
||||
@@ -69,7 +69,12 @@ const DockerDetailsPage = ({ open = "logs" }: DockerContainerDetailsProps) => {
|
||||
<Tab label={t("pages.docker.container.tabs.overview")} />
|
||||
<Tab label={t("pages.docker.container.tabs.logs")} />
|
||||
</Tabs>
|
||||
{activeTab === 0 && <TabOverview stats={stats} />}
|
||||
{activeTab === 0 && (
|
||||
<TabOverview
|
||||
stats={stats}
|
||||
range={dateRange}
|
||||
/>
|
||||
)}
|
||||
{activeTab === 1 && (
|
||||
<TabLogs
|
||||
monitorId={monitorId}
|
||||
|
||||
@@ -80,7 +80,9 @@
|
||||
"avg": "Avg: {{value}}",
|
||||
"max": "Max: {{value}}",
|
||||
"responseTime": "Response time: {{value}}",
|
||||
"total": "Total: {{value}}"
|
||||
"total": "Total: {{value}}",
|
||||
"avgCpuUsage": "Average CPU usage: {{value}}",
|
||||
"avgMemoryUsage": "Average memory usage: {{value}}"
|
||||
},
|
||||
"phases": {
|
||||
"dns": "DNS",
|
||||
|
||||
Reference in new issue
Block a user