Optimized /network Server information queries

This commit is contained in:
Rsl1122 2019-08-27 16:43:07 +03:00
parent 539d817bf9
commit 517f479ad0
4 changed files with 107 additions and 44 deletions

View File

@ -24,6 +24,7 @@ import com.djrapitops.plan.utilities.html.graphs.line.Point;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -252,4 +253,11 @@ public class TPSMutator {
.mapToDouble(TPS::getPlayers)
.average().orElse(-1);
}
public Optional<TPS> getLast() {
if (tpsData.isEmpty()) return Optional.empty();
// else
tpsData.sort(new TPSComparator());
return Optional.of(tpsData.get(tpsData.size() - 1));
}
}

View File

@ -26,9 +26,7 @@ import com.djrapitops.plan.db.sql.tables.UsersTable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.UUID;
import java.util.*;
import static com.djrapitops.plan.db.sql.parsing.Sql.*;
@ -100,6 +98,31 @@ public class PlayerCountQueries {
return queryPlayerCount(sql, after, before);
}
public static Query<Map<UUID, Integer>> uniquePlayerCounts(long after, long before) {
String sql = SELECT + SessionsTable.SERVER_UUID + ",COUNT(DISTINCT " + SessionsTable.USER_UUID + ") as player_count" +
FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + "<=?" +
AND + SessionsTable.SESSION_START + ">=?" +
GROUP_BY + UserInfoTable.SERVER_UUID;
return new QueryStatement<Map<UUID, Integer>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setLong(1, before);
statement.setLong(2, after);
}
@Override
public Map<UUID, Integer> processResults(ResultSet set) throws SQLException {
Map<UUID, Integer> byServer = new HashMap<>();
while (set.next()) {
byServer.put(UUID.fromString(set.getString(UserInfoTable.SERVER_UUID)), set.getInt("player_count"));
}
return byServer;
}
};
}
/**
* Fetch a EpochMs - Count map of unique players on a server.
*
@ -233,6 +256,31 @@ public class PlayerCountQueries {
return queryPlayerCount(sql, after, before);
}
public static Query<Map<UUID, Integer>> newPlayerCounts(long after, long before) {
String sql = SELECT + UserInfoTable.SERVER_UUID + ",COUNT(1) as player_count" +
FROM + UserInfoTable.TABLE_NAME +
WHERE + UserInfoTable.REGISTERED + "<=?" +
AND + UserInfoTable.REGISTERED + ">=?" +
GROUP_BY + UserInfoTable.SERVER_UUID;
return new QueryStatement<Map<UUID, Integer>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setLong(1, before);
statement.setLong(2, after);
}
@Override
public Map<UUID, Integer> processResults(ResultSet set) throws SQLException {
Map<UUID, Integer> byServer = new HashMap<>();
while (set.next()) {
byServer.put(UUID.fromString(set.getString(UserInfoTable.SERVER_UUID)), set.getInt("player_count"));
}
return byServer;
}
};
}
/**
* Fetch a EpochMs - Count map of new players on a server.
*

View File

@ -63,16 +63,7 @@ public class TPSQueries {
List<TPS> data = new ArrayList<>();
while (set.next()) {
TPS tps = TPSBuilder.get()
.date(set.getLong(DATE))
.tps(set.getDouble(TPS))
.playersOnline(set.getInt(PLAYERS_ONLINE))
.usedCPU(set.getDouble(CPU_USAGE))
.usedMemory(set.getLong(RAM_USAGE))
.entities(set.getInt(ENTITIES))
.chunksLoaded(set.getInt(CHUNKS))
.freeDiskSpace(set.getLong(FREE_DISK))
.toTPS();
com.djrapitops.plan.data.container.TPS tps = extractTPS(set);
data.add(tps);
}
@ -81,6 +72,19 @@ public class TPSQueries {
};
}
public static TPS extractTPS(ResultSet set) throws SQLException {
return TPSBuilder.get()
.date(set.getLong(DATE))
.tps(set.getDouble(TPS))
.playersOnline(set.getInt(PLAYERS_ONLINE))
.usedCPU(set.getDouble(CPU_USAGE))
.usedMemory(set.getLong(RAM_USAGE))
.entities(set.getInt(ENTITIES))
.chunksLoaded(set.getInt(CHUNKS))
.freeDiskSpace(set.getLong(FREE_DISK))
.toTPS();
}
public static Query<List<TPS>> fetchTPSDataOfServer(long after, long before, UUID serverUUID) {
String sql = Select.all(TABLE_NAME)
.where(SERVER_ID + "=" + ServerTable.STATEMENT_SELECT_SERVER_ID)
@ -99,18 +103,7 @@ public class TPSQueries {
public List<TPS> processResults(ResultSet set) throws SQLException {
List<TPS> data = new ArrayList<>();
while (set.next()) {
TPS tps = TPSBuilder.get()
.date(set.getLong(DATE))
.tps(set.getDouble(TPS))
.playersOnline(set.getInt(PLAYERS_ONLINE))
.usedCPU(set.getDouble(CPU_USAGE))
.usedMemory(set.getLong(RAM_USAGE))
.entities(set.getInt(ENTITIES))
.chunksLoaded(set.getInt(CHUNKS))
.freeDiskSpace(set.getLong(FREE_DISK))
.toTPS();
TPS tps = extractTPS(set);
data.add(tps);
}
return data;
@ -146,15 +139,15 @@ public class TPSQueries {
};
}
public static Query<Map<UUID, List<DateObj<Integer>>>> fetchPlayersOnlineOfAllServersBut(long after, long before, UUID leaveOut) {
String sql = SELECT + ServerTable.SERVER_UUID + ',' + DATE + ',' + PLAYERS_ONLINE +
public static Query<Map<UUID, List<TPS>>> fetchTPSDataOfAllServersBut(long after, long before, UUID leaveOut) {
String sql = SELECT + '*' +
FROM + TABLE_NAME +
INNER_JOIN + ServerTable.TABLE_NAME + " on " + ServerTable.TABLE_NAME + '.' + ServerTable.SERVER_ID + '=' + SERVER_ID +
WHERE + ServerTable.SERVER_UUID + "!=?" +
AND + ServerTable.INSTALLED + "=?" +
AND + DATE + "<?" +
AND + DATE + ">?";
return new QueryStatement<Map<UUID, List<DateObj<Integer>>>>(sql, 1000) {
return new QueryStatement<Map<UUID, List<TPS>>>(sql, 1000) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, leaveOut.toString());
@ -164,16 +157,16 @@ public class TPSQueries {
}
@Override
public Map<UUID, List<DateObj<Integer>>> processResults(ResultSet set) throws SQLException {
Map<UUID, List<DateObj<Integer>>> byServer = new HashMap<>();
public Map<UUID, List<TPS>> processResults(ResultSet set) throws SQLException {
Map<UUID, List<TPS>> byServer = new HashMap<>();
while (set.next()) {
UUID serverUUID = UUID.fromString(set.getString(ServerTable.SERVER_UUID));
List<DateObj<Integer>> ofServer = byServer.getOrDefault(serverUUID, new ArrayList<>());
ofServer.add(new DateObj<>(set.getLong(DATE), set.getInt(PLAYERS_ONLINE)));
List<TPS> ofServer = byServer.getOrDefault(serverUUID, new ArrayList<>());
ofServer.add(extractTPS(set));
byServer.put(serverUUID, ofServer);
}
return byServer;
}
};

View File

@ -155,26 +155,37 @@ public class JSONFactory {
public List<Map<String, Object>> serversAsJSONMaps() {
Database db = dbSystem.getDatabase();
Map<UUID, Server> serverInformation = db.query(ServerQueries.fetchPlanServerInformation());
long now = System.currentTimeMillis();
long weekAgo = now - TimeUnit.DAYS.toMillis(7L);
long monthAgo = now - TimeUnit.DAYS.toMillis(30L);
Formatter<Long> year = formatters.yearLong();
Formatter<Double> decimals = formatters.decimals();
Formatter<Long> timeAmount = formatters.timeAmount();
Map<UUID, Server> serverInformation = db.query(ServerQueries.fetchPlanServerInformation());
UUID proxyUUID = serverInformation.values().stream()
.filter(Server::isProxy)
.findFirst()
.map(Server::getUuid).orElse(null);
Map<UUID, List<TPS>> tpsData = db.query(
TPSQueries.fetchTPSDataOfAllServersBut(monthAgo, now, proxyUUID)
);
Map<UUID, Integer> totalPlayerCounts = db.query(PlayerCountQueries.newPlayerCounts(0, now));
Map<UUID, Integer> newPlayerCounts = db.query(PlayerCountQueries.newPlayerCounts(monthAgo, now));
Map<UUID, Integer> uniquePlayerCounts = db.query(PlayerCountQueries.uniquePlayerCounts(monthAgo, now));
List<Map<String, Object>> servers = new ArrayList<>();
serverInformation.entrySet()
.stream() // Sort alphabetically
.sorted(Comparator.comparing(entry -> entry.getValue().getIdentifiableName().toLowerCase()))
.filter(entry -> entry.getValue().isNotProxy())
.forEach(entry -> {
if (entry.getValue().isProxy()) return;
UUID serverUUID = entry.getKey();
Map<String, Object> server = new HashMap<>();
server.put("name", entry.getValue().getIdentifiableName());
// TODO Optimize these queries
Optional<DateObj<Integer>> recentPeak = db.query(TPSQueries.fetchPeakPlayerCount(serverUUID, now - TimeUnit.DAYS.toMillis(2L)));
Optional<DateObj<Integer>> allTimePeak = db.query(TPSQueries.fetchAllTimePeakPlayerCount(serverUUID));
server.put("last_peak_date", recentPeak.map(DateObj::getDate).map(year).orElse("-"));
@ -182,17 +193,20 @@ public class JSONFactory {
server.put("last_peak_players", recentPeak.map(DateObj::getValue).orElse(0));
server.put("best_peak_players", allTimePeak.map(DateObj::getValue).orElse(0));
TPSMutator tpsMonth = new TPSMutator(db.query(TPSQueries.fetchTPSDataOfServer(now - TimeUnit.DAYS.toMillis(30L), now, serverUUID)));
server.put("playersOnline", tpsMonth.all().stream().map(tps -> new double[]{tps.getDate(), tps.getPlayers()}).toArray(double[][]::new));
server.put("players", db.query(PlayerCountQueries.newPlayerCount(0, now, serverUUID)));
server.put("new_players", db.query(PlayerCountQueries.newPlayerCount(weekAgo, now, serverUUID)));
server.put("unique_players", db.query(PlayerCountQueries.uniquePlayerCount(weekAgo, now, serverUUID)));
TPSMutator tpsMonth = new TPSMutator(tpsData.getOrDefault(serverUUID, Collections.emptyList()));
server.put("playersOnline", tpsMonth.all().stream()
.map(tps -> new double[]{tps.getDate(), tps.getPlayers()})
.toArray(double[][]::new));
server.put("players", totalPlayerCounts.getOrDefault(serverUUID, 0));
server.put("new_players", newPlayerCounts.getOrDefault(serverUUID, 0));
server.put("unique_players", uniquePlayerCounts.getOrDefault(serverUUID, 0));
TPSMutator tpsWeek = tpsMonth.filterDataBetween(weekAgo, now);
double averageTPS = tpsWeek.averageTPS();
server.put("avg_tps", averageTPS != -1 ? decimals.apply(averageTPS) : "No data");
server.put("low_tps_spikes", tpsWeek.lowTpsSpikeCount(config.getNumber(DisplaySettings.GRAPH_TPS_THRESHOLD_MED)));
server.put("downtime", timeAmount.apply(tpsWeek.serverDownTime()));
Optional<TPS> online = db.query(TPSQueries.fetchLatestTPSEntryForServer(serverUUID));
Optional<TPS> online = tpsWeek.getLast();
server.put("online", online.isPresent() ?
online.get().getDate() >= now - TimeUnit.MINUTES.toMillis(3L) ?
online.get().getPlayers() : "Possibly offline"