mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-21 05:50:18 +08:00
Rewrote TPSCounter Task
This commit is a squash of 8 optimization commits to TPSCounter. 1. Extracted duplicate code in TPSCounters to ServerSensors. - TPSCounter tasks now live inside common module - ServerTPSCounter and ProxyTPSCounter - Gathering methods are implemented with ServerSensor interface: Player count, TPS, Entity count, Chunk count - ServerProperties#getOnlinePlayers was replaced with ServerSensor - Fixed sonar smells: "Hiding field" in TPSStoreTransaction & NavLink 2. Optimizations down to 0.15ms / run - Optimized entity+chunk count (same for loop) - Added warm-up for system resource methods - Removed Stream API usages - Removed List copy operation - Entities & chunks only count once per minute - CPU & RAM averages now produced with Average class - Maximum player count per minute now produced with Maximum class Affects issues: - Fixed #1289
This commit is contained in:
parent
8a059ced0b
commit
c87f981d6a
@ -54,6 +54,8 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
println "Building artifact for version $fullVersion"
|
||||
|
||||
subprojects {
|
||||
// Build plugins
|
||||
apply plugin: "java"
|
||||
|
@ -20,22 +20,21 @@ import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
|
||||
import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask;
|
||||
import com.djrapitops.plan.gathering.ShutdownHook;
|
||||
import com.djrapitops.plan.gathering.timed.BukkitPingCounter;
|
||||
import com.djrapitops.plan.gathering.timed.BukkitTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.PaperTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.ServerTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.TPSCounter;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
||||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||
import com.djrapitops.plan.settings.upkeep.ConfigStoreTask;
|
||||
import com.djrapitops.plan.storage.upkeep.DBCleanTask;
|
||||
import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -55,7 +54,7 @@ public class BukkitTaskSystem extends TaskSystem {
|
||||
private final ConfigStoreTask configStoreTask;
|
||||
private final DBCleanTask dbCleanTask;
|
||||
private final ExtensionServerMethodCallerTask extensionServerMethodCallerTask;
|
||||
private BukkitTPSCounter tpsCounter;
|
||||
private TPSCounter tpsCounter;
|
||||
|
||||
@Inject
|
||||
public BukkitTaskSystem(
|
||||
@ -64,8 +63,7 @@ public class BukkitTaskSystem extends TaskSystem {
|
||||
ShutdownHook shutdownHook,
|
||||
RunnableFactory runnableFactory,
|
||||
|
||||
PaperTPSCounter paperTPSCountTimer,
|
||||
BukkitTPSCounter bukkitTPSCountTimer,
|
||||
ServerTPSCounter<World> tpsCounter,
|
||||
BukkitPingCounter pingCounter,
|
||||
ExtensionServerMethodCallerTask extensionServerMethodCallerTask,
|
||||
|
||||
@ -80,7 +78,7 @@ public class BukkitTaskSystem extends TaskSystem {
|
||||
this.shutdownHook = shutdownHook;
|
||||
this.jsonCacheCleanTask = jsonCacheCleanTask;
|
||||
|
||||
this.tpsCounter = Check.isPaperAvailable() ? paperTPSCountTimer : bukkitTPSCountTimer;
|
||||
this.tpsCounter = tpsCounter;
|
||||
this.pingCounter = pingCounter;
|
||||
this.extensionServerMethodCallerTask = extensionServerMethodCallerTask;
|
||||
|
||||
@ -139,6 +137,6 @@ public class BukkitTaskSystem extends TaskSystem {
|
||||
@Override
|
||||
public void disable() {
|
||||
super.disable();
|
||||
Optional.ofNullable(Bukkit.getScheduler()).ifPresent(scheduler -> scheduler.cancelTasks(plugin));
|
||||
Bukkit.getScheduler().cancelTasks(plugin);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.gathering;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import org.bukkit.World;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class BukkitSensor implements ServerSensor<World> {
|
||||
|
||||
private final Plan plugin;
|
||||
private final boolean hasPaper;
|
||||
|
||||
@Inject
|
||||
public BukkitSensor(
|
||||
Plan plugin
|
||||
) {
|
||||
this.plugin = plugin;
|
||||
hasPaper = Check.isPaperAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDirectTPS() {
|
||||
return hasPaper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTPS() {
|
||||
return plugin.getServer().getTPS()[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkCount(World world) {
|
||||
if (hasPaper) {
|
||||
try {
|
||||
return getChunkCountPaperWay(world);
|
||||
} catch (BootstrapMethodError | NoSuchMethodError e) {
|
||||
// Use spigot method
|
||||
}
|
||||
}
|
||||
return getChunkCountSpigotWay(world);
|
||||
}
|
||||
|
||||
private int getChunkCountSpigotWay(World world) {
|
||||
return world.getLoadedChunks().length;
|
||||
}
|
||||
|
||||
private int getChunkCountPaperWay(World world) {
|
||||
return world.getChunkCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityCount(World world) {
|
||||
if (hasPaper) {
|
||||
try {
|
||||
return getEntitiesPaperWay(world);
|
||||
} catch (BootstrapMethodError | NoSuchMethodError e) {
|
||||
// Use spigot method
|
||||
}
|
||||
}
|
||||
return getEntitiesSpigotWay(world);
|
||||
}
|
||||
|
||||
private int getEntitiesSpigotWay(World world) {
|
||||
return world.getEntities().size();
|
||||
}
|
||||
|
||||
private int getEntitiesPaperWay(World world) {
|
||||
return world.getEntityCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayerCount() {
|
||||
return plugin.getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<World> getWorlds() {
|
||||
return plugin.getServer().getWorlds();
|
||||
}
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
/*
|
||||
* 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.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.gathering.SystemUsage;
|
||||
import com.djrapitops.plan.gathering.domain.TPS;
|
||||
import com.djrapitops.plan.gathering.domain.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.identification.properties.ServerProperties;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import org.bukkit.World;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Singleton
|
||||
public class BukkitTPSCounter extends TPSCounter {
|
||||
|
||||
protected final Plan plugin;
|
||||
private ServerProperties serverProperties;
|
||||
private long lastCheckNano;
|
||||
|
||||
@Inject
|
||||
public BukkitTPSCounter(
|
||||
Plan plugin,
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
ServerProperties serverProperties,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(dbSystem, serverInfo, logger, errorHandler);
|
||||
this.plugin = plugin;
|
||||
this.serverProperties = serverProperties;
|
||||
lastCheckNano = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNewTPSEntry(long nanoTime, long now) {
|
||||
long diff = nanoTime - lastCheckNano;
|
||||
|
||||
lastCheckNano = nanoTime;
|
||||
|
||||
if (diff > nanoTime) { // First run's diff = nanoTime + 1, no calc possible.
|
||||
logger.debug("First run of TPSCountTimer Task.");
|
||||
return;
|
||||
}
|
||||
|
||||
history.add(calculateTPS(diff, now));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the TPS
|
||||
*
|
||||
* @param diff The time difference between the last run and the new run
|
||||
* @param now The time right now
|
||||
* @return the TPS
|
||||
*/
|
||||
private TPS calculateTPS(long diff, long now) {
|
||||
double averageCPUUsage = getCPUUsage();
|
||||
long usedMemory = SystemUsage.getUsedMemory();
|
||||
long freeDiskSpace = getFreeDiskSpace();
|
||||
|
||||
int playersOnline = serverProperties.getOnlinePlayers();
|
||||
latestPlayersOnline = playersOnline;
|
||||
int loadedChunks = getLoadedChunks();
|
||||
int entityCount = getEntityCount();
|
||||
|
||||
return getTPS(diff, now, averageCPUUsage, usedMemory, entityCount, loadedChunks, playersOnline, freeDiskSpace);
|
||||
}
|
||||
|
||||
protected TPS getTPS(long diff, long now,
|
||||
double cpuUsage, long usedMemory,
|
||||
int entityCount, int chunksLoaded,
|
||||
int playersOnline, long freeDiskSpace) {
|
||||
long difference = diff;
|
||||
if (difference < TimeUnit.SECONDS.toNanos(1L)) { // No tick count above 20
|
||||
difference = TimeUnit.SECONDS.toNanos(1L);
|
||||
}
|
||||
|
||||
long twentySeconds = TimeUnit.SECONDS.toNanos(20L);
|
||||
while (difference > twentySeconds) {
|
||||
// Add 0 TPS since more than 20 ticks has passed.
|
||||
history.add(TPSBuilder.get()
|
||||
.date(now)
|
||||
.tps(0)
|
||||
.playersOnline(playersOnline)
|
||||
.usedCPU(cpuUsage)
|
||||
.usedMemory(usedMemory)
|
||||
.entities(entityCount)
|
||||
.chunksLoaded(chunksLoaded)
|
||||
.freeDiskSpace(freeDiskSpace)
|
||||
.toTPS());
|
||||
difference -= twentySeconds;
|
||||
}
|
||||
|
||||
double tpsN = twentySeconds * 1.0 / difference;
|
||||
|
||||
return TPSBuilder.get()
|
||||
.date(now)
|
||||
.tps(tpsN)
|
||||
.playersOnline(playersOnline)
|
||||
.usedCPU(cpuUsage)
|
||||
.usedMemory(usedMemory)
|
||||
.entities(entityCount)
|
||||
.chunksLoaded(chunksLoaded)
|
||||
.freeDiskSpace(freeDiskSpace)
|
||||
.toTPS();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of loaded chunks
|
||||
*
|
||||
* @return amount of loaded chunks
|
||||
*/
|
||||
private int getLoadedChunks() {
|
||||
int sum = 0;
|
||||
for (World world : plugin.getServer().getWorlds()) {
|
||||
sum += world.getLoadedChunks().length;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of entities on the server for Bukkit / Spigot
|
||||
*
|
||||
* @return amount of entities
|
||||
*/
|
||||
protected int getEntityCount() {
|
||||
int sum = 0;
|
||||
for (World world : plugin.getServer().getWorlds()) {
|
||||
sum += world.getEntities().size();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.gathering.domain.TPS;
|
||||
import com.djrapitops.plan.gathering.domain.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import org.bukkit.World;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class PaperTPSCounter extends BukkitTPSCounter {
|
||||
|
||||
@Inject
|
||||
public PaperTPSCounter(
|
||||
Plan plugin,
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(plugin, dbSystem, serverInfo, serverInfo.getServerProperties(), logger, errorHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TPS getTPS(long diff, long now, double cpuUsage, long usedMemory, int entityCount, int chunksLoaded, int playersOnline, long freeDiskSpace) {
|
||||
double tps;
|
||||
try {
|
||||
tps = plugin.getServer().getTPS()[0];
|
||||
} catch (NoSuchMethodError e) {
|
||||
// This method is from Paper
|
||||
return super.getTPS(diff, now, cpuUsage, usedMemory, entityCount, chunksLoaded, playersOnline, freeDiskSpace);
|
||||
}
|
||||
|
||||
if (tps > 20) {
|
||||
tps = 20;
|
||||
}
|
||||
|
||||
return TPSBuilder.get()
|
||||
.date(now)
|
||||
.tps(tps)
|
||||
.playersOnline(playersOnline)
|
||||
.usedCPU(cpuUsage)
|
||||
.usedMemory(usedMemory)
|
||||
.entities(entityCount)
|
||||
.chunksLoaded(chunksLoaded)
|
||||
.freeDiskSpace(freeDiskSpace)
|
||||
.toTPS();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getEntityCount() {
|
||||
try {
|
||||
return plugin.getServer().getWorlds().stream().mapToInt(World::getEntityCount).sum();
|
||||
} catch (BootstrapMethodError | NoSuchMethodError e) {
|
||||
return super.getEntityCount();
|
||||
}
|
||||
}
|
||||
}
|
@ -32,8 +32,7 @@ public class BukkitServerProperties extends ServerProperties {
|
||||
server.getVersion(),
|
||||
server.getBukkitVersion(),
|
||||
server::getIp,
|
||||
server.getMaxPlayers(),
|
||||
() -> server.getOnlinePlayers().size()
|
||||
server.getMaxPlayers()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@ package com.djrapitops.plan.modules.bukkit;
|
||||
import com.djrapitops.plan.BukkitServerShutdownSave;
|
||||
import com.djrapitops.plan.BukkitTaskSystem;
|
||||
import com.djrapitops.plan.TaskSystem;
|
||||
import com.djrapitops.plan.gathering.BukkitSensor;
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.ServerShutdownSave;
|
||||
import com.djrapitops.plan.gathering.importing.BukkitImportSystem;
|
||||
import com.djrapitops.plan.gathering.importing.ImportSystem;
|
||||
@ -32,9 +34,10 @@ import com.djrapitops.plan.storage.database.BukkitDBSystem;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import org.bukkit.World;
|
||||
|
||||
/**
|
||||
* Module for binding Bukkit specific classes to the interface implementations.
|
||||
* Module for binding Bukkit specific classes as interface implementations.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@ -42,24 +45,29 @@ import dagger.Module;
|
||||
public interface BukkitSuperClassBindingModule {
|
||||
|
||||
@Binds
|
||||
ServerInfo bindBukkitServerInfo(ServerServerInfo serverServerInfo);
|
||||
ServerInfo bindServerInfo(ServerServerInfo serverInfo);
|
||||
|
||||
@Binds
|
||||
DBSystem bindBukkitDatabaseSystem(BukkitDBSystem dbSystem);
|
||||
DBSystem bindDBSystem(BukkitDBSystem dbSystem);
|
||||
|
||||
@Binds
|
||||
ConfigSystem bindBukkitConfigSystem(BukkitConfigSystem bukkitConfigSystem);
|
||||
ConfigSystem bindConfigSystem(BukkitConfigSystem configSystem);
|
||||
|
||||
@Binds
|
||||
TaskSystem bindBukkitTaskSystem(BukkitTaskSystem bukkitTaskSystem);
|
||||
TaskSystem bindTaskSystem(BukkitTaskSystem taskSystem);
|
||||
|
||||
@Binds
|
||||
ListenerSystem bindBukkitListenerSystem(BukkitListenerSystem bukkitListenerSystem);
|
||||
ListenerSystem bindListenerSystem(BukkitListenerSystem listenerSystem);
|
||||
|
||||
@Binds
|
||||
ImportSystem bindImportSystem(BukkitImportSystem bukkitImportSystem);
|
||||
ImportSystem bindImportSystem(BukkitImportSystem importSystem);
|
||||
|
||||
@Binds
|
||||
ServerShutdownSave bindBukkitServerShutdownSave(BukkitServerShutdownSave bukkitServerShutdownSave);
|
||||
ServerShutdownSave bindServerShutdownSave(BukkitServerShutdownSave shutdownSave);
|
||||
|
||||
@Binds
|
||||
ServerSensor<World> bindServerSensor(BukkitSensor sensor);
|
||||
|
||||
@Binds
|
||||
ServerSensor<?> bindGenericsServerSensor(ServerSensor<World> sensor);
|
||||
}
|
@ -19,7 +19,8 @@ package com.djrapitops.plan;
|
||||
import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
|
||||
import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask;
|
||||
import com.djrapitops.plan.gathering.timed.BungeePingCounter;
|
||||
import com.djrapitops.plan.gathering.timed.BungeeTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.ProxyTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.TPSCounter;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
||||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||
@ -43,7 +44,7 @@ public class BungeeTaskSystem extends TaskSystem {
|
||||
|
||||
private final PlanBungee plugin;
|
||||
private final PlanConfig config;
|
||||
private final BungeeTPSCounter tpsCounter;
|
||||
private final TPSCounter tpsCounter;
|
||||
private final BungeePingCounter pingCounter;
|
||||
private final LogsFolderCleanTask logsFolderCleanTask;
|
||||
private final NetworkConfigStoreTask networkConfigStoreTask;
|
||||
@ -56,7 +57,7 @@ public class BungeeTaskSystem extends TaskSystem {
|
||||
PlanBungee plugin,
|
||||
PlanConfig config,
|
||||
RunnableFactory runnableFactory,
|
||||
BungeeTPSCounter tpsCounter,
|
||||
ProxyTPSCounter tpsCounter,
|
||||
BungeePingCounter pingCounter,
|
||||
LogsFolderCleanTask logsFolderCleanTask,
|
||||
NetworkConfigStoreTask networkConfigStoreTask,
|
||||
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.gathering;
|
||||
|
||||
import com.djrapitops.plan.PlanBungee;
|
||||
import com.djrapitops.plan.identification.properties.RedisCheck;
|
||||
import com.djrapitops.plan.identification.properties.RedisPlayersOnlineSupplier;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
@Singleton
|
||||
public class BungeeSensor implements ServerSensor<Object> {
|
||||
|
||||
private final IntSupplier onlinePlayerCountSupplier;
|
||||
|
||||
@Inject
|
||||
public BungeeSensor(PlanBungee plugin) {
|
||||
onlinePlayerCountSupplier = RedisCheck.isClassAvailable() ? new RedisPlayersOnlineSupplier() : plugin.getProxy()::getOnlineCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDirectTPS() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayerCount() {
|
||||
return onlinePlayerCountSupplier.getAsInt();
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.gathering.SystemUsage;
|
||||
import com.djrapitops.plan.gathering.domain.TPS;
|
||||
import com.djrapitops.plan.gathering.domain.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.identification.properties.ServerProperties;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class BungeeTPSCounter extends TPSCounter {
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
|
||||
@Inject
|
||||
public BungeeTPSCounter(
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
ServerProperties serverProperties,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(dbSystem, serverInfo, logger, errorHandler);
|
||||
this.serverProperties = serverProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNewTPSEntry(long nanoTime, long now) {
|
||||
int onlineCount = serverProperties.getOnlinePlayers();
|
||||
TPS tps = TPSBuilder.get()
|
||||
.date(now)
|
||||
.playersOnline(onlineCount)
|
||||
.usedCPU(getCPUUsage())
|
||||
.usedMemory(SystemUsage.getUsedMemory())
|
||||
.entities(-1)
|
||||
.chunksLoaded(-1)
|
||||
.freeDiskSpace(getFreeDiskSpace())
|
||||
.toTPS();
|
||||
|
||||
history.add(tps);
|
||||
latestPlayersOnline = onlineCount;
|
||||
}
|
||||
}
|
@ -36,8 +36,7 @@ public class BungeeServerProperties extends ServerProperties {
|
||||
server.getVersion(),
|
||||
server.getVersion(),
|
||||
() -> config.get(ProxySettings.IP),
|
||||
server.getConfig().getPlayerLimit(),
|
||||
RedisCheck.isClassAvailable() ? new RedisPlayersOnlineSupplier() : server::getOnlineCount
|
||||
server.getConfig().getPlayerLimit()
|
||||
);
|
||||
}
|
||||
}
|
@ -18,6 +18,8 @@ package com.djrapitops.plan.modules.bungee;
|
||||
|
||||
import com.djrapitops.plan.BungeeTaskSystem;
|
||||
import com.djrapitops.plan.TaskSystem;
|
||||
import com.djrapitops.plan.gathering.BungeeSensor;
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.listeners.BungeeListenerSystem;
|
||||
import com.djrapitops.plan.gathering.listeners.ListenerSystem;
|
||||
import com.djrapitops.plan.identification.BungeeServerInfo;
|
||||
@ -26,7 +28,7 @@ import dagger.Binds;
|
||||
import dagger.Module;
|
||||
|
||||
/**
|
||||
* Module for binding Bungee specific classes to the interface implementations.
|
||||
* Module for binding Bungee specific classes as interface implementations.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@ -34,11 +36,14 @@ import dagger.Module;
|
||||
public interface BungeeSuperClassBindingModule {
|
||||
|
||||
@Binds
|
||||
ServerInfo bindBungeeServerInfo(BungeeServerInfo bungeeServerInfo);
|
||||
ServerInfo bindServerInfo(BungeeServerInfo serverInfo);
|
||||
|
||||
@Binds
|
||||
TaskSystem bindBungeeTaskSystem(BungeeTaskSystem bungeeTaskSystem);
|
||||
TaskSystem bindTaskSystem(BungeeTaskSystem taskSystem);
|
||||
|
||||
@Binds
|
||||
ListenerSystem bindBungeeListenerSystem(BungeeListenerSystem bungeeListenerSystem);
|
||||
ListenerSystem bindListenerSystem(BungeeListenerSystem listenerSystem);
|
||||
|
||||
@Binds
|
||||
ServerSensor<Object> bindServerSensor(BungeeSensor sensor);
|
||||
}
|
@ -40,6 +40,8 @@ import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
|
||||
import com.djrapitops.plan.storage.file.PlanFiles;
|
||||
import com.djrapitops.plan.version.VersionCheckSystem;
|
||||
import com.djrapitops.plugin.benchmarking.Benchmark;
|
||||
import com.djrapitops.plugin.benchmarking.Timings;
|
||||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
@ -79,6 +81,7 @@ public class PlanSystem implements SubSystem {
|
||||
private final QueryServiceImplementation queryService;
|
||||
private final SettingsServiceImplementation settingsService;
|
||||
private final PluginLogger logger;
|
||||
private final Timings timings;
|
||||
private final ErrorHandler errorHandler;
|
||||
|
||||
@Inject
|
||||
@ -101,7 +104,7 @@ public class PlanSystem implements SubSystem {
|
||||
QueryServiceImplementation queryService,
|
||||
SettingsServiceImplementation settingsService,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler,
|
||||
Timings timings, ErrorHandler errorHandler,
|
||||
PlanAPI.PlanAPIHolder apiHolder
|
||||
) {
|
||||
this.files = files;
|
||||
@ -122,6 +125,7 @@ public class PlanSystem implements SubSystem {
|
||||
this.queryService = queryService;
|
||||
this.settingsService = settingsService;
|
||||
this.logger = logger;
|
||||
this.timings = timings;
|
||||
this.errorHandler = errorHandler;
|
||||
|
||||
logger.log(L.INFO_COLOR,
|
||||
@ -179,7 +183,13 @@ public class PlanSystem implements SubSystem {
|
||||
|
||||
private void enableSystems(SubSystem... systems) throws EnableException {
|
||||
for (SubSystem system : systems) {
|
||||
logger.debug("Enabling: " + system.getClass().getSimpleName());
|
||||
timings.start("subsystem-enable");
|
||||
system.enable();
|
||||
timings.end("subsystem-enable")
|
||||
.map(Benchmark::toDurationString)
|
||||
.map(duration -> "Took " + duration)
|
||||
.ifPresent(logger::debug);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,20 +59,20 @@ public class NavLink {
|
||||
}
|
||||
|
||||
public String toHtml() {
|
||||
String tabID = getTabID();
|
||||
String usedId = getUsedTabId();
|
||||
if (collapsed) {
|
||||
return "<a class=\"collapse-item nav-button\" href=\"#tab-" + tabID + "\">" +
|
||||
return "<a class=\"collapse-item nav-button\" href=\"#tab-" + usedId + "\">" +
|
||||
icon.toHtml() + ' ' +
|
||||
tabName + "</a>";
|
||||
}
|
||||
return "<li class=\"nav-item nav-button\">" +
|
||||
"<a class=\"nav-link\" href=\"#tab-" + tabID + "\">" +
|
||||
"<a class=\"nav-link\" href=\"#tab-" + usedId + "\">" +
|
||||
icon.toHtml() +
|
||||
"<span>" + tabName + "</span></a>" +
|
||||
"</li>";
|
||||
}
|
||||
|
||||
private String getTabID() {
|
||||
private String getUsedTabId() {
|
||||
return format(tabID != null ? tabID : tabName);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.domain.DateObj;
|
||||
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.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.domain.TPS;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
@ -58,6 +59,7 @@ public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<Strin
|
||||
private final Locale locale;
|
||||
private final DBSystem dbSystem;
|
||||
private final ServerInfo serverInfo;
|
||||
private final ServerSensor<?> serverSensor;
|
||||
|
||||
private final Formatter<Long> timeAmount;
|
||||
private final Formatter<Double> decimals;
|
||||
@ -70,12 +72,14 @@ public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<Strin
|
||||
Locale locale,
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
ServerSensor<?> serverSensor,
|
||||
Formatters formatters
|
||||
) {
|
||||
this.config = config;
|
||||
this.locale = locale;
|
||||
this.dbSystem = dbSystem;
|
||||
this.serverInfo = serverInfo;
|
||||
this.serverSensor = serverSensor;
|
||||
|
||||
year = formatters.year();
|
||||
day = formatters.dayLong();
|
||||
@ -149,7 +153,7 @@ public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<Strin
|
||||
|
||||
private Object getOnlinePlayers(UUID serverUUID, Database db) {
|
||||
return serverUUID.equals(serverInfo.getServerUUID())
|
||||
? serverInfo.getServerProperties().getOnlinePlayers()
|
||||
? serverSensor.getOnlinePlayerCount()
|
||||
: db.query(TPSQueries.fetchLatestTPSEntryForServer(serverUUID))
|
||||
.map(TPS::getPlayers).map(Object::toString)
|
||||
.orElse(locale.get(GenericLang.UNKNOWN).toString());
|
||||
|
@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.domain.DateObj;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||
import com.djrapitops.plan.delivery.rendering.json.Trend;
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||
@ -51,6 +52,7 @@ public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<Str
|
||||
private final PlanConfig config;
|
||||
private final DBSystem dbSystem;
|
||||
private final ServerInfo serverInfo;
|
||||
private final ServerSensor<?> serverSensor;
|
||||
private final Formatter<Long> timeAmount;
|
||||
private final Formatter<DateHolder> year;
|
||||
|
||||
@ -59,11 +61,13 @@ public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<Str
|
||||
PlanConfig config,
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
ServerSensor<?> serverSensor,
|
||||
Formatters formatters
|
||||
) {
|
||||
this.config = config;
|
||||
this.dbSystem = dbSystem;
|
||||
this.serverInfo = serverInfo;
|
||||
this.serverSensor = serverSensor;
|
||||
|
||||
year = formatters.year();
|
||||
day = formatters.dayLong();
|
||||
@ -109,7 +113,7 @@ public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<Str
|
||||
Integer userCount = db.query(PlayerCountQueries.newPlayerCount(0L, now));
|
||||
numbers.put("total_players", userCount);
|
||||
numbers.put("regular_players", db.query(NetworkActivityIndexQueries.fetchRegularPlayerCount(now, playtimeThreshold)));
|
||||
numbers.put("online_players", getOnlinePlayers());
|
||||
numbers.put("online_players", serverSensor.getOnlinePlayerCount());
|
||||
UUID serverUUID = serverInfo.getServerUUID();
|
||||
Optional<DateObj<Integer>> lastPeak = db.query(TPSQueries.fetchPeakPlayerCount(serverUUID, twoDaysAgo));
|
||||
Optional<DateObj<Integer>> allTimePeak = db.query(TPSQueries.fetchAllTimePeakPlayerCount(serverUUID));
|
||||
@ -127,10 +131,6 @@ public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<Str
|
||||
return numbers;
|
||||
}
|
||||
|
||||
private Object getOnlinePlayers() {
|
||||
return serverInfo.getServerProperties().getOnlinePlayers();
|
||||
}
|
||||
|
||||
private Map<String, Object> createWeeksMap() {
|
||||
Database db = dbSystem.getDatabase();
|
||||
long now = System.currentTimeMillis();
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.gathering;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Allows sensing values from different server platforms.
|
||||
*
|
||||
* @param <W> Type of the class representing a minecraft world.
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public interface ServerSensor<W> {
|
||||
|
||||
/**
|
||||
* Check if server platform provides TPS calculation.
|
||||
*
|
||||
* @return false if the server doesn't count TPS.
|
||||
*/
|
||||
boolean supportsDirectTPS();
|
||||
|
||||
int getOnlinePlayerCount();
|
||||
|
||||
default double getTPS() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the worlds running on the server platform.
|
||||
*
|
||||
* @return Empty collection if the platform doesn't support worlds.
|
||||
*/
|
||||
default Iterable<W> getWorlds() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
default int getChunkCount(W world) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
default int getEntityCount(W world) {
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -48,7 +48,7 @@ public class SystemUsage {
|
||||
* - On some OSes CPU usage information is not available, and system load average is used instead.
|
||||
* - On some OSes system load average is not available.
|
||||
*
|
||||
* @return 0.0 to 1.0 if CPU, or system load average, or -1 if nothing is available.
|
||||
* @return 0.0 to 100.0 if CPU, or system load average, or -1 if nothing is available.
|
||||
*/
|
||||
public static double getAverageSystemLoad() {
|
||||
double averageUsage;
|
||||
@ -64,7 +64,7 @@ public class SystemUsage {
|
||||
if (averageUsage < 0) {
|
||||
averageUsage = -1; // If unavailable, getSystemLoadAverage() returns -1
|
||||
}
|
||||
return averageUsage;
|
||||
return averageUsage * 100.0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.SystemUsage;
|
||||
import com.djrapitops.plan.gathering.domain.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.TPSStoreTransaction;
|
||||
import com.djrapitops.plan.utilities.analysis.Average;
|
||||
import com.djrapitops.plan.utilities.analysis.Maximum;
|
||||
import com.djrapitops.plan.utilities.analysis.TimerAverage;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* TPSCounter extension for game server platforms.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@Singleton
|
||||
public class ProxyTPSCounter extends TPSCounter {
|
||||
|
||||
private final ServerSensor<Object> serverSensor;
|
||||
private final DBSystem dbSystem;
|
||||
private final ServerInfo serverInfo;
|
||||
private Maximum.ForInteger playersOnline;
|
||||
private Average cpu;
|
||||
private TimerAverage ram;
|
||||
|
||||
@Inject
|
||||
public ProxyTPSCounter(
|
||||
ServerSensor<Object> serverSensor,
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(logger, errorHandler);
|
||||
|
||||
this.serverSensor = serverSensor;
|
||||
this.dbSystem = dbSystem;
|
||||
this.serverInfo = serverInfo;
|
||||
playersOnline = new Maximum.ForInteger(0);
|
||||
cpu = new Average();
|
||||
ram = new TimerAverage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pulse() {
|
||||
long time = System.currentTimeMillis();
|
||||
boolean shouldSave = ram.add(time, SystemUsage.getUsedMemory());
|
||||
playersOnline.add(serverSensor.getOnlinePlayerCount());
|
||||
cpu.add(SystemUsage.getAverageSystemLoad());
|
||||
if (shouldSave) save(time);
|
||||
}
|
||||
|
||||
private void save(long time) {
|
||||
long timeLastMinute = time - TimeUnit.MINUTES.toMillis(1L);
|
||||
int maxPlayers = playersOnline.getMaxAndReset();
|
||||
double averageCPU = cpu.getAverageAndReset();
|
||||
long averageRAM = (long) ram.getAverageAndReset(time);
|
||||
long freeDiskSpace = getFreeDiskSpace();
|
||||
|
||||
dbSystem.getDatabase().executeTransaction(new TPSStoreTransaction(
|
||||
serverInfo.getServerUUID(),
|
||||
TPSBuilder.get()
|
||||
.date(timeLastMinute)
|
||||
.playersOnline(maxPlayers)
|
||||
.usedCPU(averageCPU)
|
||||
.usedMemory(averageRAM)
|
||||
.freeDiskSpace(freeDiskSpace)
|
||||
.toTPS()
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.SystemUsage;
|
||||
import com.djrapitops.plan.gathering.domain.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.TPSStoreTransaction;
|
||||
import com.djrapitops.plan.utilities.analysis.Average;
|
||||
import com.djrapitops.plan.utilities.analysis.Maximum;
|
||||
import com.djrapitops.plan.utilities.analysis.TimerAverage;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* TPSCounter extension for game server platforms.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@Singleton
|
||||
public class ServerTPSCounter<W> extends TPSCounter {
|
||||
|
||||
private final boolean noDirectTPS;
|
||||
private final ServerSensor<W> serverSensor;
|
||||
private final DBSystem dbSystem;
|
||||
private final ServerInfo serverInfo;
|
||||
private TPSCalculator indirectTPS;
|
||||
private TimerAverage directTPS;
|
||||
private Maximum.ForInteger playersOnline;
|
||||
private Average cpu;
|
||||
private Average ram;
|
||||
|
||||
@Inject
|
||||
public ServerTPSCounter(
|
||||
ServerSensor<W> serverSensor,
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(logger, errorHandler);
|
||||
|
||||
noDirectTPS = !serverSensor.supportsDirectTPS();
|
||||
this.serverSensor = serverSensor;
|
||||
this.dbSystem = dbSystem;
|
||||
this.serverInfo = serverInfo;
|
||||
if (noDirectTPS) {
|
||||
indirectTPS = new TPSCalculator();
|
||||
} else {
|
||||
directTPS = new TimerAverage();
|
||||
}
|
||||
playersOnline = new Maximum.ForInteger(0);
|
||||
cpu = new Average();
|
||||
ram = new Average();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pulse() {
|
||||
long time = System.currentTimeMillis();
|
||||
Optional<Double> result = pulseTPS(time);
|
||||
playersOnline.add(serverSensor.getOnlinePlayerCount());
|
||||
cpu.add(SystemUsage.getAverageSystemLoad());
|
||||
ram.add(SystemUsage.getUsedMemory());
|
||||
result.ifPresent(tps -> save(tps, time));
|
||||
}
|
||||
|
||||
private void save(double averageTPS, long time) {
|
||||
long timeLastMinute = time - TimeUnit.MINUTES.toMillis(1L);
|
||||
int maxPlayers = playersOnline.getMaxAndReset();
|
||||
double averageCPU = cpu.getAverageAndReset();
|
||||
long averageRAM = (long) ram.getAverageAndReset();
|
||||
int entityCount = 0;
|
||||
int chunkCount = 0;
|
||||
for (W world : serverSensor.getWorlds()) {
|
||||
entityCount += serverSensor.getEntityCount(world);
|
||||
chunkCount += serverSensor.getChunkCount(world);
|
||||
}
|
||||
long freeDiskSpace = getFreeDiskSpace();
|
||||
|
||||
dbSystem.getDatabase().executeTransaction(new TPSStoreTransaction(
|
||||
serverInfo.getServerUUID(),
|
||||
TPSBuilder.get()
|
||||
.date(timeLastMinute)
|
||||
.tps(averageTPS)
|
||||
.playersOnline(maxPlayers)
|
||||
.usedCPU(averageCPU)
|
||||
.usedMemory(averageRAM)
|
||||
.entities(entityCount)
|
||||
.chunksLoaded(chunkCount)
|
||||
.freeDiskSpace(freeDiskSpace)
|
||||
.toTPS()
|
||||
));
|
||||
}
|
||||
|
||||
public Optional<Double> pulseTPS(long time) {
|
||||
if (noDirectTPS) {
|
||||
return indirectTPS.pulse(time);
|
||||
} else {
|
||||
if (directTPS.add(time, serverSensor.getTPS())) {
|
||||
return Optional.of(directTPS.getAverageAndReset(time));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.utilities.analysis.TimerAverage;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Utility for calculating TPS using nano time.
|
||||
* <p>
|
||||
* Math:
|
||||
* - Minecraft runs 20 ticks / second, 1 tick = 50ms
|
||||
* - To return 20 ticks, 1 second is expected
|
||||
* - If the call time is less than 1 second, the TPS is still 20, excess is not counted.
|
||||
* - If the call time is more than 1 second, the TPS is below 20
|
||||
* - If 2 seconds, TPS is 10
|
||||
* - If 4 seconds, TPS is 5
|
||||
* - If 20 seconds, TPS is 1
|
||||
* - If more than 20 seconds, TPS is 0 for 20 seconds and then according to the other rules.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TPSCalculator {
|
||||
|
||||
public static final long SECOND_NS = TimeUnit.SECONDS.toNanos(1L);
|
||||
|
||||
private long maxBeforeZeroTPS;
|
||||
private long lastPulse;
|
||||
|
||||
private TimerAverage averager;
|
||||
|
||||
public TPSCalculator() {
|
||||
maxBeforeZeroTPS = SECOND_NS * 20L; // 20 ticks
|
||||
lastPulse = -1;
|
||||
|
||||
averager = new TimerAverage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulse the TPS clock.
|
||||
*
|
||||
* @param time Current epoch ms
|
||||
* @return Average TPS for the minute, or empty.
|
||||
*/
|
||||
public Optional<Double> pulse(long time) {
|
||||
boolean firstRun = lastPulse < 0;
|
||||
long currentPulse = System.nanoTime();
|
||||
long difference = currentPulse - lastPulse;
|
||||
lastPulse = currentPulse;
|
||||
if (firstRun) {
|
||||
return Optional.empty(); // Can not calculate on first check.
|
||||
}
|
||||
|
||||
// Cap the TPS to a maximum by making nominator 1.
|
||||
// Expecting the pulse period to be 1 second.
|
||||
if (difference < SECOND_NS) difference = SECOND_NS;
|
||||
|
||||
// Add missed ticks, TPS has been low for a while, see the math in the class javadoc.
|
||||
while (difference > maxBeforeZeroTPS) {
|
||||
averager.add(time, 0.0);
|
||||
difference -= maxBeforeZeroTPS;
|
||||
}
|
||||
|
||||
double tps = maxBeforeZeroTPS * 1.0 / difference;
|
||||
if (averager.add(time, tps)) {
|
||||
return Optional.of(averager.getAverageAndReset(time));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
@ -17,18 +17,11 @@
|
||||
package com.djrapitops.plan.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.gathering.SystemUsage;
|
||||
import com.djrapitops.plan.gathering.domain.TPS;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.TPSStoreTransaction;
|
||||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class responsible for calculating TPS every second.
|
||||
*
|
||||
@ -36,45 +29,31 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class TPSCounter extends AbsRunnable {
|
||||
|
||||
protected final List<TPS> history;
|
||||
|
||||
protected final DBSystem dbSystem;
|
||||
protected final ServerInfo serverInfo;
|
||||
protected final PluginLogger logger;
|
||||
protected final ErrorHandler errorHandler;
|
||||
|
||||
private boolean diskErrored = false;
|
||||
|
||||
protected int latestPlayersOnline = 0;
|
||||
|
||||
public TPSCounter(
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
this.dbSystem = dbSystem;
|
||||
this.serverInfo = serverInfo;
|
||||
this.logger = logger;
|
||||
this.errorHandler = errorHandler;
|
||||
history = new ArrayList<>();
|
||||
|
||||
warmUp();
|
||||
}
|
||||
|
||||
public void warmUp() {
|
||||
SystemUsage.getAverageSystemLoad();
|
||||
SystemUsage.getUsedMemory();
|
||||
SystemUsage.getFreeDiskSpace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long nanoTime = System.nanoTime();
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
addNewTPSEntry(nanoTime, now);
|
||||
|
||||
if (history.size() >= 60) {
|
||||
dbSystem.getDatabase().executeTransaction(new TPSStoreTransaction(
|
||||
serverInfo.getServerUUID(),
|
||||
new ArrayList<>(history)
|
||||
));
|
||||
history.clear();
|
||||
}
|
||||
pulse();
|
||||
} catch (Exception | NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) {
|
||||
logger.error("TPS Count Task Disabled due to error, reload Plan to re-enable.");
|
||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||
@ -82,15 +61,7 @@ public abstract class TPSCounter extends AbsRunnable {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void addNewTPSEntry(long nanoTime, long now);
|
||||
|
||||
public int getLatestPlayersOnline() {
|
||||
return latestPlayersOnline;
|
||||
}
|
||||
|
||||
protected double getCPUUsage() {
|
||||
return SystemUsage.getAverageSystemLoad() * 100.0;
|
||||
}
|
||||
public abstract void pulse();
|
||||
|
||||
protected long getFreeDiskSpace() {
|
||||
try {
|
||||
|
@ -16,7 +16,6 @@
|
||||
*/
|
||||
package com.djrapitops.plan.identification.properties;
|
||||
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
@ -34,16 +33,13 @@ public abstract class ServerProperties {
|
||||
private final Supplier<String> ip;
|
||||
private final int maxPlayers;
|
||||
|
||||
private final IntSupplier onlinePlayers;
|
||||
|
||||
protected ServerProperties(
|
||||
String name,
|
||||
int port,
|
||||
String version,
|
||||
String implVersion,
|
||||
Supplier<String> ip,
|
||||
int maxPlayers,
|
||||
IntSupplier onlinePlayers
|
||||
int maxPlayers
|
||||
) {
|
||||
this.name = name;
|
||||
this.port = port;
|
||||
@ -51,7 +47,6 @@ public abstract class ServerProperties {
|
||||
this.implVersion = implVersion;
|
||||
this.ip = ip;
|
||||
this.maxPlayers = maxPlayers;
|
||||
this.onlinePlayers = onlinePlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,7 +78,4 @@ public abstract class ServerProperties {
|
||||
return maxPlayers;
|
||||
}
|
||||
|
||||
public int getOnlinePlayers() {
|
||||
return onlinePlayers.getAsInt();
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.djrapitops.plan.modules;
|
||||
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.importing.EmptyImportSystem;
|
||||
import com.djrapitops.plan.gathering.importing.ImportSystem;
|
||||
import com.djrapitops.plan.settings.ConfigSystem;
|
||||
@ -34,12 +35,15 @@ import dagger.Module;
|
||||
public interface ProxySuperClassBindingModule {
|
||||
|
||||
@Binds
|
||||
DBSystem bindProxyDatabaseSystem(ProxyDBSystem proxyDBSystem);
|
||||
DBSystem bindDBSystem(ProxyDBSystem dbSystem);
|
||||
|
||||
@Binds
|
||||
ConfigSystem bindProxyConfigSystem(ProxyConfigSystem proxyConfigSystem);
|
||||
ConfigSystem bindConfigSystem(ProxyConfigSystem configSystem);
|
||||
|
||||
@Binds
|
||||
ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem);
|
||||
|
||||
@Binds
|
||||
ServerSensor<?> bindServerSensor(ServerSensor<Object> sensor);
|
||||
|
||||
}
|
@ -17,11 +17,9 @@
|
||||
package com.djrapitops.plan.storage.database.transactions.events;
|
||||
|
||||
import com.djrapitops.plan.gathering.domain.TPS;
|
||||
import com.djrapitops.plan.gathering.domain.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.storage.database.queries.DataStoreQueries;
|
||||
import com.djrapitops.plan.storage.database.transactions.Transaction;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@ -32,38 +30,15 @@ import java.util.UUID;
|
||||
public class TPSStoreTransaction extends Transaction {
|
||||
|
||||
private final UUID serverUUID;
|
||||
private final List<TPS> tpsList;
|
||||
private final TPS tps;
|
||||
|
||||
public TPSStoreTransaction(UUID serverUUID, List<TPS> tpsList) {
|
||||
public TPSStoreTransaction(UUID serverUUID, TPS tps) {
|
||||
this.serverUUID = serverUUID;
|
||||
this.tpsList = tpsList;
|
||||
this.tps = tps;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performOperations() {
|
||||
TPS tps = calculateTPS();
|
||||
execute(DataStoreQueries.storeTPS(serverUUID, tps));
|
||||
}
|
||||
|
||||
private TPS calculateTPS() {
|
||||
long lastDate = tpsList.get(tpsList.size() - 1).getDate();
|
||||
double averageTPS = tpsList.stream().mapToDouble(TPS::getTicksPerSecond).average().orElse(0);
|
||||
int peakPlayersOnline = tpsList.stream().mapToInt(TPS::getPlayers).max().orElse(0);
|
||||
double averageCPUUsage = tpsList.stream().mapToDouble(TPS::getCPUUsage).average().orElse(0);
|
||||
long averageUsedMemory = (long) tpsList.stream().mapToLong(TPS::getUsedMemory).average().orElse(0);
|
||||
int averageEntityCount = (int) tpsList.stream().mapToInt(TPS::getEntityCount).average().orElse(0);
|
||||
int averageChunksLoaded = (int) tpsList.stream().mapToInt(TPS::getChunksLoaded).average().orElse(0);
|
||||
long freeDiskSpace = (long) tpsList.stream().mapToLong(TPS::getFreeDiskSpace).average().orElse(0);
|
||||
|
||||
return TPSBuilder.get()
|
||||
.date(lastDate)
|
||||
.tps(averageTPS)
|
||||
.playersOnline(peakPlayersOnline)
|
||||
.usedCPU(averageCPUUsage)
|
||||
.usedMemory(averageUsedMemory)
|
||||
.entities(averageEntityCount)
|
||||
.chunksLoaded(averageChunksLoaded)
|
||||
.freeDiskSpace(freeDiskSpace)
|
||||
.toTPS();
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.utilities.analysis;
|
||||
|
||||
/**
|
||||
* Utility for averaging data.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class Average {
|
||||
|
||||
private double total;
|
||||
private int count;
|
||||
|
||||
public Average() {
|
||||
total = 0.0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new entry and check if save should be done.
|
||||
*
|
||||
* @param value TPS value
|
||||
*/
|
||||
public void add(double value) {
|
||||
total += value;
|
||||
count++;
|
||||
}
|
||||
|
||||
public double getAverageAndReset() {
|
||||
double average = total / count;
|
||||
total = 0.0;
|
||||
count = 0;
|
||||
return average;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.utilities.analysis;
|
||||
|
||||
/**
|
||||
* Calculates maximum from given values.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public interface Maximum {
|
||||
|
||||
class ForInteger {
|
||||
private int max;
|
||||
private int startingValue;
|
||||
|
||||
public ForInteger() {
|
||||
this(Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public ForInteger(int startingValue) {
|
||||
this.startingValue = startingValue;
|
||||
this.max = startingValue;
|
||||
}
|
||||
|
||||
public void add(int value) {
|
||||
if (value > max) max = value;
|
||||
}
|
||||
|
||||
public int getMaxAndReset() {
|
||||
int result = max;
|
||||
max = startingValue;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.utilities.analysis;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Utility for averaging time based data.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TimerAverage {
|
||||
|
||||
private long savePeriodMs;
|
||||
private long lastSaveMs;
|
||||
|
||||
private double total;
|
||||
private int count;
|
||||
|
||||
public TimerAverage() {
|
||||
this(TimeUnit.MINUTES.toMillis(1L));
|
||||
}
|
||||
|
||||
public TimerAverage(long savePeriodMs) {
|
||||
this.savePeriodMs = savePeriodMs;
|
||||
lastSaveMs = 0;
|
||||
|
||||
total = 0.0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new entry and check if save should be done.
|
||||
*
|
||||
* @param time Current epoch ms
|
||||
* @param value TPS value
|
||||
* @return If a save should be performed.
|
||||
*/
|
||||
public boolean add(long time, double value) {
|
||||
if (lastSaveMs <= 0) lastSaveMs = time;
|
||||
if (value < 0.0) return false;
|
||||
total += value;
|
||||
count++;
|
||||
return time - lastSaveMs >= savePeriodMs;
|
||||
}
|
||||
|
||||
public double getAverageAndReset(long time) {
|
||||
lastSaveMs = time;
|
||||
double average = total / count;
|
||||
total = 0.0;
|
||||
count = 0;
|
||||
return average;
|
||||
}
|
||||
}
|
@ -79,7 +79,6 @@ import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.nio.file.Files;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
@ -439,7 +438,7 @@ public interface DatabaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
default void testRemovalEverything() throws NoSuchAlgorithmException {
|
||||
default void testRemovalEverything() {
|
||||
saveAllData();
|
||||
|
||||
db().executeTransaction(new RemoveEverythingTransaction());
|
||||
@ -456,7 +455,7 @@ public interface DatabaseTest {
|
||||
assertTrue(db().query(WebUserQueries.fetchAllPlanWebUsers()).isEmpty());
|
||||
}
|
||||
|
||||
default <T extends Map> void assertQueryIsEmpty(Database database, Query<T> query) {
|
||||
default <T extends Map<?, ?>> void assertQueryIsEmpty(Database database, Query<T> query) {
|
||||
assertTrue(database.query(query).isEmpty());
|
||||
}
|
||||
|
||||
@ -782,7 +781,7 @@ public interface DatabaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
default void testNewContainerForPlayer() throws NoSuchAlgorithmException {
|
||||
default void testNewContainerForPlayer() {
|
||||
saveAllData();
|
||||
|
||||
long start = System.nanoTime();
|
||||
@ -837,7 +836,7 @@ public interface DatabaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
default void playerContainerSupportsAllPlayerKeys() throws NoSuchAlgorithmException, IllegalAccessException {
|
||||
default void playerContainerSupportsAllPlayerKeys() throws IllegalAccessException {
|
||||
saveAllData();
|
||||
|
||||
PlayerContainer playerContainer = db().query(ContainerFetchQueries.fetchPlayerContainer(playerUUID));
|
||||
@ -846,7 +845,7 @@ public interface DatabaseTest {
|
||||
|
||||
List<String> unsupported = new ArrayList<>();
|
||||
List<Key> keys = FieldFetcher.getPublicStaticFields(PlayerKeys.class, Key.class);
|
||||
for (Key key : keys) {
|
||||
for (Key<?> key : keys) {
|
||||
if (!playerContainer.supports(key)) {
|
||||
unsupported.add(key.getKeyName());
|
||||
}
|
||||
@ -872,14 +871,14 @@ public interface DatabaseTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
default void serverContainerSupportsAllServerKeys() throws NoSuchAlgorithmException, IllegalAccessException {
|
||||
default void serverContainerSupportsAllServerKeys() throws IllegalAccessException {
|
||||
saveAllData();
|
||||
|
||||
ServerContainer serverContainer = db().query(ContainerFetchQueries.fetchServerContainer(serverUUID()));
|
||||
|
||||
List<String> unsupported = new ArrayList<>();
|
||||
List<Key> keys = FieldFetcher.getPublicStaticFields(ServerKeys.class, Key.class);
|
||||
for (Key key : keys) {
|
||||
for (Key<?> key : keys) {
|
||||
if (!serverContainer.supports(key)) {
|
||||
unsupported.add(key.getKeyName());
|
||||
}
|
||||
@ -963,7 +962,7 @@ public interface DatabaseTest {
|
||||
List<TPS> tpsData = RandomData.randomTPS();
|
||||
|
||||
for (TPS tps : tpsData) {
|
||||
db().executeTransaction(new TPSStoreTransaction(serverUUID(), Collections.singletonList(tps)));
|
||||
db().executeTransaction(new TPSStoreTransaction(serverUUID(), tps));
|
||||
}
|
||||
|
||||
tpsData.sort(Comparator.comparingInt(TPS::getPlayers));
|
||||
|
@ -22,7 +22,6 @@ import dagger.Provides;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Dagger module for Bukkit ServerProperties.
|
||||
@ -41,8 +40,7 @@ public class PluginServerPropertiesModule {
|
||||
"1.13",
|
||||
"1.13-git-mock",
|
||||
() -> new InetSocketAddress(25565).getAddress().getHostAddress(),
|
||||
20,
|
||||
() -> new Random().nextInt(20)
|
||||
20
|
||||
) {};
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ package utilities.dagger;
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.TaskSystem;
|
||||
import com.djrapitops.plan.exceptions.EnableException;
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.listeners.ListenerSystem;
|
||||
import com.djrapitops.plan.processing.Processing;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
@ -28,16 +29,17 @@ import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.H2DB;
|
||||
import com.djrapitops.plan.storage.database.MySQLDB;
|
||||
import com.djrapitops.plan.storage.database.SQLiteDB;
|
||||
import com.djrapitops.plugin.benchmarking.Timings;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.mockito.Mockito;
|
||||
import utilities.mocks.TestProcessing;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Module for binding Bukkit specific classes to the interface implementations.
|
||||
*
|
||||
@ -54,9 +56,7 @@ public class PluginSuperClassBindingModule {
|
||||
SQLiteDB.Factory sqLiteDB,
|
||||
H2DB.Factory h2Factory,
|
||||
MySQLDB mySQLDB,
|
||||
PluginLogger logger,
|
||||
Timings timings,
|
||||
ErrorHandler errorHandler
|
||||
PluginLogger logger
|
||||
) {
|
||||
return new DBSystem(locale, sqLiteDB, h2Factory, logger) {
|
||||
@Override
|
||||
@ -105,4 +105,15 @@ public class PluginSuperClassBindingModule {
|
||||
return testProcessing;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ServerSensor<?> provideServerSensor() {
|
||||
ServerSensor<?> mock = Mockito.mock(ServerSensor.class);
|
||||
when(mock.getWorlds()).thenCallRealMethod();
|
||||
when(mock.getChunkCount(Mockito.any())).thenCallRealMethod();
|
||||
when(mock.getEntityCount(Mockito.any())).thenCallRealMethod();
|
||||
when(mock.getTPS()).thenCallRealMethod();
|
||||
return mock;
|
||||
}
|
||||
|
||||
}
|
@ -17,11 +17,13 @@
|
||||
package com.djrapitops.plan;
|
||||
|
||||
import cn.nukkit.Server;
|
||||
import cn.nukkit.level.Level;
|
||||
import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
|
||||
import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask;
|
||||
import com.djrapitops.plan.gathering.ShutdownHook;
|
||||
import com.djrapitops.plan.gathering.timed.NukkitPingCounter;
|
||||
import com.djrapitops.plan.gathering.timed.NukkitTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.ServerTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.TPSCounter;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
||||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||
@ -49,11 +51,11 @@ public class NukkitTaskSystem extends TaskSystem {
|
||||
private final ShutdownHook shutdownHook;
|
||||
private final JSONCache.CleanTask jsonCacheCleanTask;
|
||||
private final LogsFolderCleanTask logsFolderCleanTask;
|
||||
private final TPSCounter tpsCounter;
|
||||
private final NukkitPingCounter pingCounter;
|
||||
private final ConfigStoreTask configStoreTask;
|
||||
private final DBCleanTask dbCleanTask;
|
||||
private final ExtensionServerMethodCallerTask extensionServerMethodCallerTask;
|
||||
private NukkitTPSCounter tpsCounter;
|
||||
|
||||
@Inject
|
||||
public NukkitTaskSystem(
|
||||
@ -62,7 +64,7 @@ public class NukkitTaskSystem extends TaskSystem {
|
||||
ShutdownHook shutdownHook,
|
||||
RunnableFactory runnableFactory,
|
||||
|
||||
NukkitTPSCounter tpsCounter,
|
||||
ServerTPSCounter<Level> tpsCounter,
|
||||
NukkitPingCounter pingCounter,
|
||||
ExtensionServerMethodCallerTask extensionServerMethodCallerTask,
|
||||
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.gathering;
|
||||
|
||||
import cn.nukkit.level.Level;
|
||||
import com.djrapitops.plan.PlanNukkit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class NukkitSensor implements ServerSensor<Level> {
|
||||
|
||||
private final PlanNukkit plugin;
|
||||
|
||||
@Inject
|
||||
public NukkitSensor(
|
||||
PlanNukkit plugin
|
||||
) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDirectTPS() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTPS() {
|
||||
return plugin.getServer().getTicksPerSecondAverage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkCount(Level world) {
|
||||
return world.getChunks().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityCount(Level world) {
|
||||
return world.getEntities().length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayerCount() {
|
||||
return plugin.getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Level> getWorlds() {
|
||||
return plugin.getServer().getLevels().values();
|
||||
}
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
/*
|
||||
* 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.gathering.timed;
|
||||
|
||||
import cn.nukkit.level.Level;
|
||||
import com.djrapitops.plan.PlanNukkit;
|
||||
import com.djrapitops.plan.gathering.SystemUsage;
|
||||
import com.djrapitops.plan.gathering.domain.TPS;
|
||||
import com.djrapitops.plan.gathering.domain.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.identification.properties.ServerProperties;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Singleton
|
||||
public class NukkitTPSCounter extends TPSCounter {
|
||||
|
||||
protected final PlanNukkit plugin;
|
||||
private ServerProperties serverProperties;
|
||||
private long lastCheckNano;
|
||||
|
||||
@Inject
|
||||
public NukkitTPSCounter(
|
||||
PlanNukkit plugin,
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
ServerProperties serverProperties,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(dbSystem, serverInfo, logger, errorHandler);
|
||||
this.plugin = plugin;
|
||||
this.serverProperties = serverProperties;
|
||||
lastCheckNano = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNewTPSEntry(long nanoTime, long now) {
|
||||
long diff = nanoTime - lastCheckNano;
|
||||
|
||||
lastCheckNano = nanoTime;
|
||||
|
||||
if (diff > nanoTime) { // First run's diff = nanoTime + 1, no calc possible.
|
||||
logger.debug("First run of TPSCountTimer Task.");
|
||||
return;
|
||||
}
|
||||
|
||||
history.add(calculateTPS(diff, now));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the TPS
|
||||
*
|
||||
* @param diff The time difference between the last run and the new run
|
||||
* @param now The time right now
|
||||
* @return the TPS
|
||||
*/
|
||||
private TPS calculateTPS(long diff, long now) {
|
||||
double averageCPUUsage = getCPUUsage();
|
||||
long usedMemory = SystemUsage.getUsedMemory();
|
||||
long freeDiskSpace = getFreeDiskSpace();
|
||||
|
||||
int playersOnline = serverProperties.getOnlinePlayers();
|
||||
latestPlayersOnline = playersOnline;
|
||||
int loadedChunks = getLoadedChunks();
|
||||
int entityCount = getEntityCount();
|
||||
|
||||
return getTPS(diff, now, averageCPUUsage, usedMemory, entityCount, loadedChunks, playersOnline, freeDiskSpace);
|
||||
}
|
||||
|
||||
protected TPS getTPS(long diff, long now,
|
||||
double cpuUsage, long usedMemory,
|
||||
int entityCount, int chunksLoaded,
|
||||
int playersOnline, long freeDiskSpace) {
|
||||
long difference = diff;
|
||||
if (difference < TimeUnit.SECONDS.toNanos(1L)) { // No tick count above 20
|
||||
difference = TimeUnit.SECONDS.toNanos(1L);
|
||||
}
|
||||
|
||||
long twentySeconds = TimeUnit.SECONDS.toNanos(20L);
|
||||
while (difference > twentySeconds) {
|
||||
// Add 0 TPS since more than 20 ticks has passed.
|
||||
history.add(TPSBuilder.get()
|
||||
.date(now)
|
||||
.tps(0)
|
||||
.playersOnline(playersOnline)
|
||||
.usedCPU(cpuUsage)
|
||||
.usedMemory(usedMemory)
|
||||
.entities(entityCount)
|
||||
.chunksLoaded(chunksLoaded)
|
||||
.freeDiskSpace(freeDiskSpace)
|
||||
.toTPS());
|
||||
difference -= twentySeconds;
|
||||
}
|
||||
|
||||
double tpsN = twentySeconds * 1.0 / difference;
|
||||
|
||||
return TPSBuilder.get()
|
||||
.date(now)
|
||||
.tps(tpsN)
|
||||
.playersOnline(playersOnline)
|
||||
.usedCPU(cpuUsage)
|
||||
.usedMemory(usedMemory)
|
||||
.entities(entityCount)
|
||||
.chunksLoaded(chunksLoaded)
|
||||
.freeDiskSpace(freeDiskSpace)
|
||||
.toTPS();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of loaded chunks
|
||||
*
|
||||
* @return amount of loaded chunks
|
||||
*/
|
||||
private int getLoadedChunks() {
|
||||
int sum = 0;
|
||||
for (Level world : plugin.getServer().getLevels().values()) {
|
||||
sum += world.getChunks().size();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of entities on the server for Nukkit
|
||||
*
|
||||
* @return amount of entities
|
||||
*/
|
||||
protected int getEntityCount() {
|
||||
int sum = 0;
|
||||
for (Level world : plugin.getServer().getLevels().values()) {
|
||||
sum += world.getEntities().length;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
@ -32,8 +32,7 @@ public class NukkitServerProperties extends ServerProperties {
|
||||
server.getVersion(),
|
||||
server.getNukkitVersion(),
|
||||
server::getIp,
|
||||
server.getMaxPlayers(),
|
||||
() -> server.getOnlinePlayers().size()
|
||||
server.getMaxPlayers()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,12 @@
|
||||
*/
|
||||
package com.djrapitops.plan.modules.nukkit;
|
||||
|
||||
import cn.nukkit.level.Level;
|
||||
import com.djrapitops.plan.NukkitServerShutdownSave;
|
||||
import com.djrapitops.plan.NukkitTaskSystem;
|
||||
import com.djrapitops.plan.TaskSystem;
|
||||
import com.djrapitops.plan.gathering.NukkitSensor;
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.ServerShutdownSave;
|
||||
import com.djrapitops.plan.gathering.importing.EmptyImportSystem;
|
||||
import com.djrapitops.plan.gathering.importing.ImportSystem;
|
||||
@ -34,7 +37,7 @@ import dagger.Binds;
|
||||
import dagger.Module;
|
||||
|
||||
/**
|
||||
* Module for binding Nukkit specific classes to the interface implementations.
|
||||
* Module for binding Nukkit specific classes as interface implementations.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@ -42,24 +45,29 @@ import dagger.Module;
|
||||
public interface NukkitSuperClassBindingModule {
|
||||
|
||||
@Binds
|
||||
ServerInfo bindNukkitServerInfo(ServerServerInfo serverServerInfo);
|
||||
ServerInfo bindServerInfo(ServerServerInfo serverInfo);
|
||||
|
||||
@Binds
|
||||
DBSystem bindNukkitDatabaseSystem(NukkitDBSystem dbSystem);
|
||||
DBSystem bindDBSystem(NukkitDBSystem dbSystem);
|
||||
|
||||
@Binds
|
||||
ConfigSystem bindNukkitConfigSystem(NukkitConfigSystem nukkitConfigSystem);
|
||||
ConfigSystem bindConfigSystem(NukkitConfigSystem configSystem);
|
||||
|
||||
@Binds
|
||||
TaskSystem bindNukkitTaskSystem(NukkitTaskSystem nukkitTaskSystem);
|
||||
TaskSystem bindTaskSystem(NukkitTaskSystem taskSystem);
|
||||
|
||||
@Binds
|
||||
ListenerSystem bindNukkitListenerSystem(NukkitListenerSystem nukkitListenerSystem);
|
||||
ListenerSystem bindListenerSystem(NukkitListenerSystem listenerSystem);
|
||||
|
||||
@Binds
|
||||
ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem);
|
||||
|
||||
@Binds
|
||||
ServerShutdownSave bindNukkitServerShutdownSave(NukkitServerShutdownSave nukkitServerShutdownSave);
|
||||
ServerShutdownSave bindServerShutdownSave(NukkitServerShutdownSave shutdownSave);
|
||||
|
||||
@Binds
|
||||
ServerSensor<Level> bindServerSensor(NukkitSensor sensor);
|
||||
|
||||
@Binds
|
||||
ServerSensor<?> bindGenericsServerSensor(ServerSensor<Level> sensor);
|
||||
}
|
@ -19,8 +19,9 @@ package com.djrapitops.plan;
|
||||
import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
|
||||
import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask;
|
||||
import com.djrapitops.plan.gathering.ShutdownHook;
|
||||
import com.djrapitops.plan.gathering.timed.ServerTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.SpongePingCounter;
|
||||
import com.djrapitops.plan.gathering.timed.SpongeTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.TPSCounter;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
||||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||
@ -31,6 +32,7 @@ import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.scheduler.Task;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -42,7 +44,7 @@ public class SpongeTaskSystem extends TaskSystem {
|
||||
private final PlanSponge plugin;
|
||||
private final PlanConfig config;
|
||||
private final ShutdownHook shutdownHook;
|
||||
private final SpongeTPSCounter tpsCounter;
|
||||
private final TPSCounter tpsCounter;
|
||||
private final JSONCache.CleanTask jsonCacheCleanTask;
|
||||
private final SpongePingCounter pingCounter;
|
||||
private final LogsFolderCleanTask logsFolderCleanTask;
|
||||
@ -57,7 +59,7 @@ public class SpongeTaskSystem extends TaskSystem {
|
||||
ShutdownHook shutdownHook,
|
||||
RunnableFactory runnableFactory,
|
||||
|
||||
SpongeTPSCounter tpsCounter,
|
||||
ServerTPSCounter<World> tpsCounter,
|
||||
SpongePingCounter pingCounter,
|
||||
ExtensionServerMethodCallerTask extensionServerMethodCallerTask,
|
||||
|
||||
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.gathering;
|
||||
|
||||
import com.djrapitops.plan.PlanSponge;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Iterator;
|
||||
|
||||
@Singleton
|
||||
public class SpongeSensor implements ServerSensor<World> {
|
||||
|
||||
private final PlanSponge plugin;
|
||||
|
||||
@Inject
|
||||
public SpongeSensor(PlanSponge plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDirectTPS() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayerCount() {
|
||||
return plugin.getGame().getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTPS() {
|
||||
return plugin.getGame().getServer().getTicksPerSecond();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<World> getWorlds() {
|
||||
return plugin.getGame().getServer().getWorlds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkCount(World world) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int getLaggyChunkCount(World world) {
|
||||
Iterator<Chunk> chunks = world.getLoadedChunks().iterator();
|
||||
int count = 0;
|
||||
while (chunks.hasNext()) {
|
||||
chunks.next();
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityCount(World world) {
|
||||
return world.getEntities().size();
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* 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.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.PlanSponge;
|
||||
import com.djrapitops.plan.gathering.SystemUsage;
|
||||
import com.djrapitops.plan.gathering.domain.TPS;
|
||||
import com.djrapitops.plan.gathering.domain.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.identification.properties.ServerProperties;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class SpongeTPSCounter extends TPSCounter {
|
||||
|
||||
private long lastCheckNano;
|
||||
private final PlanSponge plugin;
|
||||
private ServerProperties serverProperties;
|
||||
|
||||
@Inject
|
||||
public SpongeTPSCounter(
|
||||
PlanSponge plugin,
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
ServerProperties serverProperties,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(dbSystem, serverInfo, logger, errorHandler);
|
||||
this.plugin = plugin;
|
||||
this.serverProperties = serverProperties;
|
||||
lastCheckNano = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNewTPSEntry(long nanoTime, long now) {
|
||||
long diff = nanoTime - lastCheckNano;
|
||||
|
||||
lastCheckNano = nanoTime;
|
||||
|
||||
if (diff > nanoTime) { // First run's diff = nanoTime + 1, no calc possible.
|
||||
logger.debug("First run of TPSCountTimer Task.");
|
||||
return;
|
||||
}
|
||||
|
||||
history.add(calculateTPS(now));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the TPS
|
||||
*
|
||||
* @param now The time right now
|
||||
* @return the TPS
|
||||
*/
|
||||
private TPS calculateTPS(long now) {
|
||||
double averageCPUUsage = getCPUUsage();
|
||||
|
||||
long usedMemory = SystemUsage.getUsedMemory();
|
||||
|
||||
double tps = plugin.getGame().getServer().getTicksPerSecond();
|
||||
int playersOnline = serverProperties.getOnlinePlayers();
|
||||
latestPlayersOnline = playersOnline;
|
||||
int loadedChunks = -1; // getLoadedChunks();
|
||||
int entityCount = getEntityCount();
|
||||
long freeDiskSpace = getFreeDiskSpace();
|
||||
|
||||
return TPSBuilder.get()
|
||||
.date(now)
|
||||
.tps(tps)
|
||||
.playersOnline(playersOnline)
|
||||
.usedCPU(averageCPUUsage)
|
||||
.usedMemory(usedMemory)
|
||||
.entities(entityCount)
|
||||
.chunksLoaded(loadedChunks)
|
||||
.freeDiskSpace(freeDiskSpace)
|
||||
.toTPS();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of loaded chunks
|
||||
*
|
||||
* @return amount of loaded chunks
|
||||
*/
|
||||
private int getLoadedChunks() {
|
||||
// DISABLED
|
||||
int loaded = 0;
|
||||
for (World world : plugin.getGame().getServer().getWorlds()) {
|
||||
loaded += world.getLoadedChunks().spliterator().estimateSize();
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of entities on the server
|
||||
*
|
||||
* @return amount of entities
|
||||
*/
|
||||
private int getEntityCount() {
|
||||
return plugin.getGame().getServer().getWorlds().stream().mapToInt(world -> world.getEntities().size()).sum();
|
||||
}
|
||||
}
|
@ -36,8 +36,7 @@ public class SpongeServerProperties extends ServerProperties {
|
||||
() -> game.getServer().getBoundAddress()
|
||||
.orElseGet(() -> new InetSocketAddress(25565))
|
||||
.getAddress().getHostAddress(),
|
||||
game.getServer().getMaxPlayers(),
|
||||
() -> game.getServer().getOnlinePlayers().size()
|
||||
game.getServer().getMaxPlayers()
|
||||
);
|
||||
}
|
||||
}
|
@ -19,7 +19,9 @@ package com.djrapitops.plan.modules.sponge;
|
||||
import com.djrapitops.plan.SpongeServerShutdownSave;
|
||||
import com.djrapitops.plan.SpongeTaskSystem;
|
||||
import com.djrapitops.plan.TaskSystem;
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.ServerShutdownSave;
|
||||
import com.djrapitops.plan.gathering.SpongeSensor;
|
||||
import com.djrapitops.plan.gathering.importing.EmptyImportSystem;
|
||||
import com.djrapitops.plan.gathering.importing.ImportSystem;
|
||||
import com.djrapitops.plan.gathering.listeners.ListenerSystem;
|
||||
@ -34,9 +36,10 @@ import com.djrapitops.plan.storage.file.PlanFiles;
|
||||
import com.djrapitops.plan.storage.file.SpongePlanFiles;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
/**
|
||||
* Module for binding Sponge specific classes to the interface implementations.
|
||||
* Module for binding Sponge specific classes as interface implementations.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@ -44,27 +47,32 @@ import dagger.Module;
|
||||
public interface SpongeSuperClassBindingModule {
|
||||
|
||||
@Binds
|
||||
PlanFiles bindSpongePlanFiles(SpongePlanFiles files);
|
||||
PlanFiles bindPlanFiles(SpongePlanFiles files);
|
||||
|
||||
@Binds
|
||||
ServerInfo bindSpongeServerInfo(ServerServerInfo serverServerInfo);
|
||||
ServerInfo bindServerInfo(ServerServerInfo serverInfo);
|
||||
|
||||
@Binds
|
||||
DBSystem bindSpongeDatabaseSystem(SpongeDBSystem dbSystem);
|
||||
DBSystem bindDBSystem(SpongeDBSystem dbSystem);
|
||||
|
||||
@Binds
|
||||
ConfigSystem bindSpongeConfigSystem(SpongeConfigSystem spongeConfigSystem);
|
||||
ConfigSystem bindConfigSystem(SpongeConfigSystem configSystem);
|
||||
|
||||
@Binds
|
||||
TaskSystem bindSpongeTaskSystem(SpongeTaskSystem spongeTaskSystem);
|
||||
TaskSystem bindTaskSystem(SpongeTaskSystem taskSystem);
|
||||
|
||||
@Binds
|
||||
ListenerSystem bindSpongeListenerSystem(SpongeListenerSystem spongeListenerSystem);
|
||||
ListenerSystem bindListenerSystem(SpongeListenerSystem listenerSystem);
|
||||
|
||||
@Binds
|
||||
ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem);
|
||||
|
||||
@Binds
|
||||
ServerShutdownSave bindSpongeServerShutdownSave(SpongeServerShutdownSave spongeServerShutdownSave);
|
||||
ServerShutdownSave bindServerShutdownSave(SpongeServerShutdownSave shutdownSave);
|
||||
|
||||
@Binds
|
||||
ServerSensor<World> bindServerSensor(SpongeSensor sensor);
|
||||
|
||||
@Binds
|
||||
ServerSensor<?> bindGenericsServerSensor(ServerSensor<World> sensor);
|
||||
}
|
@ -18,8 +18,9 @@ package com.djrapitops.plan;
|
||||
|
||||
import com.djrapitops.plan.delivery.webserver.cache.JSONCache;
|
||||
import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask;
|
||||
import com.djrapitops.plan.gathering.timed.ProxyTPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.TPSCounter;
|
||||
import com.djrapitops.plan.gathering.timed.VelocityPingCounter;
|
||||
import com.djrapitops.plan.gathering.timed.VelocityTPSCounter;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
|
||||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||
@ -43,7 +44,7 @@ public class VelocityTaskSystem extends TaskSystem {
|
||||
|
||||
private final PlanVelocity plugin;
|
||||
private final PlanConfig config;
|
||||
private final VelocityTPSCounter tpsCounter;
|
||||
private final TPSCounter tpsCounter;
|
||||
private final VelocityPingCounter pingCounter;
|
||||
private final LogsFolderCleanTask logsFolderCleanTask;
|
||||
private final NetworkConfigStoreTask networkConfigStoreTask;
|
||||
@ -56,7 +57,7 @@ public class VelocityTaskSystem extends TaskSystem {
|
||||
PlanVelocity plugin,
|
||||
PlanConfig config,
|
||||
RunnableFactory runnableFactory,
|
||||
VelocityTPSCounter tpsCounter,
|
||||
ProxyTPSCounter tpsCounter,
|
||||
VelocityPingCounter pingCounter,
|
||||
LogsFolderCleanTask logsFolderCleanTask,
|
||||
NetworkConfigStoreTask networkConfigStoreTask,
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.gathering;
|
||||
|
||||
import com.djrapitops.plan.PlanVelocity;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
@Singleton
|
||||
public class VelocitySensor implements ServerSensor<Object> {
|
||||
|
||||
private final IntSupplier onlinePlayerCountSupplier;
|
||||
|
||||
@Inject
|
||||
public VelocitySensor(PlanVelocity plugin) {
|
||||
onlinePlayerCountSupplier = plugin.getProxy()::getPlayerCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDirectTPS() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayerCount() {
|
||||
return onlinePlayerCountSupplier.getAsInt();
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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.gathering.timed;
|
||||
|
||||
import com.djrapitops.plan.gathering.SystemUsage;
|
||||
import com.djrapitops.plan.gathering.domain.TPS;
|
||||
import com.djrapitops.plan.gathering.domain.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
import com.djrapitops.plan.identification.properties.ServerProperties;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class VelocityTPSCounter extends TPSCounter {
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
|
||||
@Inject
|
||||
public VelocityTPSCounter(
|
||||
DBSystem dbSystem,
|
||||
ServerInfo serverInfo,
|
||||
ServerProperties serverProperties,
|
||||
PluginLogger logger,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(dbSystem, serverInfo, logger, errorHandler);
|
||||
this.serverProperties = serverProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNewTPSEntry(long nanoTime, long now) {
|
||||
int onlineCount = serverProperties.getOnlinePlayers();
|
||||
TPS tps = TPSBuilder.get()
|
||||
.date(now)
|
||||
.playersOnline(onlineCount)
|
||||
.usedCPU(getCPUUsage())
|
||||
.usedMemory(SystemUsage.getUsedMemory())
|
||||
.entities(-1)
|
||||
.chunksLoaded(-1)
|
||||
.freeDiskSpace(getFreeDiskSpace())
|
||||
.toTPS();
|
||||
|
||||
history.add(tps);
|
||||
latestPlayersOnline = onlineCount;
|
||||
}
|
||||
}
|
@ -36,8 +36,7 @@ public class VelocityServerProperties extends ServerProperties {
|
||||
server.getClass().getPackage().getImplementationVersion(),
|
||||
server.getClass().getPackage().getImplementationVersion(),
|
||||
() -> config.get(ProxySettings.IP),
|
||||
-1,
|
||||
server::getPlayerCount
|
||||
-1
|
||||
);
|
||||
}
|
||||
}
|
@ -18,6 +18,8 @@ package com.djrapitops.plan.modules.velocity;
|
||||
|
||||
import com.djrapitops.plan.TaskSystem;
|
||||
import com.djrapitops.plan.VelocityTaskSystem;
|
||||
import com.djrapitops.plan.gathering.ServerSensor;
|
||||
import com.djrapitops.plan.gathering.VelocitySensor;
|
||||
import com.djrapitops.plan.gathering.listeners.ListenerSystem;
|
||||
import com.djrapitops.plan.gathering.listeners.VelocityListenerSystem;
|
||||
import com.djrapitops.plan.identification.ServerInfo;
|
||||
@ -26,7 +28,7 @@ import dagger.Binds;
|
||||
import dagger.Module;
|
||||
|
||||
/**
|
||||
* Module for binding Velocity specific classes to the interface implementations.
|
||||
* Module for binding Velocity specific classes as interface implementations.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@ -34,11 +36,14 @@ import dagger.Module;
|
||||
public interface VelocitySuperClassBindingModule {
|
||||
|
||||
@Binds
|
||||
ServerInfo provideVelocityServerInfo(VelocityServerInfo velocityServerInfo);
|
||||
ServerInfo bindServerInfo(VelocityServerInfo serverInfo);
|
||||
|
||||
@Binds
|
||||
TaskSystem provideVelocityTaskSystem(VelocityTaskSystem velocityTaskSystem);
|
||||
TaskSystem bindTaskSystem(VelocityTaskSystem taskSystem);
|
||||
|
||||
@Binds
|
||||
ListenerSystem provideVelocityListenerSystem(VelocityListenerSystem velocityListenerSystem);
|
||||
ListenerSystem bindListenerSystem(VelocityListenerSystem listenerSystem);
|
||||
|
||||
@Binds
|
||||
ServerSensor<Object> bindServerSensor(VelocitySensor sensor);
|
||||
}
|
Loading…
Reference in New Issue
Block a user