blob: 5edc0532dbd196875627554c99b6d82b944c6548 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
Stack,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography
} from "@mui/material";
import {
Accordion,
AccordionDetails,
AccordionSummary
} from "@components/muiComponents";
import { numberFormatWithComma } from "@utils/Helper";
import { useMemo, useState } from "react";
import { useAppSelector } from "@hooks/reducerHook";
import { isEmpty } from "@utils/Utils";
import { stats } from "@utils/Enum";
import { getStatsValue } from "./Statistics";
const ServerStats = ({ selectedValue, currentMetricsData }: any) => {
const { metricsData }: any = useAppSelector((state: any) => state.metrics);
const { label } = selectedValue;
const { metrics } = currentMetricsData;
const selectedMetricsData = label == "Current" ? metricsData : metrics;
const { general } = selectedMetricsData?.data || {};
let statsData = general?.stats || {};
const generateStatusData = (stateObject: any) => {
let stats: any = {};
for (let key in stateObject) {
let keys: string[] = key.split(":");
key = keys[0];
let subKey = keys[1];
if (stats[key]) {
stats[key][subKey] = stateObject[`${key}:${subKey}`];
} else {
stats[key] = {};
stats[key][subKey] = stateObject[`${key}:${subKey}`];
}
}
return stats;
};
let serverData = generateStatusData(statsData);
const offsetTableColumn = (obj: {
[x: string]: any;
hasOwnProperty: (arg0: string) => any;
}) => {
var returnObj = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
returnObj.push({ label: key, dataValue: obj[key] });
}
}
return returnObj;
};
let offSetTabelData = offsetTableColumn(
serverData?.Notification?.topicDetails
);
const [topicSort, setTopicSort] = useState<{
key: string;
order: "asc" | "desc";
}>({ key: "label", order: "asc" });
const handleSort = (key: string) => {
setTopicSort((prev) => {
const nextOrder = prev.key === key && prev.order === "asc" ? "desc" : "asc";
return { key, order: nextOrder };
});
};
const sortedOffsetTableData = useMemo(() => {
const list = Array.isArray(offSetTabelData) ? [...offSetTabelData] : [];
const { key, order } = topicSort;
const dir = order === "asc" ? 1 : -1;
return list.sort((a: any, b: any) => {
if (key === "label") {
const av = String(a.label || "").toLowerCase();
const bv = String(b.label || "").toLowerCase();
if (av < bv) return -1 * dir;
if (av > bv) return 1 * dir;
return 0;
}
const aTopic = serverData?.Notification?.topicDetails?.[a.label] || {};
const bTopic = serverData?.Notification?.topicDetails?.[b.label] || {};
const av = Number(aTopic?.[key] ?? 0);
const bv = Number(bTopic?.[key] ?? 0);
if (av < bv) return -1 * dir;
if (av > bv) return 1 * dir;
return 0;
});
}, [JSON.stringify(offSetTabelData), JSON.stringify(serverData?.Notification?.topicDetails), topicSort]);
let notificationTableHeader = [
"Count",
"Avg",
"Time (ms)",
"Creates",
"Updates",
"Deletes"
// "Failed"
];
let topciOffsetTableHeader = [
"offsetStart",
"offsetCurrent",
"processedMessageCount",
"failedMessageCount",
"lastMessageProcessedTime",
"avgProcessingTime"
];
let tableCol = [
{
label:
"Total from " +
getStatsValue({
value: serverData?.Server?.["startTimeStamp"],
type: stats?.Server?.["startTimeStamp"]
}),
key: "total"
},
{
label:
"Current Hour from " +
getStatsValue({
value: serverData?.Notification?.["currentHourStartTime"],
type: stats.Notification?.["currentHourStartTime"]
}),
key: "currentHour"
},
{ label: "Previous Hour", key: "previousHour" },
{
label:
"Current Day from " +
getStatsValue({
value: serverData?.Notification?.["currentDayStartTime"],
type: stats?.Notification?.["currentDayStartTime"]
}),
key: "currentDay"
},
{ label: "Previous Day", key: "previousDay" }
];
let tableHeader = [
"count",
"AvgTime",
"EntityCreates",
"EntityUpdates",
"EntityDeletes",
"Failed"
];
const getTmplValue = (
argument: { label?: string; key: any },
args: string
) => {
let pickValueFrom = argument.key.concat(args);
if (argument.key == "total" && args == "EntityCreates") {
pickValueFrom = "totalCreates";
} else if (argument.key == "total" && args == "EntityUpdates") {
pickValueFrom = "totalUpdates";
} else if (argument.key == "total" && args == "EntityDeletes") {
pickValueFrom = "totalDeletes";
} else if (args == "count") {
pickValueFrom = argument.key;
}
let returnVal = serverData?.Notification?.[pickValueFrom];
return returnVal ? numberFormatWithComma(returnVal) : 0;
};
return (
<Accordion
sx={{
width: "100%",
borderBottom: "1px solid rgba(0, 0, 0, 0.12) !important",
boxShadow: "none"
}}
defaultExpanded
>
<AccordionSummary
aria-controls="technical-properties-content"
id="technical-properties-header"
>
<Stack direction="row" alignItems="center" flex="1">
<div className="properties-panel-name">
<Typography fontWeight="600" className="text-color-green">
Server Statistics
</Typography>
</div>
</Stack>
</AccordionSummary>
<AccordionDetails>
<Stack gap={"2rem"}>
<TableContainer>
<Table className="classificationTable" size="small">
<TableHead>
<TableRow>
<TableCell>
<Typography fontWeight="600">Server Details</Typography>
</TableCell>
<TableCell align="right">
<Typography fontWeight="600"></Typography>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{isEmpty(serverData?.Server) ? (
<TableRow className="empty text-center">
<TableCell colSpan={2} align="center">
<span>No records found!</span>
</TableCell>
</TableRow>
) : (
Object.entries(serverData?.Server)?.map(
([key, value]: any) => (
<TableRow key={key}>
<TableCell>{key}</TableCell>
<TableCell align="right">
{getStatsValue({
value: value,
type: {
...stats.Server,
...stats.ConnectionStatus,
...stats.generalData
}[key]
})}
</TableCell>
</TableRow>
)
)
)}
</TableBody>
</Table>
</TableContainer>
<Stack gap={"2rem"}>
<Typography fontWeight="600">Notification Table</Typography>
<TableContainer>
<Table className="classificationTable" size="small">
<TableHead>
<TableRow>
<TableCell align="left" onClick={() => handleSort("label")} sx={{ cursor: "pointer" }}>
<Typography fontWeight="600">
Kafka Topic-Partition{topicSort.key === "label" ? (topicSort.order === "asc" ? " ▲" : " ▼") : ""}
</Typography>
</TableCell>
{topciOffsetTableHeader.map((key) => (
<TableCell key={key} align="left" onClick={() => handleSort(key)} sx={{ cursor: "pointer" }}>
<Typography fontWeight="600">
{(
{
offsetStart: "Start Offset",
offsetCurrent: "Current Offset",
processedMessageCount: "Processed",
failedMessageCount: "Failed",
lastMessageProcessedTime: "Last Message Processed Time",
avgProcessingTime: "Average message processing time"
} as any
)[key]}
{topicSort.key === key ? (topicSort.order === "asc" ? " ▲" : " ▼") : ""}
</Typography>
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{isEmpty(offSetTabelData) ? (
<TableRow className="empty text-center">
<TableCell colSpan={2} align="center">
<span>No records found!</span>
</TableCell>
</TableRow>
) : (
sortedOffsetTableData?.map((obj, index) => (
<TableRow key={index}>
<TableCell>{obj.label}</TableCell>
{topciOffsetTableHeader.map((header) => {
let returnVal =
serverData?.Notification?.topicDetails?.[obj.label]?.[header];
const typeForKey =
header === "avgProcessingTime"
? stats.Notification["lastMessageProcessedTime"]
: stats.Notification[header];
return (
<TableCell align="left">
{returnVal
? getStatsValue({
value: returnVal,
type: typeForKey
})
: 0}
</TableCell>
);
})}
</TableRow>
))
)}
</TableBody>
</Table>
</TableContainer>
<TableContainer>
<Table className="classificationTable" size="small">
<TableHead>
<TableRow>
<TableCell>
<Typography fontWeight="600">Period</Typography>
</TableCell>
{notificationTableHeader.map((header) => {
return (
<>
<TableCell align="right">
<Typography fontWeight="600">{header}</Typography>
</TableCell>
</>
);
})}
</TableRow>
</TableHead>
<TableBody>
{isEmpty(tableCol) ? (
<TableRow className="empty text-center">
<TableCell colSpan={2} align="center">
<span>No records found!</span>
</TableCell>
</TableRow>
) : (
tableCol?.map((obj, index) => (
<TableRow key={index}>
<TableCell>{obj.label}</TableCell>
{tableHeader.map((header) => (
<TableCell align="right">
{getTmplValue(obj, header)}
</TableCell>
))}{" "}
</TableRow>
))
)}
</TableBody>
</Table>
</TableContainer>
</Stack>
</Stack>
</AccordionDetails>
</Accordion>
);
};
export default ServerStats;