mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-09-27 14:02:38 +02:00
Performance tab (no graphs yet)
This commit is contained in:
parent
d39c377756
commit
5bd882036c
@ -104,9 +104,9 @@ public class PerformanceJSONCreator implements ServerTabJSONCreator<Map<String,
|
||||
numbers.put("server_downtime_7d", timeAmount.apply(tpsDataWeek.serverDownTime()));
|
||||
numbers.put("server_downtime_24h", timeAmount.apply(tpsDataDay.serverDownTime()));
|
||||
|
||||
numbers.put("players_30d", tpsDataMonth.averagePlayers());
|
||||
numbers.put("players_7d", tpsDataWeek.averagePlayers());
|
||||
numbers.put("players_24h", tpsDataDay.averagePlayers());
|
||||
numbers.put("players_30d", format(tpsDataMonth.averagePlayers()));
|
||||
numbers.put("players_7d", format(tpsDataWeek.averagePlayers()));
|
||||
numbers.put("players_24h", format(tpsDataDay.averagePlayers()));
|
||||
numbers.put("tps_30d", format(tpsDataMonth.averageTPS()));
|
||||
numbers.put("tps_7d", format(tpsDataWeek.averageTPS()));
|
||||
numbers.put("tps_24h", format(tpsDataDay.averageTPS()));
|
||||
|
@ -93,6 +93,9 @@ public enum HtmlLang implements Lang {
|
||||
TITLE_30_DAYS("html.label.thirtyDays", "30 days"),
|
||||
TITLE_AS_NUMBERS("html.label.asNumbers", "as Numbers"),
|
||||
LABEL_AVG_TPS("html.label.averageTps", "Average TPS"),
|
||||
LABEL_AVG_PLAYERS("html.label.averagePlayers", "Average Players"),
|
||||
LABEL_AVG_CPU("html.label.averageCpuUsage", "Average CPU Usage"),
|
||||
LABEL_AVG_RAM("html.label.averageRamUsage", "Average RAM Usage"),
|
||||
LABEL_AVG_ENTITIES("html.label.averageEntities", "Average Entities"),
|
||||
LABEL_AVG_CHUNKS("html.label.averageChunks", "Average Chunks"),
|
||||
LABEL_LOW_TPS("html.label.lowTpsSpikes", "Low TPS Spikes"),
|
||||
|
@ -29,6 +29,7 @@ import PlayersPage from "./views/layout/PlayersPage";
|
||||
import AllPlayers from "./views/players/AllPlayers";
|
||||
import ServerGeolocations from "./views/server/ServerGeolocations";
|
||||
import LoginPage from "./views/layout/LoginPage";
|
||||
import ServerPerformance from "./views/server/ServerPerformance";
|
||||
|
||||
const SwaggerView = React.lazy(() => import("./views/SwaggerView"));
|
||||
|
||||
@ -87,7 +88,7 @@ function App() {
|
||||
<Route path="retention" element={<></>}/>
|
||||
<Route path="players" element={<ServerPlayers/>}/>
|
||||
<Route path="geolocations" element={<ServerGeolocations/>}/>
|
||||
<Route path="performance" element={<></>}/>
|
||||
<Route path="performance" element={<ServerPerformance/>}/>
|
||||
<Route path="plugins-overview" element={<></>}/>
|
||||
<Route path="*" element={<ErrorView error={{
|
||||
message: 'Unknown tab address, please correct the address',
|
||||
|
@ -0,0 +1,95 @@
|
||||
import {useParams} from "react-router-dom";
|
||||
import {useDataRequest} from "../../../../hooks/dataFetchHook";
|
||||
import {fetchOptimizedPerformance} from "../../../../service/serverService";
|
||||
import {ErrorViewBody} from "../../../../views/ErrorView";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Card} from "react-bootstrap-v5";
|
||||
import CardTabs from "../../../CardTabs";
|
||||
import {faGears, faHdd, faMap, faMicrochip, faSignal, faTachometerAlt} from "@fortawesome/free-solid-svg-icons";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {ChartLoader} from "../../../navigation/Loader";
|
||||
|
||||
const PunchCardTab = ({data, loadingError}) => {
|
||||
|
||||
if (loadingError) return <ErrorViewBody error={loadingError}/>
|
||||
if (!data) return <ChartLoader/>;
|
||||
|
||||
return <ChartLoader/>
|
||||
}
|
||||
|
||||
function mapToDataSeries(performanceData) {
|
||||
const playersOnline = [];
|
||||
const tps = [];
|
||||
const cpu = [];
|
||||
const ram = [];
|
||||
const entities = [];
|
||||
const chunks = [];
|
||||
const disk = [];
|
||||
|
||||
return new Promise((resolve => {
|
||||
let i = 0;
|
||||
const length = performanceData.length;
|
||||
|
||||
function processNextThousand() {
|
||||
const to = Math.min(i + 1000, length);
|
||||
for (i; i < to; i++) {
|
||||
const entry = performanceData[i];
|
||||
const date = entry[0];
|
||||
playersOnline[i] = [date, entry[1]];
|
||||
tps[i] = [date, entry[2]];
|
||||
cpu[i] = [date, entry[3]];
|
||||
ram[i] = [date, entry[4]];
|
||||
entities[i] = [date, entry[5]];
|
||||
chunks[i] = [date, entry[6]];
|
||||
disk[i] = [date, entry[7]];
|
||||
}
|
||||
if (i >= length) {
|
||||
resolve({playersOnline, tps, cpu, ram, entities, chunks, disk})
|
||||
} else {
|
||||
setTimeout(processNextThousand, 10);
|
||||
}
|
||||
}
|
||||
|
||||
processNextThousand();
|
||||
}))
|
||||
}
|
||||
|
||||
const PerformanceGraphsCard = () => {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const {identifier} = useParams();
|
||||
const {data, loadingError} = useDataRequest(fetchOptimizedPerformance, [identifier]);
|
||||
const [parsedData, setParsedData] = useState(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
mapToDataSeries(data).then(parsed => setParsedData(parsed))
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
return <Card>
|
||||
<CardTabs tabs={[
|
||||
{
|
||||
name: t('html.label.all'), icon: faGears, color: 'blue-grey', href: 'all',
|
||||
element: <PunchCardTab data={parsedData} loadingError={loadingError}/>
|
||||
}, {
|
||||
name: t('html.label.tps'), icon: faTachometerAlt, color: 'red', href: 'tps',
|
||||
element: <PunchCardTab data={parsedData} loadingError={loadingError}/>
|
||||
}, {
|
||||
name: t('html.label.cpuRam'), icon: faMicrochip, color: 'light-green', href: 'cpu-ram',
|
||||
element: <PunchCardTab data={parsedData} loadingError={loadingError}/>
|
||||
}, {
|
||||
name: t('html.label.world'), icon: faMap, color: 'purple', href: 'world-load',
|
||||
element: <PunchCardTab data={parsedData} loadingError={loadingError}/>
|
||||
}, {
|
||||
name: t('html.label.ping'), icon: faSignal, color: 'amber', href: 'ping',
|
||||
element: <PunchCardTab data={parsedData} loadingError={loadingError}/>
|
||||
}, {
|
||||
name: t('html.label.diskSpace'), icon: faHdd, color: 'green', href: 'disk',
|
||||
element: <PunchCardTab data={parsedData} loadingError={loadingError}/>
|
||||
},
|
||||
]}/>
|
||||
</Card>
|
||||
}
|
||||
|
||||
export default PerformanceGraphsCard;
|
@ -0,0 +1,28 @@
|
||||
import React from "react";
|
||||
import InsightsFor30DaysCard from "../../common/InsightsFor30DaysCard";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import Datapoint from "../../../Datapoint";
|
||||
import {faDragon, faMap, faTachometerAlt, faUsers} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
const PerformanceInsightsCard = ({data}) => {
|
||||
const {t} = useTranslation();
|
||||
if (!data) return <></>
|
||||
|
||||
return (
|
||||
<InsightsFor30DaysCard>
|
||||
<p>{t('html.label.duringLowTps')}</p>
|
||||
<Datapoint name={t('html.label.average') + ' ' + t('html.label.players')} icon={faUsers} color="red"
|
||||
value={data.low_tps_players} bold/>
|
||||
<Datapoint name={t('html.label.averageEntities')} icon={faDragon} color="red"
|
||||
value={data.low_tps_entities}/>
|
||||
<Datapoint name={t('html.label.averageChunks')} icon={faMap} color="red"
|
||||
value={data.low_tps_chunks}/>
|
||||
<Datapoint name={t('html.label.averageCpuUsage')} icon={faTachometerAlt} color="red"
|
||||
value={data.low_tps_entities}/>
|
||||
<Datapoint name={t('html.label.averageTps')} icon={faTachometerAlt} color="red"
|
||||
value={data.low_tps_tps}/>
|
||||
</InsightsFor30DaysCard>
|
||||
)
|
||||
}
|
||||
|
||||
export default PerformanceInsightsCard;
|
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import PerformanceAsNumbersTable from "../../../table/PerformanceAsNumbersTable";
|
||||
import CardHeader from "../../CardHeader";
|
||||
import {faBookOpen} from "@fortawesome/free-solid-svg-icons";
|
||||
import {Card} from "react-bootstrap-v5";
|
||||
|
||||
const PerformanceAsNumbersCard = ({data}) => {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader icon={faBookOpen} color="blue-grey" label={'html.label.performanceAsNumbers'}/>
|
||||
<PerformanceAsNumbersTable data={data}/>
|
||||
</Card>
|
||||
)
|
||||
};
|
||||
|
||||
export default PerformanceAsNumbersCard
|
@ -0,0 +1,95 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {
|
||||
faDragon,
|
||||
faExclamationCircle,
|
||||
faHdd,
|
||||
faMap,
|
||||
faMicrochip,
|
||||
faPowerOff,
|
||||
faTachometerAlt,
|
||||
faUser
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
import {TableRow} from "./TableRow";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faEye} from "@fortawesome/free-regular-svg-icons";
|
||||
import AsNumbersTable from "./AsNumbersTable";
|
||||
|
||||
const PerformanceAsNumbersTable = ({data}) => {
|
||||
const {t} = useTranslation();
|
||||
if (!data) return <></>;
|
||||
|
||||
return (
|
||||
<AsNumbersTable
|
||||
headers={[t('html.label.last30days'), t('html.label.last7days'), t('html.label.last24hours')]}
|
||||
>
|
||||
<TableRow icon={faExclamationCircle} color="red" text={t('html.label.lowTpsSpikes')}
|
||||
values={[
|
||||
data.low_tps_spikes_30d,
|
||||
data.low_tps_spikes_7d,
|
||||
data.low_tps_spikes_24h
|
||||
]}/>
|
||||
<TableRow icon={faPowerOff} color="red"
|
||||
text={t('html.label.serverDowntime') + ' (' + t('generic.noData') + ')'}
|
||||
values={[
|
||||
data.server_downtime_30d,
|
||||
data.server_downtime_7d,
|
||||
data.server_downtime_24h
|
||||
]}/>
|
||||
<TableRow icon={faUser} color="light-blue" text={t('html.label.averagePlayers')}
|
||||
values={[
|
||||
data.players_30d,
|
||||
data.players_7d,
|
||||
data.players_24h
|
||||
]}/>
|
||||
<TableRow icon={faTachometerAlt} color="orange" text={t('html.label.averageTps')}
|
||||
values={[
|
||||
data.tps_30d,
|
||||
data.tps_7d,
|
||||
data.tps_24h
|
||||
]}/>
|
||||
<TableRow icon={faTachometerAlt} color="amber" text={t('html.label.averageCpuUsage')}
|
||||
values={[
|
||||
data.cpu_30d,
|
||||
data.cpu_7d,
|
||||
data.cpu_24h
|
||||
]}/>
|
||||
<TableRow icon={faMicrochip} color="light-green" text={t('html.label.averageRamUsage')}
|
||||
values={[
|
||||
data.ram_30d,
|
||||
data.ram_7d,
|
||||
data.ram_24h
|
||||
]}/>
|
||||
<TableRow icon={faDragon} color="purple" text={t('html.label.averageEntities')}
|
||||
values={[
|
||||
data.entities_30d,
|
||||
data.entities_7d,
|
||||
data.entities_24h
|
||||
]}/>
|
||||
<TableRow icon={faMap} color="blue-grey"
|
||||
text={<>{t('html.label.averageChunks')}{' '}{data.chunks_30d === 'Unavailable' ?
|
||||
<Fa icon={faEye} title={t('html.description.noSpongeChunks')}/> : ''}</>}
|
||||
values={[
|
||||
data.chunks_30d,
|
||||
data.chunks_7d,
|
||||
data.chunks_24h
|
||||
]}/>
|
||||
<TableRow icon={faHdd} color="green"
|
||||
text={t('html.label.maxFreeDisk')}
|
||||
values={[
|
||||
data.max_disk_30d,
|
||||
data.max_disk_7d,
|
||||
data.max_disk_24h
|
||||
]}/>
|
||||
<TableRow icon={faHdd} color="green"
|
||||
text={t('html.label.minFreeDisk')}
|
||||
values={[
|
||||
data.min_disk_30d,
|
||||
data.min_disk_7d,
|
||||
data.min_disk_24h
|
||||
]}/>
|
||||
</AsNumbersTable>
|
||||
)
|
||||
}
|
||||
|
||||
export default PerformanceAsNumbersTable;
|
@ -36,6 +36,12 @@ export const fetchPvpPve = async (identifier) => {
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPerformanceOverview = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/performanceOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchSessions = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/sessions?server=${identifier}×tamp=${timestamp}`;
|
||||
@ -107,3 +113,9 @@ export const fetchGeolocations = async (identifier) => {
|
||||
const url = `/v1/graph?type=geolocation&server=${identifier}×tamp=${timestamp}`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchOptimizedPerformance = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/graph?type=optimizedPerformance&server=${identifier}×tamp=${timestamp}`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
40
Plan/react/dashboard/src/views/server/ServerPerformance.js
Normal file
40
Plan/react/dashboard/src/views/server/ServerPerformance.js
Normal file
@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import LoadIn from "../../components/animation/LoadIn";
|
||||
import {Col, Row} from "react-bootstrap-v5";
|
||||
import {useParams} from "react-router-dom";
|
||||
import {useDataRequest} from "../../hooks/dataFetchHook";
|
||||
import {fetchPerformanceOverview} from "../../service/serverService";
|
||||
import PerformanceGraphsCard from "../../components/cards/server/graphs/PerformanceGraphsCard";
|
||||
import PerformanceInsightsCard from "../../components/cards/server/insights/PerformanceInsightsCard";
|
||||
import {ErrorViewCard} from "../ErrorView";
|
||||
import PerformanceAsNumbersCard from "../../components/cards/server/tables/PerformanceAsNumbersCard";
|
||||
|
||||
const ServerPerformance = () => {
|
||||
const {identifier} = useParams();
|
||||
|
||||
const {data, loadingError} = useDataRequest(fetchPerformanceOverview, [identifier]);
|
||||
|
||||
return (
|
||||
<LoadIn>
|
||||
<section className="server_performance">
|
||||
<Row>
|
||||
<Col lg={12}>
|
||||
<PerformanceGraphsCard/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col lg={8}>
|
||||
{loadingError ? <ErrorViewCard error={loadingError}/> :
|
||||
<PerformanceAsNumbersCard data={data?.numbers}/>}
|
||||
</Col>
|
||||
<Col lg={4}>
|
||||
{loadingError ? <ErrorViewCard error={loadingError}/> :
|
||||
<PerformanceInsightsCard data={data?.insights}/>}
|
||||
</Col>
|
||||
</Row>
|
||||
</section>
|
||||
</LoadIn>
|
||||
)
|
||||
};
|
||||
|
||||
export default ServerPerformance
|
Loading…
Reference in New Issue
Block a user