mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-11-16 15:45:16 +01:00
Network performance tab (#2009)
* Fixed disk medium threshold not showing color * Added 'serverName' and 'serverUUID' to optimizedPerformance endpoint * Added /v1/network/listServers endpoint * Added /v1/network/performanceOverview?servers endpoint * Hide negative values from performance graphs * Allow json cache bypass by not providing timestamp parameter in URIQuery * Ignore negative values in low tps spike count * Added (Unavailable with Export) to exported network html performance tab title Affects issues: - Close #1693
This commit is contained in:
parent
c22874df34
commit
13823c044a
@ -170,7 +170,7 @@ public class TPSMutator {
|
|||||||
|
|
||||||
for (TPS tpsObj : tpsData) {
|
for (TPS tpsObj : tpsData) {
|
||||||
double tps = tpsObj.getTicksPerSecond();
|
double tps = tpsObj.getTicksPerSecond();
|
||||||
if (tps < threshold) {
|
if (0 <= tps && tps < threshold) {
|
||||||
if (!wasLow) {
|
if (!wasLow) {
|
||||||
spikeCount++;
|
spikeCount++;
|
||||||
wasLow = true;
|
wasLow = true;
|
||||||
|
@ -98,8 +98,8 @@ public class NetworkPageExporter extends FileExporter {
|
|||||||
|
|
||||||
// Fixes refreshingJsonRequest ignoring old data of export
|
// Fixes refreshingJsonRequest ignoring old data of export
|
||||||
String html = StringUtils.replaceEach(page.toHtml(),
|
String html = StringUtils.replaceEach(page.toHtml(),
|
||||||
new String[]{"loadPlayersOnlineGraph, 'network-overview', true);"},
|
new String[]{"loadPlayersOnlineGraph, 'network-overview', true);", "· Performance"},
|
||||||
new String[]{"loadPlayersOnlineGraph, 'network-overview');"});
|
new String[]{"loadPlayersOnlineGraph, 'network-overview');", "· Performance (Unavailable with Export)"});
|
||||||
|
|
||||||
export(to, exportPaths.resolveExportPaths(html));
|
export(to, exportPaths.resolveExportPaths(html));
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ import javax.inject.Inject;
|
|||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory with different JSON creation methods placed to a single class.
|
* Factory with different JSON creation methods placed to a single class.
|
||||||
@ -258,4 +259,16 @@ public class JSONFactory {
|
|||||||
return tableEntries;
|
return tableEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> listServers() {
|
||||||
|
Collection<Server> servers = dbSystem.getDatabase().query(ServerQueries.fetchPlanServerInformationCollection());
|
||||||
|
return Maps.builder(String.class, Object.class)
|
||||||
|
.put("servers", servers.stream()
|
||||||
|
.map(server -> Maps.builder(String.class, Object.class)
|
||||||
|
.put("serverUUID", server.getUuid().toString())
|
||||||
|
.put("serverName", server.getIdentifiableName())
|
||||||
|
.put("proxy", server.isProxy())
|
||||||
|
.build())
|
||||||
|
.collect(Collectors.toList()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
@ -29,9 +29,12 @@ import com.djrapitops.plan.delivery.rendering.json.graphs.pie.Pie;
|
|||||||
import com.djrapitops.plan.delivery.rendering.json.graphs.pie.WorldPie;
|
import com.djrapitops.plan.delivery.rendering.json.graphs.pie.WorldPie;
|
||||||
import com.djrapitops.plan.delivery.rendering.json.graphs.special.WorldMap;
|
import com.djrapitops.plan.delivery.rendering.json.graphs.special.WorldMap;
|
||||||
import com.djrapitops.plan.delivery.rendering.json.graphs.stack.StackGraph;
|
import com.djrapitops.plan.delivery.rendering.json.graphs.stack.StackGraph;
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.request.URIQuery;
|
||||||
import com.djrapitops.plan.gathering.domain.FinishedSession;
|
import com.djrapitops.plan.gathering.domain.FinishedSession;
|
||||||
import com.djrapitops.plan.gathering.domain.Ping;
|
import com.djrapitops.plan.gathering.domain.Ping;
|
||||||
import com.djrapitops.plan.gathering.domain.WorldTimes;
|
import com.djrapitops.plan.gathering.domain.WorldTimes;
|
||||||
|
import com.djrapitops.plan.identification.Server;
|
||||||
import com.djrapitops.plan.identification.ServerUUID;
|
import com.djrapitops.plan.identification.ServerUUID;
|
||||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||||
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
||||||
@ -119,7 +122,9 @@ public class GraphJSONCreator {
|
|||||||
"}}";
|
"}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> optimizedPerformanceGraphJSON(ServerUUID serverUUID) {
|
public Map<String, Object> optimizedPerformanceGraphJSON(ServerUUID serverUUID, URIQuery query) {
|
||||||
|
long after = getAfter(query); // TODO Implement if performance issues become apparent.
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
long twoMonthsAgo = now - TimeUnit.DAYS.toMillis(60);
|
long twoMonthsAgo = now - TimeUnit.DAYS.toMillis(60);
|
||||||
long monthAgo = now - TimeUnit.DAYS.toMillis(30);
|
long monthAgo = now - TimeUnit.DAYS.toMillis(30);
|
||||||
@ -131,6 +136,10 @@ public class GraphJSONCreator {
|
|||||||
TPSMutator lowResolutionData = new TPSMutator(db.query(TPSQueries.fetchTPSDataOfServerInResolution(twoMonthsAgo, monthAgo, lowResolution, serverUUID)));
|
TPSMutator lowResolutionData = new TPSMutator(db.query(TPSQueries.fetchTPSDataOfServerInResolution(twoMonthsAgo, monthAgo, lowResolution, serverUUID)));
|
||||||
TPSMutator highResolutionData = new TPSMutator(db.query(TPSQueries.fetchTPSDataOfServer(monthAgo, now, serverUUID)));
|
TPSMutator highResolutionData = new TPSMutator(db.query(TPSQueries.fetchTPSDataOfServer(monthAgo, now, serverUUID)));
|
||||||
|
|
||||||
|
String serverName = db.query(ServerQueries.fetchServerMatchingIdentifier(serverUUID))
|
||||||
|
.map(Server::getIdentifiableName)
|
||||||
|
.orElse(serverUUID.toString());
|
||||||
|
|
||||||
List<Number[]> values = lowestResolutionData.toArrays(new LineGraph.GapStrategy(
|
List<Number[]> values = lowestResolutionData.toArrays(new LineGraph.GapStrategy(
|
||||||
config.isTrue(DisplaySettings.GAPS_IN_GRAPH_DATA),
|
config.isTrue(DisplaySettings.GAPS_IN_GRAPH_DATA),
|
||||||
lowestResolution + TimeUnit.MINUTES.toMillis(1),
|
lowestResolution + TimeUnit.MINUTES.toMillis(1),
|
||||||
@ -172,9 +181,21 @@ public class GraphJSONCreator {
|
|||||||
.put("diskThresholdMed", config.get(DisplaySettings.GRAPH_DISK_THRESHOLD_MED))
|
.put("diskThresholdMed", config.get(DisplaySettings.GRAPH_DISK_THRESHOLD_MED))
|
||||||
.put("diskThresholdHigh", config.get(DisplaySettings.GRAPH_DISK_THRESHOLD_HIGH))
|
.put("diskThresholdHigh", config.get(DisplaySettings.GRAPH_DISK_THRESHOLD_HIGH))
|
||||||
.build())
|
.build())
|
||||||
|
.put("serverName", serverName)
|
||||||
|
.put("serverUUID", serverUUID)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long getAfter(URIQuery query) {
|
||||||
|
try {
|
||||||
|
return query.get("after")
|
||||||
|
.map(Long::parseLong)
|
||||||
|
.orElse(0L) - 500L; // Some headroom for out-of-sync clock.
|
||||||
|
} catch (NumberFormatException badType) {
|
||||||
|
throw new BadRequestException("'after': " + badType.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String playersOnlineGraph(ServerUUID serverUUID) {
|
public String playersOnlineGraph(ServerUUID serverUUID) {
|
||||||
Database db = dbSystem.getDatabase();
|
Database db = dbSystem.getDatabase();
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
@ -25,6 +25,7 @@ import com.djrapitops.plan.utilities.UnitSemaphoreAccessLock;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
@ -62,7 +63,7 @@ public class AsyncJSONResolverService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T> JSONStorage.StoredJSON resolve(
|
public <T> JSONStorage.StoredJSON resolve(
|
||||||
long newerThanTimestamp, DataID dataID, ServerUUID serverUUID, Function<ServerUUID, T> creator
|
Optional<Long> newerThanTimestamp, DataID dataID, ServerUUID serverUUID, Function<ServerUUID, T> creator
|
||||||
) {
|
) {
|
||||||
String identifier = dataID.of(serverUUID);
|
String identifier = dataID.of(serverUUID);
|
||||||
Supplier<T> jsonCreator = () -> creator.apply(serverUUID);
|
Supplier<T> jsonCreator = () -> creator.apply(serverUUID);
|
||||||
@ -71,24 +72,29 @@ public class AsyncJSONResolverService {
|
|||||||
|
|
||||||
|
|
||||||
public <T> JSONStorage.StoredJSON resolve(
|
public <T> JSONStorage.StoredJSON resolve(
|
||||||
long newerThanTimestamp, DataID dataID, Supplier<T> jsonCreator
|
Optional<Long> newerThanTimestamp, DataID dataID, Supplier<T> jsonCreator
|
||||||
) {
|
) {
|
||||||
String identifier = dataID.name();
|
String identifier = dataID.name();
|
||||||
return getStoredOrCreateJSON(newerThanTimestamp, identifier, jsonCreator);
|
return getStoredOrCreateJSON(newerThanTimestamp, identifier, jsonCreator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> JSONStorage.StoredJSON getStoredOrCreateJSON(
|
private <T> JSONStorage.StoredJSON getStoredOrCreateJSON(
|
||||||
long timestamp, String identifier, Supplier<T> jsonCreator
|
Optional<Long> givenTimestamp, String identifier, Supplier<T> jsonCreator
|
||||||
) {
|
) {
|
||||||
JSONStorage.StoredJSON storedJSON = getNewFromCache(timestamp, identifier);
|
JSONStorage.StoredJSON storedJSON = null;
|
||||||
|
Future<JSONStorage.StoredJSON> updatedJSON = null;
|
||||||
|
if (givenTimestamp.isPresent()) {
|
||||||
|
long timestamp = givenTimestamp.get();
|
||||||
|
storedJSON = getNewFromCache(timestamp, identifier);
|
||||||
if (storedJSON != null) return storedJSON;
|
if (storedJSON != null) return storedJSON;
|
||||||
|
|
||||||
// No new enough version, let's refresh and send old version of the file
|
// No new enough version, let's refresh and send old version of the file
|
||||||
Future<JSONStorage.StoredJSON> updatedJSON = scheduleJSONForUpdate(timestamp, identifier, jsonCreator);
|
updatedJSON = scheduleJSONForUpdate(timestamp, identifier, jsonCreator);
|
||||||
|
|
||||||
storedJSON = getOldFromCache(timestamp, identifier);
|
storedJSON = getOldFromCache(timestamp, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
if (storedJSON != null) {
|
if (storedJSON != null) {
|
||||||
return storedJSON;
|
return storedJSON; // Found old from cache
|
||||||
} else {
|
} else {
|
||||||
// Update not performed if the last update was recent and the file is deleted before next update
|
// Update not performed if the last update was recent and the file is deleted before next update
|
||||||
// Fall back to waiting for the updated file if old version of the file doesn't exist.
|
// Fall back to waiting for the updated file if old version of the file doesn't exist.
|
||||||
|
@ -49,8 +49,8 @@ public enum DataID {
|
|||||||
PLAYERBASE_OVERVIEW,
|
PLAYERBASE_OVERVIEW,
|
||||||
PERFORMANCE_OVERVIEW,
|
PERFORMANCE_OVERVIEW,
|
||||||
EXTENSION_NAV,
|
EXTENSION_NAV,
|
||||||
EXTENSION_TABS
|
EXTENSION_TABS,
|
||||||
;
|
LIST_SERVERS;
|
||||||
|
|
||||||
public String of(ServerUUID serverUUID) {
|
public String of(ServerUUID serverUUID) {
|
||||||
return name() + '-' + serverUUID;
|
return name() + '-' + serverUUID;
|
||||||
|
@ -22,6 +22,7 @@ import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
|||||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||||
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
|
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
|
||||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.request.URIQuery;
|
||||||
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.AsyncJSONResolverService;
|
import com.djrapitops.plan.delivery.webserver.cache.AsyncJSONResolverService;
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.DataID;
|
import com.djrapitops.plan.delivery.webserver.cache.DataID;
|
||||||
@ -87,14 +88,14 @@ public class GraphsJSONResolver implements Resolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private JSONStorage.StoredJSON getGraphJSON(Request request, DataID dataID) {
|
private JSONStorage.StoredJSON getGraphJSON(Request request, DataID dataID) {
|
||||||
long timestamp = Identifiers.getTimestamp(request);
|
Optional<Long> timestamp = Identifiers.getTimestamp(request);
|
||||||
|
|
||||||
JSONStorage.StoredJSON storedJSON;
|
JSONStorage.StoredJSON storedJSON;
|
||||||
if (request.getQuery().get("server").isPresent()) {
|
if (request.getQuery().get("server").isPresent()) {
|
||||||
ServerUUID serverUUID = identifiers.getServerUUID(request); // Can throw BadRequestException
|
ServerUUID serverUUID = identifiers.getServerUUID(request); // Can throw BadRequestException
|
||||||
storedJSON = jsonResolverService.resolve(
|
storedJSON = jsonResolverService.resolve(
|
||||||
timestamp, dataID, serverUUID,
|
timestamp, dataID, serverUUID,
|
||||||
theServerUUID -> generateGraphDataJSONOfType(dataID, theServerUUID)
|
theServerUUID -> generateGraphDataJSONOfType(dataID, theServerUUID, request.getQuery())
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Assume network
|
// Assume network
|
||||||
@ -138,12 +139,12 @@ public class GraphsJSONResolver implements Resolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object generateGraphDataJSONOfType(DataID id, ServerUUID serverUUID) {
|
private Object generateGraphDataJSONOfType(DataID id, ServerUUID serverUUID, URIQuery query) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case GRAPH_PERFORMANCE:
|
case GRAPH_PERFORMANCE:
|
||||||
return graphJSON.performanceGraphJSON(serverUUID);
|
return graphJSON.performanceGraphJSON(serverUUID);
|
||||||
case GRAPH_OPTIMIZED_PERFORMANCE:
|
case GRAPH_OPTIMIZED_PERFORMANCE:
|
||||||
return graphJSON.optimizedPerformanceGraphJSON(serverUUID);
|
return graphJSON.optimizedPerformanceGraphJSON(serverUUID, query);
|
||||||
case GRAPH_ONLINE:
|
case GRAPH_ONLINE:
|
||||||
return graphJSON.playersOnlineGraph(serverUUID);
|
return graphJSON.playersOnlineGraph(serverUUID);
|
||||||
case GRAPH_UNIQUE_NEW:
|
case GRAPH_UNIQUE_NEW:
|
||||||
|
@ -44,7 +44,8 @@ public class NetworkJSONResolver {
|
|||||||
AsyncJSONResolverService asyncJSONResolverService, JSONFactory jsonFactory,
|
AsyncJSONResolverService asyncJSONResolverService, JSONFactory jsonFactory,
|
||||||
NetworkOverviewJSONCreator networkOverviewJSONCreator,
|
NetworkOverviewJSONCreator networkOverviewJSONCreator,
|
||||||
NetworkPlayerBaseOverviewJSONCreator networkPlayerBaseOverviewJSONCreator,
|
NetworkPlayerBaseOverviewJSONCreator networkPlayerBaseOverviewJSONCreator,
|
||||||
NetworkSessionsOverviewJSONCreator networkSessionsOverviewJSONCreator
|
NetworkSessionsOverviewJSONCreator networkSessionsOverviewJSONCreator,
|
||||||
|
NetworkPerformanceJSONResolver networkPerformanceJSONResolver
|
||||||
) {
|
) {
|
||||||
this.asyncJSONResolverService = asyncJSONResolverService;
|
this.asyncJSONResolverService = asyncJSONResolverService;
|
||||||
resolver = CompositeResolver.builder()
|
resolver = CompositeResolver.builder()
|
||||||
@ -53,6 +54,8 @@ public class NetworkJSONResolver {
|
|||||||
.add("sessionsOverview", forJSON(DataID.SESSIONS_OVERVIEW, networkSessionsOverviewJSONCreator))
|
.add("sessionsOverview", forJSON(DataID.SESSIONS_OVERVIEW, networkSessionsOverviewJSONCreator))
|
||||||
.add("servers", forJSON(DataID.SERVERS, jsonFactory::serversAsJSONMaps))
|
.add("servers", forJSON(DataID.SERVERS, jsonFactory::serversAsJSONMaps))
|
||||||
.add("pingTable", forJSON(DataID.PING_TABLE, jsonFactory::pingPerGeolocation))
|
.add("pingTable", forJSON(DataID.PING_TABLE, jsonFactory::pingPerGeolocation))
|
||||||
|
.add("listServers", forJSON(DataID.LIST_SERVERS, jsonFactory::listServers))
|
||||||
|
.add("performanceOverview", networkPerformanceJSONResolver)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Player Analytics (Plan).
|
||||||
|
*
|
||||||
|
* Plan is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Plan is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.djrapitops.plan.delivery.webserver.resolver.json;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.delivery.domain.mutators.TPSMutator;
|
||||||
|
import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||||
|
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||||
|
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
||||||
|
import com.djrapitops.plan.gathering.domain.TPS;
|
||||||
|
import com.djrapitops.plan.identification.ServerUUID;
|
||||||
|
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||||
|
import com.djrapitops.plan.settings.config.paths.DisplaySettings;
|
||||||
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
|
import com.djrapitops.plan.settings.locale.lang.GenericLang;
|
||||||
|
import com.djrapitops.plan.storage.database.DBSystem;
|
||||||
|
import com.djrapitops.plan.storage.database.Database;
|
||||||
|
import com.djrapitops.plan.storage.database.queries.objects.TPSQueries;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates JSON payload for /server-page Performance tab.
|
||||||
|
*
|
||||||
|
* @author AuroraLS3
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class NetworkPerformanceJSONResolver implements Resolver {
|
||||||
|
|
||||||
|
private final PlanConfig config;
|
||||||
|
private final Locale locale;
|
||||||
|
private final DBSystem dbSystem;
|
||||||
|
|
||||||
|
private final Formatter<Double> decimals;
|
||||||
|
private final Formatter<Long> timeAmount;
|
||||||
|
private final Formatter<Double> percentage;
|
||||||
|
private final Formatter<Double> byteSize;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NetworkPerformanceJSONResolver(
|
||||||
|
PlanConfig config,
|
||||||
|
Locale locale,
|
||||||
|
DBSystem dbSystem,
|
||||||
|
Formatters formatters
|
||||||
|
) {
|
||||||
|
this.config = config;
|
||||||
|
this.locale = locale;
|
||||||
|
this.dbSystem = dbSystem;
|
||||||
|
|
||||||
|
decimals = formatters.decimals();
|
||||||
|
percentage = formatters.percentage();
|
||||||
|
timeAmount = formatters.timeAmount();
|
||||||
|
byteSize = formatters.byteSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canAccess(Request request) {
|
||||||
|
return request.getUser().orElse(new WebUser("")).hasPermission("page.network");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Response> resolve(Request request) {
|
||||||
|
List<ServerUUID> serverUUIDs = request.getQuery().get("servers")
|
||||||
|
.map(this::getUUIDList)
|
||||||
|
.orElse(Collections.emptyList())
|
||||||
|
.stream().map(ServerUUID::from)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return Optional.of(Response.builder()
|
||||||
|
.setJSONContent(createJSONAsMap(serverUUIDs))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<UUID> getUUIDList(String jsonString) {
|
||||||
|
return new Gson().fromJson(jsonString, new TypeToken<List<UUID>>() {}.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> createJSONAsMap(Collection<ServerUUID> serverUUIDs) {
|
||||||
|
Map<String, Object> serverOverview = new HashMap<>();
|
||||||
|
Database db = dbSystem.getDatabase();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long monthAgo = now - TimeUnit.DAYS.toMillis(30L);
|
||||||
|
Map<Integer, List<TPS>> tpsData = db.query(TPSQueries.fetchTPSDataOfServers(monthAgo, now, serverUUIDs));
|
||||||
|
|
||||||
|
serverOverview.put("numbers", createNumbersMap(tpsData));
|
||||||
|
return serverOverview;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> createNumbersMap(Map<Integer, List<TPS>> tpsData) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long dayAgo = now - TimeUnit.DAYS.toMillis(1L);
|
||||||
|
long weekAgo = now - TimeUnit.DAYS.toMillis(7L);
|
||||||
|
|
||||||
|
Map<String, Object> numbers = new HashMap<>();
|
||||||
|
|
||||||
|
List<TPS> tpsDataOfAllServers = new ArrayList<>();
|
||||||
|
tpsData.values().forEach(tpsDataOfAllServers::addAll);
|
||||||
|
TPSMutator tpsDataMonth = new TPSMutator(tpsDataOfAllServers);
|
||||||
|
TPSMutator tpsDataWeek = tpsDataMonth.filterDataBetween(weekAgo, now);
|
||||||
|
TPSMutator tpsDataDay = tpsDataWeek.filterDataBetween(dayAgo, now);
|
||||||
|
|
||||||
|
Map<Integer, TPSMutator> mutatorsOfServersMonth = new HashMap<>();
|
||||||
|
Map<Integer, TPSMutator> mutatorsOfServersWeek = new HashMap<>();
|
||||||
|
Map<Integer, TPSMutator> mutatorsOfServersDay = new HashMap<>();
|
||||||
|
for (Map.Entry<Integer, List<TPS>> entry : tpsData.entrySet()) {
|
||||||
|
TPSMutator mutator = new TPSMutator(entry.getValue());
|
||||||
|
mutatorsOfServersMonth.put(entry.getKey(), mutator);
|
||||||
|
mutatorsOfServersWeek.put(entry.getKey(), mutator.filterDataBetween(weekAgo, now));
|
||||||
|
mutatorsOfServersDay.put(entry.getKey(), mutator.filterDataBetween(dayAgo, now));
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer tpsThreshold = config.get(DisplaySettings.GRAPH_TPS_THRESHOLD_MED);
|
||||||
|
numbers.put("low_tps_spikes_30d", tpsDataMonth.lowTpsSpikeCount(tpsThreshold));
|
||||||
|
numbers.put("low_tps_spikes_7d", tpsDataWeek.lowTpsSpikeCount(tpsThreshold));
|
||||||
|
numbers.put("low_tps_spikes_24h", tpsDataDay.lowTpsSpikeCount(tpsThreshold));
|
||||||
|
|
||||||
|
long downtimeMonth = getTotalDowntime(mutatorsOfServersMonth);
|
||||||
|
long downtimeWeek = getTotalDowntime(mutatorsOfServersWeek);
|
||||||
|
long downtimeDay = getTotalDowntime(mutatorsOfServersDay);
|
||||||
|
numbers.put("server_downtime_30d", timeAmount.apply(downtimeMonth));
|
||||||
|
numbers.put("server_downtime_7d", timeAmount.apply(downtimeWeek));
|
||||||
|
numbers.put("server_downtime_24h", timeAmount.apply(downtimeDay));
|
||||||
|
|
||||||
|
if (!tpsData.isEmpty()) {
|
||||||
|
numbers.put("avg_server_downtime_30d", timeAmount.apply(downtimeMonth / tpsData.size()));
|
||||||
|
numbers.put("avg_server_downtime_7d", timeAmount.apply(downtimeWeek / tpsData.size()));
|
||||||
|
numbers.put("avg_server_downtime_24h", timeAmount.apply(downtimeDay / tpsData.size()));
|
||||||
|
} else {
|
||||||
|
numbers.put("avg_server_downtime_30d", "-");
|
||||||
|
numbers.put("avg_server_downtime_7d", "-");
|
||||||
|
numbers.put("avg_server_downtime_24h", "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
numbers.put("tps_30d", format(tpsDataMonth.averageTPS()));
|
||||||
|
numbers.put("tps_7d", format(tpsDataWeek.averageTPS()));
|
||||||
|
numbers.put("tps_24h", format(tpsDataDay.averageTPS()));
|
||||||
|
numbers.put("cpu_30d", formatPercentage(tpsDataMonth.averageCPU()));
|
||||||
|
numbers.put("cpu_7d", formatPercentage(tpsDataWeek.averageCPU()));
|
||||||
|
numbers.put("cpu_24h", formatPercentage(tpsDataDay.averageCPU()));
|
||||||
|
numbers.put("ram_30d", formatBytes(tpsDataMonth.averageRAM()));
|
||||||
|
numbers.put("ram_7d", formatBytes(tpsDataWeek.averageRAM()));
|
||||||
|
numbers.put("ram_24h", formatBytes(tpsDataDay.averageRAM()));
|
||||||
|
numbers.put("entities_30d", format((int) tpsDataMonth.averageEntities()));
|
||||||
|
numbers.put("entities_7d", format((int) tpsDataWeek.averageEntities()));
|
||||||
|
numbers.put("entities_24h", format((int) tpsDataDay.averageEntities()));
|
||||||
|
numbers.put("chunks_30d", format((int) tpsDataMonth.averageChunks()));
|
||||||
|
numbers.put("chunks_7d", format((int) tpsDataWeek.averageChunks()));
|
||||||
|
numbers.put("chunks_24h", format((int) tpsDataDay.averageChunks()));
|
||||||
|
|
||||||
|
return numbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getTotalDowntime(Map<Integer, TPSMutator> mutatorsOfServersMonth) {
|
||||||
|
long downTime = 0L;
|
||||||
|
for (TPSMutator tpsMutator : mutatorsOfServersMonth.values()) {
|
||||||
|
downTime += tpsMutator.serverDownTime();
|
||||||
|
}
|
||||||
|
return downTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String format(double value) {
|
||||||
|
return value != -1 ? decimals.apply(value) : locale.get(GenericLang.UNAVAILABLE).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatBytes(double value) {
|
||||||
|
return value != -1 ? byteSize.apply(value) : locale.get(GenericLang.UNAVAILABLE).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatPercentage(double value) {
|
||||||
|
return value != -1 ? percentage.apply(value / 100.0) : locale.get(GenericLang.UNAVAILABLE).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -68,7 +68,7 @@ public class PlayerKillsJSONResolver implements Resolver {
|
|||||||
|
|
||||||
private Response getResponse(Request request) {
|
private Response getResponse(Request request) {
|
||||||
ServerUUID serverUUID = identifiers.getServerUUID(request);
|
ServerUUID serverUUID = identifiers.getServerUUID(request);
|
||||||
long timestamp = Identifiers.getTimestamp(request);
|
Optional<Long> timestamp = Identifiers.getTimestamp(request);
|
||||||
JSONStorage.StoredJSON storedJSON = jsonResolverService.resolve(timestamp, DataID.KILLS, serverUUID,
|
JSONStorage.StoredJSON storedJSON = jsonResolverService.resolve(timestamp, DataID.KILLS, serverUUID,
|
||||||
theUUID -> Collections.singletonMap("player_kills", jsonFactory.serverPlayerKillsAsJSONMap(theUUID))
|
theUUID -> Collections.singletonMap("player_kills", jsonFactory.serverPlayerKillsAsJSONMap(theUUID))
|
||||||
);
|
);
|
||||||
|
@ -78,7 +78,7 @@ public class PlayersTableJSONResolver implements Resolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private JSONStorage.StoredJSON getStoredJSON(Request request) {
|
private JSONStorage.StoredJSON getStoredJSON(Request request) {
|
||||||
long timestamp = Identifiers.getTimestamp(request);
|
Optional<Long> timestamp = Identifiers.getTimestamp(request);
|
||||||
JSONStorage.StoredJSON storedJSON;
|
JSONStorage.StoredJSON storedJSON;
|
||||||
if (request.getQuery().get("server").isPresent()) {
|
if (request.getQuery().get("server").isPresent()) {
|
||||||
ServerUUID serverUUID = identifiers.getServerUUID(request); // Can throw BadRequestException
|
ServerUUID serverUUID = identifiers.getServerUUID(request); // Can throw BadRequestException
|
||||||
|
@ -74,7 +74,7 @@ public class SessionsJSONResolver implements Resolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private JSONStorage.StoredJSON getStoredJSON(Request request) {
|
private JSONStorage.StoredJSON getStoredJSON(Request request) {
|
||||||
long timestamp = Identifiers.getTimestamp(request);
|
Optional<Long> timestamp = Identifiers.getTimestamp(request);
|
||||||
if (request.getQuery().get("server").isPresent()) {
|
if (request.getQuery().get("server").isPresent()) {
|
||||||
ServerUUID serverUUID = identifiers.getServerUUID(request);
|
ServerUUID serverUUID = identifiers.getServerUUID(request);
|
||||||
return jsonResolverService.resolve(timestamp, DataID.SESSIONS, serverUUID,
|
return jsonResolverService.resolve(timestamp, DataID.SESSIONS, serverUUID,
|
||||||
|
@ -170,15 +170,21 @@ public class TPS implements DateHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Number[] toArray() {
|
public Number[] toArray() {
|
||||||
|
double tps = getTicksPerSecond();
|
||||||
|
double cpu = getCPUUsage();
|
||||||
|
long ram = getUsedMemory();
|
||||||
|
int entities = getEntityCount();
|
||||||
|
int chunks = getChunksLoaded();
|
||||||
|
long disk = getFreeDiskSpace();
|
||||||
return new Number[]{
|
return new Number[]{
|
||||||
getDate(),
|
getDate(),
|
||||||
getPlayers(),
|
getPlayers(),
|
||||||
getTicksPerSecond(),
|
tps >= 0 ? tps : null,
|
||||||
getCPUUsage(),
|
cpu >= 0 ? cpu : null,
|
||||||
getUsedMemory(),
|
ram >= 0 ? ram : null,
|
||||||
getEntityCount(),
|
entities >= 0 ? entities : null,
|
||||||
getChunksLoaded(),
|
chunks >= 0 ? chunks : null,
|
||||||
getFreeDiskSpace()
|
disk >= 0 ? disk : null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,16 +105,16 @@ public class Identifiers {
|
|||||||
return uuidUtility.getUUIDOf(name);
|
return uuidUtility.getUUIDOf(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getTimestamp(Request request) {
|
public static Optional<Long> getTimestamp(Request request) {
|
||||||
try {
|
try {
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
long timestamp = request.getQuery().get("timestamp")
|
long timestamp = request.getQuery().get("timestamp")
|
||||||
.map(Long::parseLong)
|
.map(Long::parseLong)
|
||||||
.orElse(currentTime);
|
.orElse(currentTime);
|
||||||
if (currentTime + TimeUnit.SECONDS.toMillis(10L) < timestamp) {
|
if (currentTime + TimeUnit.SECONDS.toMillis(10L) < timestamp) {
|
||||||
return currentTime;
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
return timestamp;
|
return Optional.of(timestamp);
|
||||||
} catch (NumberFormatException nonNumberTimestamp) {
|
} catch (NumberFormatException nonNumberTimestamp) {
|
||||||
throw new BadRequestException("'timestamp' was not a number: " + nonNumberTimestamp.getMessage());
|
throw new BadRequestException("'timestamp' was not a number: " + nonNumberTimestamp.getMessage());
|
||||||
}
|
}
|
||||||
|
@ -445,4 +445,31 @@ public class TPSQueries {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Query<Map<Integer, List<TPS>>> fetchTPSDataOfServers(long after, long before, Collection<ServerUUID> serverUUIDs) {
|
||||||
|
String sql = SELECT + "*" + FROM + TABLE_NAME +
|
||||||
|
WHERE + SERVER_ID + " IN " + ServerTable.selectServerIds(serverUUIDs) +
|
||||||
|
AND + DATE + ">=?" +
|
||||||
|
AND + DATE + "<=?" +
|
||||||
|
ORDER_BY + DATE;
|
||||||
|
System.out.println(sql);
|
||||||
|
return new QueryStatement<Map<Integer, List<TPS>>>(sql, 50000) {
|
||||||
|
@Override
|
||||||
|
public void prepare(PreparedStatement statement) throws SQLException {
|
||||||
|
statement.setLong(1, after);
|
||||||
|
statement.setLong(2, before);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Integer, List<TPS>> processResults(ResultSet set) throws SQLException {
|
||||||
|
Map<Integer, List<TPS>> data = new HashMap<>();
|
||||||
|
while (set.next()) {
|
||||||
|
int serverId = set.getInt(SERVER_ID);
|
||||||
|
data.computeIfAbsent(serverId, Lists::create)
|
||||||
|
.add(extractTPS(set));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
@ -17,11 +17,15 @@
|
|||||||
package com.djrapitops.plan.storage.database.sql.tables;
|
package com.djrapitops.plan.storage.database.sql.tables;
|
||||||
|
|
||||||
import com.djrapitops.plan.identification.Server;
|
import com.djrapitops.plan.identification.Server;
|
||||||
|
import com.djrapitops.plan.identification.ServerUUID;
|
||||||
import com.djrapitops.plan.storage.database.DBType;
|
import com.djrapitops.plan.storage.database.DBType;
|
||||||
import com.djrapitops.plan.storage.database.sql.building.CreateTableBuilder;
|
import com.djrapitops.plan.storage.database.sql.building.CreateTableBuilder;
|
||||||
import com.djrapitops.plan.storage.database.sql.building.Insert;
|
import com.djrapitops.plan.storage.database.sql.building.Insert;
|
||||||
import com.djrapitops.plan.storage.database.sql.building.Sql;
|
import com.djrapitops.plan.storage.database.sql.building.Sql;
|
||||||
import com.djrapitops.plan.storage.database.sql.building.Update;
|
import com.djrapitops.plan.storage.database.sql.building.Update;
|
||||||
|
import org.apache.commons.text.TextStringBuilder;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
|
import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
|
||||||
|
|
||||||
@ -77,4 +81,12 @@ public class ServerTable {
|
|||||||
.column(MAX_PLAYERS, Sql.INT).notNull().defaultValue("-1")
|
.column(MAX_PLAYERS, Sql.INT).notNull().defaultValue("-1")
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String selectServerIds(Collection<ServerUUID> serverUUIDs) {
|
||||||
|
return '(' + SELECT + TABLE_NAME + '.' + SERVER_ID +
|
||||||
|
FROM + TABLE_NAME +
|
||||||
|
WHERE + TABLE_NAME + '.' + SERVER_UUID + " IN ('" +
|
||||||
|
new TextStringBuilder().appendWithSeparators(serverUUIDs, "','").build() +
|
||||||
|
"'))";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,9 @@ function loadservers(json, error) {
|
|||||||
|
|
||||||
if (!servers || !servers.length) {
|
if (!servers || !servers.length) {
|
||||||
let elements = document.getElementsByClassName('nav-servers');
|
let elements = document.getElementsByClassName('nav-servers');
|
||||||
for (let i = 0; i < elements.length; i++) { elements[i].style.display = 'none'; }
|
for (let i = 0; i < elements.length; i++) {
|
||||||
|
elements[i].style.display = 'none';
|
||||||
|
}
|
||||||
document.getElementById('game-server-warning').classList.remove('hidden');
|
document.getElementById('game-server-warning').classList.remove('hidden');
|
||||||
document.getElementById('data_server_list').innerHTML =
|
document.getElementById('data_server_list').innerHTML =
|
||||||
`<div class="card shadow mb-4"><div class="card-body"><p>No servers found in the database.</p><p>It appears that Plan is not installed on any game servers or not connected to the same database. See <a href="https://github.com/plan-player-analytics/Plan/wiki">wiki</a> for Network tutorial.</p></div></div>`
|
`<div class="card shadow mb-4"><div class="card-body"><p>No servers found in the database.</p><p>It appears that Plan is not installed on any game servers or not connected to the same database. See <a href="https://github.com/plan-player-analytics/Plan/wiki">wiki</a> for Network tutorial.</p></div></div>`
|
||||||
@ -445,3 +447,229 @@ function loadJoinAddressPie(json, error) {
|
|||||||
document.getElementById('joinAddressPie').innerText = `Failed to load graph data: ${error}`;
|
document.getElementById('joinAddressPie').innerText = `Failed to load graph data: ${error}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadPerformanceServerOptions() {
|
||||||
|
const refreshElement = document.querySelector(`#performance .refresh-element`);
|
||||||
|
refreshElement.querySelector('i').addEventListener('click', () => {
|
||||||
|
if (refreshElement.querySelector('.refresh-notice').innerHTML.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onSelectPerformanceServers();
|
||||||
|
refreshElement.querySelector('.refresh-notice').innerHTML = '<i class="fa fa-fw fa-cog fa-spin"></i> Updating..';
|
||||||
|
});
|
||||||
|
const selector = document.getElementById('performance-server-selector');
|
||||||
|
jsonRequest('./v1/network/listServers', function (json, error) {
|
||||||
|
if (json) {
|
||||||
|
let options = ``;
|
||||||
|
for (let server of json.servers) {
|
||||||
|
options += `<option${server.proxy ? ' selected' : ''} data-plan-server-uuid="${server.serverUUID}">${server.serverName}</option>`
|
||||||
|
}
|
||||||
|
selector.innerHTML = options;
|
||||||
|
onSelectPerformanceServers();
|
||||||
|
} else if (error) {
|
||||||
|
selector.innerText = `Failed to load server list: ${error}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onSelectPerformanceServers() {
|
||||||
|
const selector = document.getElementById('performance-server-selector');
|
||||||
|
const selectedServerUUIDs = [];
|
||||||
|
|
||||||
|
for (const option of selector.selectedOptions) {
|
||||||
|
selectedServerUUIDs.push(option.getAttribute('data-plan-server-uuid'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverUUIDs = encodeURIComponent(JSON.stringify(selectedServerUUIDs));
|
||||||
|
const loadedJson = {
|
||||||
|
servers: [],
|
||||||
|
errors: [],
|
||||||
|
zones: {},
|
||||||
|
colors: {},
|
||||||
|
timestamp_f: ''
|
||||||
|
}
|
||||||
|
const time = new Date().getTime();
|
||||||
|
const monthMs = 2592000000;
|
||||||
|
const after = time - monthMs;
|
||||||
|
for (const serverUUID of selectedServerUUIDs) {
|
||||||
|
jsonRequest(`./v1/graph?type=optimizedPerformance&server=${serverUUID}&after=${after}`, (json, error) => {
|
||||||
|
if (json) {
|
||||||
|
loadedJson.servers.push(json);
|
||||||
|
loadedJson.zones = json.zones;
|
||||||
|
loadedJson.colors = json.colors;
|
||||||
|
loadedJson.timestamp_f = json.timestamp_f;
|
||||||
|
} else if (error) {
|
||||||
|
loadedJson.errors.push(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await awaitUntil(() => selectedServerUUIDs.length === (loadedJson.servers.length + loadedJson.errors.length));
|
||||||
|
|
||||||
|
jsonRequest(`./v1/network/performanceOverview?servers=${serverUUIDs}`, loadPerformanceValues);
|
||||||
|
if (loadedJson.errors.length) {
|
||||||
|
await loadPerformanceGraph(undefined, loadedJson.errors[0]);
|
||||||
|
} else {
|
||||||
|
await loadPerformanceGraph({
|
||||||
|
servers: loadedJson.servers,
|
||||||
|
zones: loadedJson.zones,
|
||||||
|
colors: loadedJson.colors
|
||||||
|
}, undefined);
|
||||||
|
}
|
||||||
|
const refreshElement = document.querySelector(`#performance .refresh-element`);
|
||||||
|
refreshElement.querySelector('.refresh-time').innerText = loadedJson.timestamp_f;
|
||||||
|
refreshElement.querySelector('.refresh-notice').innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadPerformanceGraph(json, error) {
|
||||||
|
if (json) {
|
||||||
|
const zones = {
|
||||||
|
tps: [{
|
||||||
|
value: json.zones.tpsThresholdMed,
|
||||||
|
color: json.colors.low
|
||||||
|
}, {
|
||||||
|
value: json.zones.tpsThresholdHigh,
|
||||||
|
color: json.colors.med
|
||||||
|
}, {
|
||||||
|
value: 30,
|
||||||
|
color: json.colors.high
|
||||||
|
}],
|
||||||
|
disk: [{
|
||||||
|
value: json.zones.diskThresholdMed,
|
||||||
|
color: json.colors.low
|
||||||
|
}, {
|
||||||
|
value: json.zones.diskThresholdHigh,
|
||||||
|
color: json.colors.med
|
||||||
|
}, {
|
||||||
|
value: Number.MAX_VALUE,
|
||||||
|
color: json.colors.high
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
const serverData = [];
|
||||||
|
for (const server of json.servers) {
|
||||||
|
serverData.push({
|
||||||
|
serverName: server.serverName,
|
||||||
|
values: await mapToDataSeries(server.values)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const series = {
|
||||||
|
tps: [],
|
||||||
|
cpu: [],
|
||||||
|
ram: [],
|
||||||
|
entities: [],
|
||||||
|
chunks: [],
|
||||||
|
disk: []
|
||||||
|
}
|
||||||
|
for (const server of serverData) {
|
||||||
|
series.tps.push({
|
||||||
|
name: server.serverName, type: s.type.spline, tooltip: s.tooltip.twoDecimals,
|
||||||
|
data: server.values.tps, color: json.colors.high, zones: zones.tps, yAxis: 0
|
||||||
|
});
|
||||||
|
series.cpu.push({
|
||||||
|
name: server.serverName, type: s.type.spline, tooltip: s.tooltip.twoDecimals,
|
||||||
|
data: server.values.cpu, color: json.colors.cpu, yAxis: 0
|
||||||
|
});
|
||||||
|
series.ram.push({
|
||||||
|
name: server.serverName, type: s.type.spline, tooltip: s.tooltip.zeroDecimals,
|
||||||
|
data: server.values.ram, color: json.colors.ram, yAxis: 0
|
||||||
|
});
|
||||||
|
series.entities.push({
|
||||||
|
name: server.serverName, type: s.type.spline, tooltip: s.tooltip.zeroDecimals,
|
||||||
|
data: server.values.entities, color: json.colors.entities, yAxis: 0
|
||||||
|
});
|
||||||
|
series.chunks.push({
|
||||||
|
name: server.serverName, type: s.type.spline, tooltip: s.tooltip.zeroDecimals,
|
||||||
|
data: server.values.chunks, color: json.colors.chunks, yAxis: 0
|
||||||
|
});
|
||||||
|
series.disk.push({
|
||||||
|
name: server.serverName, type: s.type.spline, tooltip: s.tooltip.zeroDecimals,
|
||||||
|
data: server.values.disk, color: json.colors.high, zones: zones.disk, yAxis: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => lineChart('tpsGraph', series.tps), 10);
|
||||||
|
setTimeout(() => lineChart('cpuGraph', series.cpu), 20);
|
||||||
|
setTimeout(() => lineChart('ramGraph', series.ram), 30);
|
||||||
|
setTimeout(() => lineChart('entityGraph', series.entities), 40);
|
||||||
|
setTimeout(() => lineChart('chunkGraph', series.chunks), 50);
|
||||||
|
setTimeout(() => lineChart('diskGraph', series.disk), 60);
|
||||||
|
} else if (error) {
|
||||||
|
const errorMessage = `Failed to load graph data: ${error}`;
|
||||||
|
document.getElementById('tpsGraph').innerText = errorMessage;
|
||||||
|
document.getElementById('cpuGraph').innerText = errorMessage;
|
||||||
|
document.getElementById('ramGraph').innerText = errorMessage;
|
||||||
|
document.getElementById('entityGraph').innerText = errorMessage;
|
||||||
|
document.getElementById('chunkGraph').innerText = errorMessage;
|
||||||
|
document.getElementById('diskGraph').innerText = errorMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function loads Performance tab */
|
||||||
|
function loadPerformanceValues(json, error) {
|
||||||
|
const tab = document.getElementById('performance');
|
||||||
|
if (error) {
|
||||||
|
displayError(tab, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// as Numbers
|
||||||
|
let data = json.numbers;
|
||||||
|
let element = tab.querySelector('#data_numbers');
|
||||||
|
|
||||||
|
element.querySelector('#data_low_tps_spikes_30d').innerText = data.low_tps_spikes_30d;
|
||||||
|
element.querySelector('#data_low_tps_spikes_7d').innerText = data.low_tps_spikes_7d;
|
||||||
|
element.querySelector('#data_low_tps_spikes_24h').innerText = data.low_tps_spikes_24h;
|
||||||
|
element.querySelector('#data_server_downtime_30d').innerText = data.server_downtime_30d;
|
||||||
|
element.querySelector('#data_server_downtime_7d').innerText = data.server_downtime_7d;
|
||||||
|
element.querySelector('#data_server_downtime_24h').innerText = data.server_downtime_24h;
|
||||||
|
element.querySelector('#data_avg_server_downtime_30d').innerText = data.avg_server_downtime_30d;
|
||||||
|
element.querySelector('#data_avg_server_downtime_7d').innerText = data.avg_server_downtime_7d;
|
||||||
|
element.querySelector('#data_avg_server_downtime_24h').innerText = data.avg_server_downtime_24h;
|
||||||
|
element.querySelector('#data_tps_30d').innerText = data.tps_30d;
|
||||||
|
element.querySelector('#data_tps_7d').innerText = data.tps_7d;
|
||||||
|
element.querySelector('#data_tps_24h').innerText = data.tps_24h;
|
||||||
|
element.querySelector('#data_cpu_30d').innerText = data.cpu_30d;
|
||||||
|
element.querySelector('#data_cpu_7d').innerText = data.cpu_7d;
|
||||||
|
element.querySelector('#data_cpu_24h').innerText = data.cpu_24h;
|
||||||
|
element.querySelector('#data_ram_30d').innerText = data.ram_30d;
|
||||||
|
element.querySelector('#data_ram_7d').innerText = data.ram_7d;
|
||||||
|
element.querySelector('#data_ram_24h').innerText = data.ram_24h;
|
||||||
|
element.querySelector('#data_entities_30d').innerText = data.entities_30d;
|
||||||
|
element.querySelector('#data_entities_7d').innerText = data.entities_7d;
|
||||||
|
element.querySelector('#data_entities_24h').innerText = data.entities_24h;
|
||||||
|
element.querySelector('#data_chunks_30d').innerText = data.chunks_30d;
|
||||||
|
element.querySelector('#data_chunks_7d').innerText = data.chunks_7d;
|
||||||
|
element.querySelector('#data_chunks_24h').innerText = data.chunks_24h;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadPingGraph(json, error) {
|
||||||
|
if (json) {
|
||||||
|
const series = {
|
||||||
|
avgPing: {
|
||||||
|
name: s.name.avgPing,
|
||||||
|
type: s.type.spline,
|
||||||
|
tooltip: s.tooltip.twoDecimals,
|
||||||
|
data: json.avg_ping_series,
|
||||||
|
color: json.colors.avg
|
||||||
|
},
|
||||||
|
maxPing: {
|
||||||
|
name: s.name.maxPing,
|
||||||
|
type: s.type.spline,
|
||||||
|
tooltip: s.tooltip.zeroDecimals,
|
||||||
|
data: json.max_ping_series,
|
||||||
|
color: json.colors.max
|
||||||
|
},
|
||||||
|
minPing: {
|
||||||
|
name: s.name.minPing,
|
||||||
|
type: s.type.spline,
|
||||||
|
tooltip: s.tooltip.zeroDecimals,
|
||||||
|
data: json.min_ping_series,
|
||||||
|
color: json.colors.min
|
||||||
|
}
|
||||||
|
};
|
||||||
|
lineChart('pingGraph', [series.avgPing, series.maxPing, series.minPing]);
|
||||||
|
} else if (error) {
|
||||||
|
document.getElementById('pingGraph').innerText = `Failed to load graph data: ${error}`;
|
||||||
|
}
|
||||||
|
}
|
@ -369,7 +369,7 @@ async function loadOptimizedPerformanceGraph(json, error) {
|
|||||||
value: json.zones.diskThresholdMed,
|
value: json.zones.diskThresholdMed,
|
||||||
color: json.colors.low
|
color: json.colors.low
|
||||||
}, {
|
}, {
|
||||||
value: json.zones.tpsThresholdHigh,
|
value: json.zones.diskThresholdHigh,
|
||||||
color: json.colors.med
|
color: json.colors.med
|
||||||
}, {
|
}, {
|
||||||
value: Number.MAX_VALUE,
|
value: Number.MAX_VALUE,
|
||||||
|
@ -121,3 +121,16 @@ function newConfiguredXHR(callback) {
|
|||||||
|
|
||||||
return xhr;
|
return xhr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function awaitUntil(predicateFunction) {
|
||||||
|
return new Promise((resolve => {
|
||||||
|
const handlerFunction = () => {
|
||||||
|
if (predicateFunction.apply()) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
setTimeout(handlerFunction, 10)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
handlerFunction();
|
||||||
|
}))
|
||||||
|
}
|
@ -75,6 +75,9 @@
|
|||||||
<a class="collapse-item nav-button" href="#tab-sessions-overview"><i
|
<a class="collapse-item nav-button" href="#tab-sessions-overview"><i
|
||||||
class="far fa-fw fa-calendar-alt"></i>
|
class="far fa-fw fa-calendar-alt"></i>
|
||||||
Sessions</a>
|
Sessions</a>
|
||||||
|
<a class="collapse-item nav-button" href="#tab-performance">
|
||||||
|
<i class="fas fa-fw fa-cogs"></i>
|
||||||
|
<span>Performance</span></a>
|
||||||
<hr class="nav-servers dropdown-divider mx-3 my-2">
|
<hr class="nav-servers dropdown-divider mx-3 my-2">
|
||||||
<div class="nav-servers" id="navSrvContainer">
|
<div class="nav-servers" id="navSrvContainer">
|
||||||
</div>
|
</div>
|
||||||
@ -471,6 +474,205 @@
|
|||||||
</div>
|
</div>
|
||||||
</div> <!-- /.container-fluid -->
|
</div> <!-- /.container-fluid -->
|
||||||
</div> <!-- End of Sessions tab -->
|
</div> <!-- End of Sessions tab -->
|
||||||
|
<!-- Begin Performance Tab -->
|
||||||
|
<div class="tab" id="performance">
|
||||||
|
<div class="container-fluid mt-4">
|
||||||
|
<!-- Page Heading -->
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
||||||
|
<h1 class="h3 mb-0 text-gray-800"><i class="sidebar-toggler fa fa-fw fa-bars"></i>${networkDisplayName}
|
||||||
|
· Performance
|
||||||
|
<span class="refresh-element">
|
||||||
|
<i class="fa fa-fw fa-sync"></i> <span class="refresh-time"></span>
|
||||||
|
<span class="refresh-notice"><i class="fa fa-fw fa-cog fa-spin"></i> Updating..</span>
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<!-- Performance Charts -->
|
||||||
|
<div class="col-xl-12 col-lg-12 col-sm-12">
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<ul class="nav nav-tabs" id="performanceChartTab" role="tablist">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a aria-controls="profile" aria-selected="true"
|
||||||
|
class="nav-link col-black active"
|
||||||
|
data-bs-toggle="tab"
|
||||||
|
href="#tps" id="performance-tps-tab" role="tab"><i
|
||||||
|
class="fa fa-fw fa-tachometer-alt col-deep-orange"></i> TPS</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a aria-controls="contact" aria-selected="false" class="nav-link col-black"
|
||||||
|
data-bs-toggle="tab" href="#cpu" id="performance-cpu-tab"
|
||||||
|
role="tab"><i
|
||||||
|
class="fa fa-fw fa-tachometer-alt col-amber"></i>
|
||||||
|
CPU</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a aria-controls="contact" aria-selected="false" class="nav-link col-black"
|
||||||
|
data-bs-toggle="tab" href="#ram" id="performance-ram-tab"
|
||||||
|
role="tab"><i
|
||||||
|
class="fa fa-fw fa-microchip col-light-green"></i>
|
||||||
|
RAM</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a aria-controls="contact" aria-selected="false" class="nav-link col-black"
|
||||||
|
data-bs-toggle="tab" href="#entity" id="performance-entity-tab"
|
||||||
|
role="tab"><i class="fa fa-fw fa-dragon col-purple"></i>
|
||||||
|
Entities</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a aria-controls="contact" aria-selected="false" class="nav-link col-black"
|
||||||
|
data-bs-toggle="tab" href="#chunk" id="performance-chunk-tab"
|
||||||
|
role="tab"><i class="fa fa-fw fa-map col-blue-grey"></i>
|
||||||
|
Chunks</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a aria-controls="contact" aria-selected="false" class="nav-link col-black"
|
||||||
|
data-bs-toggle="tab" href="#ping" id="performance-ping-tab" role="tab"><i
|
||||||
|
class="fa fa-fw fa-signal col-amber"></i> Ping</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a aria-controls="contact" aria-selected="false" class="nav-link col-black"
|
||||||
|
data-bs-toggle="tab" href="#disk" id="performance-disk-tab" role="tab"><i
|
||||||
|
class="fa fa-fw fa-hdd col-green"></i> Disk Space</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content" id="performanceChartTabContent">
|
||||||
|
<div aria-labelledby="performance-tps-tab" class="tab-pane show active" id="tps"
|
||||||
|
role="tabpanel">
|
||||||
|
<div class="chart-area" id="tpsGraph"><span class="loader"></span></div>
|
||||||
|
</div>
|
||||||
|
<div aria-labelledby="performance-hardware-tab" class="tab-pane" id="cpu"
|
||||||
|
role="tabpanel">
|
||||||
|
<div class="chart-area" id="cpuGraph"><span class="loader"></span></div>
|
||||||
|
</div>
|
||||||
|
<div aria-labelledby="performance-hardware-tab" class="tab-pane" id="ram"
|
||||||
|
role="tabpanel">
|
||||||
|
<div class="chart-area" id="ramGraph"><span class="loader"></span></div>
|
||||||
|
</div>
|
||||||
|
<div aria-labelledby="performance-entity-tab" class="tab-pane"
|
||||||
|
id="entity"
|
||||||
|
role="tabpanel">
|
||||||
|
<div class="chart-area" id="entityGraph"><span class="loader"></span></div>
|
||||||
|
</div>
|
||||||
|
<div aria-labelledby="performance-chunk-tab" class="tab-pane"
|
||||||
|
id="chunk"
|
||||||
|
role="tabpanel">
|
||||||
|
<div class="chart-area" id="chunkGraph"><span class="loader"></span></div>
|
||||||
|
</div>
|
||||||
|
<div aria-labelledby="performance-ping-tab" class="tab-pane" id="ping"
|
||||||
|
role="tabpanel">
|
||||||
|
<p>This data is from only the proxy server (bungeecord or velocity)</p>
|
||||||
|
<div class="chart-area" id="pingGraph"><span class="loader"></span></div>
|
||||||
|
</div>
|
||||||
|
<div aria-labelledby="performance-disk-tab" class="tab-pane" id="disk"
|
||||||
|
role="tabpanel">
|
||||||
|
<div class="chart-area" id="diskGraph"><span class="loader"></span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<!-- Performance as Numbers -->
|
||||||
|
<div class="col-lg-8 mb-8 col-sm-12">
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h6 class="m-0 font-weight-bold col-black"><i
|
||||||
|
class="fa fa-fw fa-book-open col-blue-grey"></i>
|
||||||
|
Performance as Numbers</h6>
|
||||||
|
</div>
|
||||||
|
<table class="table" id="data_numbers">
|
||||||
|
<thead>
|
||||||
|
<th></th>
|
||||||
|
<th>Last 30 days</th>
|
||||||
|
<th>Last 7 days</th>
|
||||||
|
<th>Last 24 hours</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><i class="fa fa-fw fa-exclamation-circle col-red"></i>
|
||||||
|
Low TPS Spikes
|
||||||
|
</td>
|
||||||
|
<td id="data_low_tps_spikes_30d"></td>
|
||||||
|
<td id="data_low_tps_spikes_7d"></td>
|
||||||
|
<td id="data_low_tps_spikes_24h"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><i class="fa fa-fw fa-power-off col-red"></i>
|
||||||
|
Total Downtime (No Data)
|
||||||
|
</td>
|
||||||
|
<td id="data_server_downtime_30d"></td>
|
||||||
|
<td id="data_server_downtime_7d"></td>
|
||||||
|
<td id="data_server_downtime_24h"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><i class="fa fa-fw fa-power-off col-red"></i>
|
||||||
|
Average Downtime / Server
|
||||||
|
</td>
|
||||||
|
<td id="data_avg_server_downtime_30d"></td>
|
||||||
|
<td id="data_avg_server_downtime_7d"></td>
|
||||||
|
<td id="data_avg_server_downtime_24h"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><i class="fa fa-fw fa-tachometer-alt col-orange"></i> Average TPS</td>
|
||||||
|
<td id="data_tps_30d"></td>
|
||||||
|
<td id="data_tps_7d"></td>
|
||||||
|
<td id="data_tps_24h"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><i class="fa fa-fw fa-tachometer-alt col-amber"></i> Average CPU Usage</td>
|
||||||
|
<td id="data_cpu_30d"></td>
|
||||||
|
<td id="data_cpu_7d"></td>
|
||||||
|
<td id="data_cpu_24h"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><i class="fa fa-fw fa-microchip col-light-green"></i> Average RAM Usage</td>
|
||||||
|
<td id="data_ram_30d"></td>
|
||||||
|
<td id="data_ram_7d"></td>
|
||||||
|
<td id="data_ram_24h"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><i class="fa fa-fw fa-dragon col-purple"></i> Average Entities</td>
|
||||||
|
<td id="data_entities_30d"></td>
|
||||||
|
<td id="data_entities_7d"></td>
|
||||||
|
<td id="data_entities_24h"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<i class="fa fa-fw fa-map col-blue-grey"></i> Average Chunks
|
||||||
|
<i class="far fa-fw fa-eye hidden" id="sponge-chunk-warning"
|
||||||
|
title="Chunks unavailable on Sponge"></i>
|
||||||
|
</td>
|
||||||
|
<td id="data_chunks_30d"></td>
|
||||||
|
<td id="data_chunks_7d"></td>
|
||||||
|
<td id="data_chunks_24h"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div> <!-- End of Performance as numbers-->
|
||||||
|
<!-- Insights -->
|
||||||
|
<div class="col-lg-4 mb-4 col-sm-12">
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h6 class="m-0 font-weight-bold col-black"><i
|
||||||
|
class="fa fa-fw fa-server col-light-green"></i>
|
||||||
|
Server selector</h6>
|
||||||
|
</div>
|
||||||
|
<select class="form-control" id="performance-server-selector" multiple>
|
||||||
|
<option selected>Proxy server</option>
|
||||||
|
<option>Server 1</option>
|
||||||
|
<option>Skyblock</option>
|
||||||
|
<option>Server 3</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn bg-plan" onclick="onSelectPerformanceServers()">Apply</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> <!-- /.container-fluid -->
|
||||||
|
</div> <!-- End of Performance tab -->
|
||||||
<!-- Begin Playerbase Overview Tab -->
|
<!-- Begin Playerbase Overview Tab -->
|
||||||
<div class="tab" id="playerbase-overview">
|
<div class="tab" id="playerbase-overview">
|
||||||
<div class="container-fluid mt-4">
|
<div class="container-fluid mt-4">
|
||||||
@ -928,6 +1130,7 @@
|
|||||||
refreshingJsonRequest("./v1/graph?type=joinAddressPie", loadJoinAddressPie, 'playerbase-overview');
|
refreshingJsonRequest("./v1/graph?type=joinAddressPie", loadJoinAddressPie, 'playerbase-overview');
|
||||||
refreshingJsonRequest("./v1/graph?type=activity", loadActivityGraphs, 'playerbase-overview');
|
refreshingJsonRequest("./v1/graph?type=activity", loadActivityGraphs, 'playerbase-overview');
|
||||||
refreshingJsonRequest("./v1/graph?type=geolocation", loadGeolocationGraph, 'geolocations');
|
refreshingJsonRequest("./v1/graph?type=geolocation", loadGeolocationGraph, 'geolocations');
|
||||||
|
refreshingJsonRequest("../v1/graph?type=aggregatedPing&server=${serverUUID}", loadPingGraph, 'performance');
|
||||||
|
|
||||||
setLoadingText('Sorting out plugin tables..');
|
setLoadingText('Sorting out plugin tables..');
|
||||||
|
|
||||||
@ -937,6 +1140,8 @@
|
|||||||
responsive: true
|
responsive: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
loadPerformanceServerOptions();
|
||||||
|
|
||||||
setLoadingText('Almost done..');
|
setLoadingText('Almost done..');
|
||||||
openPage();
|
openPage();
|
||||||
setLoadingText('Done.');
|
setLoadingText('Done.');
|
||||||
|
@ -195,6 +195,8 @@ public class AccessControlTest {
|
|||||||
"/v1/query,400",
|
"/v1/query,400",
|
||||||
"/v1/errors,200",
|
"/v1/errors,200",
|
||||||
"/errors,200",
|
"/errors,200",
|
||||||
|
"/v1/network/listServers,200",
|
||||||
|
"/v1/network/performanceOverview?servers=[" + TestConstants.SERVER_UUID_STRING + "],200",
|
||||||
})
|
})
|
||||||
void levelZeroCanAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
void levelZeroCanAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
||||||
int responseCode = access(resource, cookieLevel0);
|
int responseCode = access(resource, cookieLevel0);
|
||||||
@ -255,6 +257,8 @@ public class AccessControlTest {
|
|||||||
"/v1/query,400",
|
"/v1/query,400",
|
||||||
"/v1/errors,403",
|
"/v1/errors,403",
|
||||||
"/errors,403",
|
"/errors,403",
|
||||||
|
"/v1/network/listServers,403",
|
||||||
|
"/v1/network/performanceOverview?servers=[" + TestConstants.SERVER_UUID_STRING + "],403",
|
||||||
})
|
})
|
||||||
void levelOneCanAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
void levelOneCanAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
||||||
int responseCode = access(resource, cookieLevel1);
|
int responseCode = access(resource, cookieLevel1);
|
||||||
@ -315,6 +319,8 @@ public class AccessControlTest {
|
|||||||
"/v1/query,403",
|
"/v1/query,403",
|
||||||
"/v1/errors,403",
|
"/v1/errors,403",
|
||||||
"/errors,403",
|
"/errors,403",
|
||||||
|
"/v1/network/listServers,403",
|
||||||
|
"/v1/network/performanceOverview?servers=[" + TestConstants.SERVER_UUID_STRING + "],403",
|
||||||
})
|
})
|
||||||
void levelTwoCanAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
void levelTwoCanAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
||||||
int responseCode = access(resource, cookieLevel2);
|
int responseCode = access(resource, cookieLevel2);
|
||||||
@ -372,7 +378,9 @@ public class AccessControlTest {
|
|||||||
"/v1/players,403",
|
"/v1/players,403",
|
||||||
"/query,403",
|
"/query,403",
|
||||||
"/v1/filters,403",
|
"/v1/filters,403",
|
||||||
"/v1/query,403"
|
"/v1/query,403",
|
||||||
|
"/v1/network/listServers,403",
|
||||||
|
"/v1/network/performanceOverview?servers=[" + TestConstants.SERVER_UUID_STRING + "],403",
|
||||||
})
|
})
|
||||||
void levelHundredCanNotAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
void levelHundredCanNotAccess(String resource, String expectedResponseCode) throws NoSuchAlgorithmException, IOException, KeyManagementException {
|
||||||
int responseCode = access(resource, cookieLevel100);
|
int responseCode = access(resource, cookieLevel100);
|
||||||
|
Loading…
Reference in New Issue
Block a user