diff options
Diffstat (limited to 'spark-common/src/main/java/me/lucko/spark/common/api')
3 files changed, 343 insertions, 0 deletions
diff --git a/spark-common/src/main/java/me/lucko/spark/common/api/AbstractStatistic.java b/spark-common/src/main/java/me/lucko/spark/common/api/AbstractStatistic.java new file mode 100644 index 0000000..49a6ccb --- /dev/null +++ b/spark-common/src/main/java/me/lucko/spark/common/api/AbstractStatistic.java @@ -0,0 +1,85 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) <luck@lucko.me> + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package me.lucko.spark.common.api; + +import me.lucko.spark.api.statistic.Statistic; +import me.lucko.spark.api.statistic.StatisticWindow; +import me.lucko.spark.api.statistic.types.DoubleStatistic; +import me.lucko.spark.api.statistic.types.GenericStatistic; + +import org.checkerframework.checker.nullness.qual.NonNull; + +import java.lang.reflect.Array; +import java.util.Arrays; + +public abstract class AbstractStatistic<W extends Enum<W> & StatisticWindow> implements Statistic<W> { + private final String name; + protected final W[] windows; + + protected AbstractStatistic(String name, Class<W> enumClass) { + this.name = name; + this.windows = enumClass.getEnumConstants(); + } + + @Override + public @NonNull String name() { + return this.name; + } + + @Override + public W[] getWindows() { + return Arrays.copyOf(this.windows, this.windows.length); + } + + public static abstract class Double<W extends Enum<W> & StatisticWindow> extends AbstractStatistic<W> implements DoubleStatistic<W> { + public Double(String name, Class<W> enumClass) { + super(name, enumClass); + } + + @Override + public double[] poll() { + double[] values = new double[this.windows.length]; + for (int i = 0; i < values.length; i++) { + values[i] = poll(this.windows[i]); + } + return values; + } + } + + public static abstract class Generic<T, W extends Enum<W> & StatisticWindow> extends AbstractStatistic<W> implements GenericStatistic<T, W> { + private final Class<T> typeClass; + + public Generic(String name, Class<T> typeClass, Class<W> enumClass) { + super(name, enumClass); + this.typeClass = typeClass; + } + + @SuppressWarnings("unchecked") + @Override + public T[] poll() { + T[] values = (T[]) Array.newInstance(this.typeClass, this.windows.length); + for (int i = 0; i < values.length; i++) { + values[i] = poll(this.windows[i]); + } + return values; + } + } +} diff --git a/spark-common/src/main/java/me/lucko/spark/common/api/GarbageCollectorInfo.java b/spark-common/src/main/java/me/lucko/spark/common/api/GarbageCollectorInfo.java new file mode 100644 index 0000000..8d289aa --- /dev/null +++ b/spark-common/src/main/java/me/lucko/spark/common/api/GarbageCollectorInfo.java @@ -0,0 +1,69 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) <luck@lucko.me> + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package me.lucko.spark.common.api; + +import me.lucko.spark.api.gc.GarbageCollector; +import me.lucko.spark.common.monitor.memory.GarbageCollectorStatistics; + +import org.checkerframework.checker.nullness.qual.NonNull; + +public class GarbageCollectorInfo implements GarbageCollector { + private final String name; + private final long totalCollections; + private final long totalTime; + private final double averageTime; + private final long averageFrequency; + + public GarbageCollectorInfo(String name, GarbageCollectorStatistics stats, long serverUptime) { + this.name = name; + this.totalCollections = stats.getCollectionCount(); + this.totalTime = stats.getCollectionTime(); + + double totalTimeDouble = this.totalTime; + this.averageTime = this.totalCollections == 0 ? 0 : totalTimeDouble / this.totalCollections; + this.averageFrequency = this.totalCollections == 0 ? 0 : (long) ((serverUptime - totalTimeDouble) / this.totalCollections); + } + + @Override + public @NonNull String name() { + return this.name; + } + + @Override + public long totalCollections() { + return this.totalCollections; + } + + @Override + public long totalTime() { + return this.totalTime; + } + + @Override + public double avgTime() { + return this.averageTime; + } + + @Override + public long avgFrequency() { + return this.averageFrequency; + } +} diff --git a/spark-common/src/main/java/me/lucko/spark/common/api/SparkApi.java b/spark-common/src/main/java/me/lucko/spark/common/api/SparkApi.java new file mode 100644 index 0000000..5ac41fc --- /dev/null +++ b/spark-common/src/main/java/me/lucko/spark/common/api/SparkApi.java @@ -0,0 +1,189 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) <luck@lucko.me> + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package me.lucko.spark.common.api; + +import com.google.common.collect.ImmutableMap; + +import me.lucko.spark.api.Spark; +import me.lucko.spark.api.SparkProvider; +import me.lucko.spark.api.gc.GarbageCollector; +import me.lucko.spark.api.statistic.misc.DoubleAverageInfo; +import me.lucko.spark.api.statistic.types.DoubleStatistic; +import me.lucko.spark.api.statistic.types.GenericStatistic; +import me.lucko.spark.api.statistic.StatisticWindow; +import me.lucko.spark.common.SparkPlatform; +import me.lucko.spark.common.monitor.cpu.CpuMonitor; +import me.lucko.spark.common.monitor.memory.GarbageCollectorStatistics; +import me.lucko.spark.common.monitor.tick.TickStatistics; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.sql.Ref; +import java.util.HashMap; +import java.util.Map; + +public class SparkApi implements Spark { + private static final Method SINGLETON_SET_METHOD; + + static { + try { + SINGLETON_SET_METHOD = SparkProvider.class.getDeclaredMethod("set", Spark.class); + SINGLETON_SET_METHOD.setAccessible(true); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + private final SparkPlatform platform; + + public SparkApi(SparkPlatform platform) { + this.platform = platform; + } + + @Override + public @NonNull DoubleStatistic<StatisticWindow.CpuUsage> cpuProcess() { + return new AbstractStatistic.Double<StatisticWindow.CpuUsage>( + "CPU Process Usage", StatisticWindow.CpuUsage.class + ) { + @Override + public double poll(StatisticWindow.@NonNull CpuUsage window) { + switch (window) { + case SECONDS_10: + return CpuMonitor.processLoad10SecAvg(); + case MINUTES_1: + return CpuMonitor.processLoad1MinAvg(); + case MINUTES_15: + return CpuMonitor.processLoad15MinAvg(); + default: + throw new AssertionError(window); + } + } + }; + } + + @Override + public @NonNull DoubleStatistic<StatisticWindow.CpuUsage> cpuSystem() { + return new AbstractStatistic.Double<StatisticWindow.CpuUsage>( + "CPU System Usage", StatisticWindow.CpuUsage.class + ) { + @Override + public double poll(StatisticWindow.@NonNull CpuUsage window) { + switch (window) { + case SECONDS_10: + return CpuMonitor.systemLoad10SecAvg(); + case MINUTES_1: + return CpuMonitor.systemLoad1MinAvg(); + case MINUTES_15: + return CpuMonitor.systemLoad15MinAvg(); + default: + throw new AssertionError(window); + } + } + }; + } + + @Override + public @Nullable DoubleStatistic<StatisticWindow.TicksPerSecond> tps() { + TickStatistics stats = this.platform.getTickStatistics(); + if (stats == null) { + return null; + } + + return new AbstractStatistic.Double<StatisticWindow.TicksPerSecond>( + "Ticks Per Second", StatisticWindow.TicksPerSecond.class + ) { + @Override + public double poll(StatisticWindow.@NonNull TicksPerSecond window) { + switch (window) { + case SECONDS_5: + return stats.tps5Sec(); + case SECONDS_10: + return stats.tps10Sec(); + case MINUTES_1: + return stats.tps1Min(); + case MINUTES_5: + return stats.tps5Min(); + case MINUTES_15: + return stats.tps15Min(); + default: + throw new AssertionError(window); + } + } + }; + } + + @Override + public @Nullable GenericStatistic<DoubleAverageInfo, StatisticWindow.MillisPerTick> mspt() { + TickStatistics stats = this.platform.getTickStatistics(); + if (stats == null || !stats.isDurationSupported()) { + return null; + } + + return new AbstractStatistic.Generic<DoubleAverageInfo, StatisticWindow.MillisPerTick>( + "Milliseconds Per Tick", DoubleAverageInfo.class, StatisticWindow.MillisPerTick.class + ) { + @Override + public DoubleAverageInfo poll(StatisticWindow.@NonNull MillisPerTick window) { + switch (window) { + case SECONDS_10: + return stats.duration10Sec(); + case MINUTES_1: + return stats.duration1Min(); + default: + throw new AssertionError(window); + } + } + }; + } + + @Override + public @NonNull Map<String, GarbageCollector> gc() { + long serverUptime = System.currentTimeMillis() - this.platform.getServerNormalOperationStartTime(); + Map<String, GarbageCollectorStatistics> stats = GarbageCollectorStatistics.pollStatsSubtractInitial( + this.platform.getStartupGcStatistics() + ); + + Map<String, GarbageCollector> map = new HashMap<>(stats.size()); + for (Map.Entry<String, GarbageCollectorStatistics> entry : stats.entrySet()) { + map.put(entry.getKey(), new GarbageCollectorInfo(entry.getKey(), entry.getValue(), serverUptime)); + } + return ImmutableMap.copyOf(map); + } + + public static void register(Spark spark) { + try { + SINGLETON_SET_METHOD.invoke(null, spark); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + } + + public static void unregister() { + try { + SINGLETON_SET_METHOD.invoke(null, new Object[]{null}); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + } +} |