From 9bed6177ddf94f67aaad5ee2504721cf0b957a94 Mon Sep 17 00:00:00 2001 From: Luck Date: Mon, 31 Dec 2018 18:15:39 +0000 Subject: Add '/spark heapdump' command --- .../spark/common/command/modules/HeapModule.java | 68 ------------ .../spark/common/command/modules/MemoryModule.java | 116 +++++++++++++++++++++ .../common/command/modules/MonitoringModule.java | 92 ---------------- .../command/modules/TickMonitoringModule.java | 92 ++++++++++++++++ 4 files changed, 208 insertions(+), 160 deletions(-) delete mode 100644 spark-common/src/main/java/me/lucko/spark/common/command/modules/HeapModule.java create mode 100644 spark-common/src/main/java/me/lucko/spark/common/command/modules/MemoryModule.java delete mode 100644 spark-common/src/main/java/me/lucko/spark/common/command/modules/MonitoringModule.java create mode 100644 spark-common/src/main/java/me/lucko/spark/common/command/modules/TickMonitoringModule.java (limited to 'spark-common/src/main/java/me/lucko/spark/common/command') diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/HeapModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/HeapModule.java deleted file mode 100644 index 318ce25..0000000 --- a/spark-common/src/main/java/me/lucko/spark/common/command/modules/HeapModule.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of spark. - * - * Copyright (c) lucko (Luck) - * 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 . - */ - -package me.lucko.spark.common.command.modules; - -import me.lucko.spark.common.SparkPlatform; -import me.lucko.spark.common.command.Command; -import me.lucko.spark.common.command.CommandModule; -import me.lucko.spark.memory.HeapDump; - -import okhttp3.MediaType; - -import java.io.IOException; -import java.util.function.Consumer; - -public class HeapModule implements CommandModule { - private static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8"); - - @Override - public void registerCommands(Consumer> consumer) { - consumer.accept(Command.builder() - .aliases("heap", "memory") - .executor((platform, sender, arguments) -> { - platform.runAsync(() -> { - platform.sendPrefixedMessage("&7Creating a new heap dump, please wait..."); - - HeapDump heapDump; - try { - heapDump = HeapDump.createNew(); - } catch (Exception e) { - platform.sendPrefixedMessage("&cAn error occurred whilst inspecting the heap."); - e.printStackTrace(); - return; - } - - byte[] output = heapDump.formCompressedDataPayload(); - try { - String key = SparkPlatform.BYTEBIN_CLIENT.postGzippedContent(output, JSON_TYPE); - platform.sendPrefixedMessage("&bHeap dump output:"); - platform.sendLink(SparkPlatform.VIEWER_URL + key); - } catch (IOException e) { - platform.sendPrefixedMessage("&cAn error occurred whilst uploading the data."); - e.printStackTrace(); - } - }); - }) - .build() - ); - } - -} diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/MemoryModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/MemoryModule.java new file mode 100644 index 0000000..405b3d3 --- /dev/null +++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/MemoryModule.java @@ -0,0 +1,116 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * 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 . + */ + +package me.lucko.spark.common.command.modules; + +import me.lucko.spark.common.SparkPlatform; +import me.lucko.spark.common.command.Command; +import me.lucko.spark.common.command.CommandModule; +import me.lucko.spark.memory.HeapDump; +import me.lucko.spark.memory.HeapDumpSummary; + +import okhttp3.MediaType; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.function.Consumer; + +public class MemoryModule implements CommandModule { + private static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8"); + + @Override + public void registerCommands(Consumer> consumer) { + consumer.accept(Command.builder() + .aliases("heapsummary") + .argumentUsage("run-gc-before", null) + .executor((platform, sender, arguments) -> { + platform.runAsync(() -> { + if (arguments.boolFlag("run-gc-before")) { + platform.sendPrefixedMessage("&7Running garbage collector..."); + System.gc(); + } + + platform.sendPrefixedMessage("&7Creating a new heap dump summary, please wait..."); + + HeapDumpSummary heapDump; + try { + heapDump = HeapDumpSummary.createNew(); + } catch (Exception e) { + platform.sendPrefixedMessage("&cAn error occurred whilst inspecting the heap."); + e.printStackTrace(); + return; + } + + byte[] output = heapDump.formCompressedDataPayload(); + try { + String key = SparkPlatform.BYTEBIN_CLIENT.postGzippedContent(output, JSON_TYPE); + platform.sendPrefixedMessage("&bHeap dump summmary output:"); + platform.sendLink(SparkPlatform.VIEWER_URL + key); + } catch (IOException e) { + platform.sendPrefixedMessage("&cAn error occurred whilst uploading the data."); + e.printStackTrace(); + } + }); + }) + .build() + ); + + consumer.accept(Command.builder() + .aliases("heapdump") + .argumentUsage("run-gc-before", null) + .argumentUsage("include-non-live", null) + .executor((platform, sender, arguments) -> { + platform.runAsync(() -> { + Path pluginFolder = platform.getPluginFolder(); + try { + Files.createDirectories(pluginFolder); + } catch (IOException e) { + // ignore + } + + Path file = pluginFolder.resolve("heap-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".hprof"); + boolean liveOnly = !arguments.boolFlag("include-non-live"); + + if (arguments.boolFlag("run-gc-before")) { + platform.sendPrefixedMessage("&7Running garbage collector..."); + System.gc(); + } + + platform.sendPrefixedMessage("&7Creating a new heap dump, please wait..."); + + try { + HeapDump.dumpHeap(file, liveOnly); + } catch (Exception e) { + platform.sendPrefixedMessage("&cAn error occurred whilst creating a heap dump."); + e.printStackTrace(); + return; + } + + platform.sendPrefixedMessage("&bHeap dump written to: " + file.toString()); + }); + }) + .build() + ); + } + +} diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/MonitoringModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/MonitoringModule.java deleted file mode 100644 index 608d6b4..0000000 --- a/spark-common/src/main/java/me/lucko/spark/common/command/modules/MonitoringModule.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of spark. - * - * Copyright (c) lucko (Luck) - * 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 . - */ - -package me.lucko.spark.common.command.modules; - -import me.lucko.spark.common.SparkPlatform; -import me.lucko.spark.common.command.Command; -import me.lucko.spark.common.command.CommandModule; -import me.lucko.spark.common.command.tabcomplete.CompletionSupplier; -import me.lucko.spark.common.command.tabcomplete.TabCompleter; -import me.lucko.spark.monitor.TickMonitor; -import me.lucko.spark.sampler.TickCounter; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Consumer; - -public class MonitoringModule implements CommandModule { - - /** The tick monitor instance currently running, if any */ - private ReportingTickMonitor activeTickMonitor = null; - - @Override - public void registerCommands(Consumer> consumer) { - consumer.accept(Command.builder() - .aliases("monitoring") - .argumentUsage("threshold", "percentage increase") - .argumentUsage("without-gc", null) - .executor((platform, sender, arguments) -> { - if (this.activeTickMonitor == null) { - - int threshold = arguments.intFlag("threshold"); - if (threshold == -1) { - threshold = 100; - } - - try { - TickCounter tickCounter = platform.newTickCounter(); - this.activeTickMonitor = new ReportingTickMonitor(platform, tickCounter, threshold, !arguments.boolFlag("without-gc")); - } catch (UnsupportedOperationException e) { - platform.sendPrefixedMessage(sender, "&cNot supported!"); - } - } else { - this.activeTickMonitor.close(); - this.activeTickMonitor = null; - platform.sendPrefixedMessage("&7Tick monitor disabled."); - } - }) - .tabCompleter((platform, sender, arguments) -> { - List opts = new ArrayList<>(Arrays.asList("--threshold", "--without-gc")); - opts.removeAll(arguments); - - return TabCompleter.create() - .from(0, CompletionSupplier.startsWith(opts)) - .complete(arguments); - }) - .build() - ); - } - - private class ReportingTickMonitor extends TickMonitor { - private final SparkPlatform platform; - - ReportingTickMonitor(SparkPlatform platform, TickCounter tickCounter, int percentageChangeThreshold, boolean monitorGc) { - super(tickCounter, percentageChangeThreshold, monitorGc); - this.platform = platform; - } - - @Override - protected void sendMessage(String message) { - this.platform.sendPrefixedMessage(message); - } - } -} diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/TickMonitoringModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/TickMonitoringModule.java new file mode 100644 index 0000000..d0513ab --- /dev/null +++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/TickMonitoringModule.java @@ -0,0 +1,92 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * 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 . + */ + +package me.lucko.spark.common.command.modules; + +import me.lucko.spark.common.SparkPlatform; +import me.lucko.spark.common.command.Command; +import me.lucko.spark.common.command.CommandModule; +import me.lucko.spark.common.command.tabcomplete.CompletionSupplier; +import me.lucko.spark.common.command.tabcomplete.TabCompleter; +import me.lucko.spark.monitor.TickMonitor; +import me.lucko.spark.sampler.TickCounter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +public class TickMonitoringModule implements CommandModule { + + /** The tick monitor instance currently running, if any */ + private ReportingTickMonitor activeTickMonitor = null; + + @Override + public void registerCommands(Consumer> consumer) { + consumer.accept(Command.builder() + .aliases("monitoring") + .argumentUsage("threshold", "percentage increase") + .argumentUsage("without-gc", null) + .executor((platform, sender, arguments) -> { + if (this.activeTickMonitor == null) { + + int threshold = arguments.intFlag("threshold"); + if (threshold == -1) { + threshold = 100; + } + + try { + TickCounter tickCounter = platform.newTickCounter(); + this.activeTickMonitor = new ReportingTickMonitor(platform, tickCounter, threshold, !arguments.boolFlag("without-gc")); + } catch (UnsupportedOperationException e) { + platform.sendPrefixedMessage(sender, "&cNot supported!"); + } + } else { + this.activeTickMonitor.close(); + this.activeTickMonitor = null; + platform.sendPrefixedMessage("&7Tick monitor disabled."); + } + }) + .tabCompleter((platform, sender, arguments) -> { + List opts = new ArrayList<>(Arrays.asList("--threshold", "--without-gc")); + opts.removeAll(arguments); + + return TabCompleter.create() + .from(0, CompletionSupplier.startsWith(opts)) + .complete(arguments); + }) + .build() + ); + } + + private class ReportingTickMonitor extends TickMonitor { + private final SparkPlatform platform; + + ReportingTickMonitor(SparkPlatform platform, TickCounter tickCounter, int percentageChangeThreshold, boolean monitorGc) { + super(tickCounter, percentageChangeThreshold, monitorGc); + this.platform = platform; + } + + @Override + protected void sendMessage(String message) { + this.platform.sendPrefixedMessage(message); + } + } +} -- cgit