feat: 新增屏蔽指定插件报错功能

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2021-10-28 09:51:27 +00:00
parent 129f854382
commit 18dc99e78e
7 changed files with 708 additions and 714 deletions

18
pom.xml
View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>Yum</artifactId>
<version>2.9.1</version>
<version>2.9.5</version>
<packaging>jar</packaging>
<description>Minecraft 服务器插件管理系统</description>
@ -16,16 +16,18 @@
</parent>
<properties>
<update.description>§a补丁包 2.9.1 版本</update.description>
<update.description>§a补丁包 2.9.5 版本</update.description>
<update.changes>
§620-03-25 §cfix: paper HikariPool error;
§619-09-30 §cfix: tabComplete error;
§619-08-28 §cfix: knownCommands not compatible;
       §cfix: async event on primary thread;
§619-08-26 §cfix: 修复不兼容 1.14.4 的问题;
§619-02-23 §cfix: 修复不兼容 1.13 的问题;
§621-10-28 §afeat: 新增屏蔽插件报错功能;
§620-03-25 §afeat: 优化 当前插件获取逻辑;
§620-03-25 §c修复: Paper HikariPool 不兼容问题;
§619-09-30 §c修复: 自动补全报错的问题;
§619-08-28 §c修复: knownCommands 不兼容;
      §c修复: async event on primary thread;
</update.changes>
<update.changelog>
§619-08-26 §c修复: 修复不兼容 1.14.4 的问题;
§619-02-23 §c修复: 修复不兼容 1.13 的问题;
§617-07-29 §cfix: 修复不兼容 1.12 的问题;
§6- §cfix: §7修复仓库数据读取错误的问题;
§6- §cfix: §7修复一个tab补全产生的错误

View File

@ -1,139 +1,132 @@
package pw.yumc.Yum.inject;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.command.TabCompleter;
import org.bukkit.command.TabExecutor;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.MonitorManager;
import pw.yumc.YumCore.kit.StrKit;
import pw.yumc.YumCore.reflect.Reflect;
public class CommandInjector implements TabExecutor {
private static String prefix = "§6[§bYum §a命令监控§6] ";
private static String warn = "§c注意! §6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令 §c耗时 §4%sms §c平均耗时 §4%sms!";
private static String err = prefix + "§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常!";
private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败!";
private static String plugin_is_null = "插件不得为NULL!";
private CommandExecutor originalExecutor;
private TabCompleter originalCompleter;
private Plugin plugin;
public long totalTime;
public int count;
public CommandInjector(CommandExecutor originalCommandExecutor, TabCompleter originalTabCompleter, Plugin plugin) {
this.originalExecutor = originalCommandExecutor;
this.originalCompleter = originalTabCompleter;
this.plugin = plugin;
}
public static void inject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
PluginManager pluginManager = Bukkit.getPluginManager();
SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap");
for (Command command : commandMap.getCommands()) {
if (command instanceof PluginCommand) {
PluginCommand pluginCommand = (PluginCommand) command;
Plugin cp = pluginCommand.getPlugin();
if (cp.equals(plugin)) {
CommandExecutor executor = Reflect.on(command).get("executor");
if (executor instanceof CommandInjector) { return; }
TabCompleter completer = Reflect.on(command).get("completer");
CommandInjector commandInjector = new CommandInjector(executor, completer, plugin);
Reflect.on(command).set("executor", commandInjector);
Reflect.on(command).set("completer", commandInjector);
}
}
}
} catch (Throwable e) {
MonitorManager.log(String.format(inject_error, plugin.getName()));
}
}
public static void uninject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
PluginManager pluginManager = Bukkit.getPluginManager();
SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap");
for (Command command : commandMap.getCommands()) {
if (command instanceof PluginCommand) {
PluginCommand pluginCommand = (PluginCommand) command;
Plugin cp = pluginCommand.getPlugin();
if (cp.equals(plugin)) {
CommandExecutor executor = Reflect.on(command).get("executor");
if (executor instanceof CommandInjector) {
CommandInjector injected = (CommandInjector) executor;
Reflect.on(command).set("executor", injected.getOriginalExecutor());
}
TabCompleter completer = Reflect.on(command).get("completer");
if (completer instanceof CommandInjector) {
CommandInjector injected = (CommandInjector) completer;
Reflect.on(command).set("completer", injected.getOriginalCompleter());
}
}
}
}
} catch (Throwable ignored) {
}
}
public TabCompleter getOriginalCompleter() {
return originalCompleter;
}
public CommandExecutor getOriginalExecutor() {
return originalExecutor;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
try {
long start = System.nanoTime();
boolean result = originalExecutor.onCommand(sender, command, label, args);
long end = System.nanoTime();
long lag = end - start;
totalTime += lag;
count++;
long lagms = lag / MonitorManager.um;
long avglagms = totalTime / count / MonitorManager.um;
if (Bukkit.isPrimaryThread() && lagms > MonitorManager.lagTime && avglagms > MonitorManager.lagTime) {
MonitorManager.lagTip(String.format(warn, sender.getName(), plugin.getName(), label, StrKit.join(args, " "), lagms, avglagms));
}
MonitorManager.addCmd(plugin.getName(), lag);
return result;
} catch (Throwable e) {
while (e.getCause() != null) {
e = e.getCause();
}
MonitorCommand.lastError = e;
MonitorManager.sendError(sender, plugin, e);
MonitorManager.printThrowable(String.format(err, sender.getName(), plugin.getName(), label, StrKit.join(args, " ")), e);
}
return false;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (originalCompleter == null) { return Collections.emptyList(); }
long start = System.nanoTime();
List<String> result = originalCompleter.onTabComplete(sender, command, alias, args);
long end = System.nanoTime();
totalTime += end - start;
count++;
return result;
}
}
package pw.yumc.Yum.inject;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.command.*;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.MonitorManager;
import pw.yumc.YumCore.kit.StrKit;
import pw.yumc.YumCore.reflect.Reflect;
import java.util.Collections;
import java.util.List;
public class CommandInjector implements TabExecutor {
private static String prefix = "§6[§bYum §a命令监控§6] ";
private static String warn = "§c注意! §6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令 §c耗时 §4%sms §c平均耗时 §4%sms!";
private static String err = prefix + "§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常!";
private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败!";
private static String plugin_is_null = "插件不得为NULL!";
private CommandExecutor originalExecutor;
private TabCompleter originalCompleter;
private Plugin plugin;
public long totalTime;
public int count;
public CommandInjector(CommandExecutor originalCommandExecutor, TabCompleter originalTabCompleter, Plugin plugin) {
this.originalExecutor = originalCommandExecutor;
this.originalCompleter = originalTabCompleter;
this.plugin = plugin;
}
public static void inject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
PluginManager pluginManager = Bukkit.getPluginManager();
SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap");
for (Command command : commandMap.getCommands()) {
if (command instanceof PluginCommand) {
PluginCommand pluginCommand = (PluginCommand) command;
Plugin cp = pluginCommand.getPlugin();
if (cp.equals(plugin)) {
CommandExecutor executor = Reflect.on(command).get("executor");
if (executor instanceof CommandInjector) { return; }
TabCompleter completer = Reflect.on(command).get("completer");
CommandInjector commandInjector = new CommandInjector(executor, completer, plugin);
Reflect.on(command).set("executor", commandInjector);
Reflect.on(command).set("completer", commandInjector);
}
}
}
} catch (Throwable e) {
MonitorManager.log(String.format(inject_error, plugin.getName()));
}
}
public static void uninject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
PluginManager pluginManager = Bukkit.getPluginManager();
SimpleCommandMap commandMap = Reflect.on(pluginManager).get("commandMap");
for (Command command : commandMap.getCommands()) {
if (command instanceof PluginCommand) {
PluginCommand pluginCommand = (PluginCommand) command;
Plugin cp = pluginCommand.getPlugin();
if (cp.equals(plugin)) {
CommandExecutor executor = Reflect.on(command).get("executor");
if (executor instanceof CommandInjector) {
CommandInjector injected = (CommandInjector) executor;
Reflect.on(command).set("executor", injected.getOriginalExecutor());
}
TabCompleter completer = Reflect.on(command).get("completer");
if (completer instanceof CommandInjector) {
CommandInjector injected = (CommandInjector) completer;
Reflect.on(command).set("completer", injected.getOriginalCompleter());
}
}
}
}
} catch (Throwable ignored) {
}
}
public TabCompleter getOriginalCompleter() {
return originalCompleter;
}
public CommandExecutor getOriginalExecutor() {
return originalExecutor;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
try {
long start = System.nanoTime();
boolean result = originalExecutor.onCommand(sender, command, label, args);
long end = System.nanoTime();
long lag = end - start;
totalTime += lag;
count++;
long lagms = lag / MonitorManager.um;
long avglagms = totalTime / count / MonitorManager.um;
if (Bukkit.isPrimaryThread() && lagms > MonitorManager.lagTime && avglagms > MonitorManager.lagTime) {
MonitorManager.lagTip(String.format(warn, sender.getName(), plugin.getName(), label, StrKit.join(args, " "), lagms, avglagms));
}
MonitorManager.addCmd(plugin.getName(), lag);
return result;
} catch (Throwable e) {
while (e.getCause() != null) {
e = e.getCause();
}
MonitorCommand.lastError = e;
MonitorManager.sendError(sender, plugin, e);
MonitorManager.printThrowable(plugin, String.format(err, sender.getName(), plugin.getName(), label, StrKit.join(args, " ")), e);
}
return false;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (originalCompleter == null) { return Collections.emptyList(); }
long start = System.nanoTime();
List<String> result = originalCompleter.onTabComplete(sender, command, alias, args);
long end = System.nanoTime();
totalTime += end - start;
count++;
return result;
}
}

View File

@ -1,120 +1,119 @@
package pw.yumc.Yum.inject;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.Validate;
import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredListener;
import org.bukkit.plugin.TimedRegisteredListener;
import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.ConfigManager;
import pw.yumc.Yum.managers.MonitorManager;
import pw.yumc.YumCore.reflect.Reflect;
public class ListenerInjector implements EventExecutor {
private static String prefix = "§6[§bYum §a事件监控§6] ";
private static String warn = "§c注意! §6插件 §b%s §6处理 §d%s §6事件 §c耗时 §4%sms §c平均耗时 §4%sms!";
private static String err = prefix + "§6插件 §b%s §6处理 §d%s §6事件时发生异常!";
private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败 §6注入类: §3%s!";
private static String plugin_is_null = "插件不得为NULL!";
private EventExecutor originalExecutor;
private Plugin plugin;
public Map<String, Long> eventTotalTime = new ConcurrentHashMap<>();
public Map<String, Integer> eventCount = new ConcurrentHashMap<>();
public ListenerInjector(EventExecutor originalExecutor, Plugin plugin) {
this.originalExecutor = originalExecutor;
this.plugin = plugin;
}
public static void inject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
List<RegisteredListener> listeners = HandlerList.getRegisteredListeners(plugin);
for (RegisteredListener listener : listeners) {
try {
if (listener instanceof TimedRegisteredListener) { return; }
// 兼容PerWorldPlugin
if (listener.getClass().getName().contains("PWPRegisteredListener")) {
Field f = Reflect.getDeclaredField(RegisteredListener.class, "executor");
f.setAccessible(true);
EventExecutor originalExecutor = (EventExecutor) f.get(listener);
if (originalExecutor instanceof ListenerInjector) { return; }
ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin);
f.set(listener, listenerInjector);
} else {
EventExecutor originalExecutor = Reflect.on(listener).get("executor");
if (originalExecutor instanceof ListenerInjector) { return; }
ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin);
Reflect.on(listener).set("executor", listenerInjector);
}
} catch (Throwable e) {
MonitorManager.log(String.format(inject_error, plugin.getName(), listener.getClass().getName()));
e.printStackTrace();
}
}
}
public static void uninject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
List<RegisteredListener> listeners = HandlerList.getRegisteredListeners(plugin);
for (RegisteredListener listener : listeners) {
if (listener instanceof TimedRegisteredListener) { return; }
EventExecutor executor = Reflect.on(listener).get("executor");
if (executor instanceof ListenerInjector) {
Reflect.on(listener).set("executor", ((ListenerInjector) executor).getOriginalExecutor());
}
}
} catch (Throwable ignored) {
}
}
@Override
public void execute(Listener listener, Event event) throws EventException {
try {
if (!event.isAsynchronous()) {
long start = System.nanoTime();
originalExecutor.execute(listener, event);
long end = System.nanoTime();
String en = event.getEventName();
long lag = end - start;
if (eventTotalTime.containsKey(en)) {
eventTotalTime.put(en, eventTotalTime.get(en) + lag);
eventCount.put(en, eventCount.get(en) + 1);
} else {
eventTotalTime.put(en, end - start);
eventCount.put(en, 1);
}
long lagms = lag / MonitorManager.um;
long avglagms = eventTotalTime.get(en) / eventCount.get(en) / MonitorManager.um;
if (avglagms > MonitorManager.lagTime && lagms > MonitorManager.lagTime && !ConfigManager.i().getMonitorIgnoreList().contains(plugin.getName())) {
MonitorManager.lagTip(String.format(warn, plugin.getName(), event.getEventName(), lagms, avglagms));
}
MonitorManager.addEvent(plugin.getName(), lag);
} else {
originalExecutor.execute(listener, event);
}
} catch (Throwable e) {
while (e.getCause() != null) {
e = e.getCause();
}
MonitorCommand.lastError = e;
MonitorManager.printThrowable(String.format(err, plugin.getName(), event.getEventName()), e);
}
}
public EventExecutor getOriginalExecutor() {
return originalExecutor;
}
}
package pw.yumc.Yum.inject;
import org.apache.commons.lang.Validate;
import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredListener;
import org.bukkit.plugin.TimedRegisteredListener;
import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.ConfigManager;
import pw.yumc.Yum.managers.MonitorManager;
import pw.yumc.YumCore.reflect.Reflect;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ListenerInjector implements EventExecutor {
private static String prefix = "§6[§bYum §a事件监控§6] ";
private static String warn = "§c注意! §6插件 §b%s §6处理 §d%s §6事件 §c耗时 §4%sms §c平均耗时 §4%sms!";
private static String err = prefix + "§6插件 §b%s §6处理 §d%s §6事件时发生异常!";
private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败 §6注入类: §3%s!";
private static String plugin_is_null = "插件不得为NULL!";
private EventExecutor originalExecutor;
private Plugin plugin;
public Map<String, Long> eventTotalTime = new ConcurrentHashMap<>();
public Map<String, Integer> eventCount = new ConcurrentHashMap<>();
public ListenerInjector(EventExecutor originalExecutor, Plugin plugin) {
this.originalExecutor = originalExecutor;
this.plugin = plugin;
}
public static void inject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
List<RegisteredListener> listeners = HandlerList.getRegisteredListeners(plugin);
for (RegisteredListener listener : listeners) {
try {
if (listener instanceof TimedRegisteredListener) { return; }
// 兼容PerWorldPlugin
if (listener.getClass().getName().contains("PWPRegisteredListener")) {
Field f = Reflect.getDeclaredField(RegisteredListener.class, "executor");
f.setAccessible(true);
EventExecutor originalExecutor = (EventExecutor) f.get(listener);
if (originalExecutor instanceof ListenerInjector) { return; }
ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin);
f.set(listener, listenerInjector);
} else {
EventExecutor originalExecutor = Reflect.on(listener).get("executor");
if (originalExecutor instanceof ListenerInjector) { return; }
ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin);
Reflect.on(listener).set("executor", listenerInjector);
}
} catch (Throwable e) {
MonitorManager.log(String.format(inject_error, plugin.getName(), listener.getClass().getName()));
e.printStackTrace();
}
}
}
public static void uninject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
List<RegisteredListener> listeners = HandlerList.getRegisteredListeners(plugin);
for (RegisteredListener listener : listeners) {
if (listener instanceof TimedRegisteredListener) { return; }
EventExecutor executor = Reflect.on(listener).get("executor");
if (executor instanceof ListenerInjector) {
Reflect.on(listener).set("executor", ((ListenerInjector) executor).getOriginalExecutor());
}
}
} catch (Throwable ignored) {
}
}
@Override
public void execute(Listener listener, Event event) throws EventException {
try {
if (!event.isAsynchronous()) {
long start = System.nanoTime();
originalExecutor.execute(listener, event);
long end = System.nanoTime();
String en = event.getEventName();
long lag = end - start;
if (eventTotalTime.containsKey(en)) {
eventTotalTime.put(en, eventTotalTime.get(en) + lag);
eventCount.put(en, eventCount.get(en) + 1);
} else {
eventTotalTime.put(en, end - start);
eventCount.put(en, 1);
}
long lagms = lag / MonitorManager.um;
long avglagms = eventTotalTime.get(en) / eventCount.get(en) / MonitorManager.um;
if (avglagms > MonitorManager.lagTime && lagms > MonitorManager.lagTime && !ConfigManager.i().getMonitorIgnoreList().contains(plugin.getName())) {
MonitorManager.lagTip(String.format(warn, plugin.getName(), event.getEventName(), lagms, avglagms));
}
MonitorManager.addEvent(plugin.getName(), lag);
} else {
originalExecutor.execute(listener, event);
}
} catch (Throwable e) {
while (e.getCause() != null) {
e = e.getCause();
}
MonitorCommand.lastError = e;
MonitorManager.printThrowable(plugin, String.format(err, plugin.getName(), event.getEventName()), e);
}
}
public EventExecutor getOriginalExecutor() {
return originalExecutor;
}
}

View File

@ -1,120 +1,119 @@
package pw.yumc.Yum.inject;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.MonitorManager;
import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.kit.StrKit;
import pw.yumc.YumCore.reflect.Reflect;
public class TaskInjector implements Runnable {
private static String prefix = "§6[§bYum §a任务监控§6] ";
private static String warn = "§c注意! §6插件 §b%s §6处理 §d%s §6任务 §c耗时 §4%sms §c平均耗时 §4%sms!";
private static String err = prefix + "§6插件 §b%s §6处理 §d%s §6任务时发生异常!";
private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败!";
private static String plugin_is_null = "插件不得为NULL!";
private static String taskFieldName = "task";
static {
BukkitTask task = Bukkit.getServer().getScheduler().runTask(P.instance, new Runnable(){
@Override
public void run() {}
});
try {
Reflect.on(task).get("rTask");
taskFieldName = "rTask";
}catch (Throwable ex) {
}
}
private Runnable originalTask;
private Plugin plugin;
private String taskName;
public long totalTime;
public int count;
public TaskInjector(Runnable originalTask, Plugin plugin) {
this.originalTask = originalTask;
this.plugin = plugin;
Class<? extends Runnable> taskClass = getOriginalTask().getClass();
taskName = StrKit.isBlank(taskClass.getSimpleName()) ? taskClass.getName() : taskClass.getSimpleName();
}
// 当前注入只能对TimerTask有效
// 对于单次执行的任务 我们需要注册一个动态的代理
public static void inject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
BukkitScheduler scheduler = Bukkit.getScheduler();
List<BukkitTask> pendingTasks = scheduler.getPendingTasks();
for (BukkitTask pendingTask : pendingTasks) {
// 忽略异步任务
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) {
Runnable originalTask = Reflect.on(pendingTask).get(taskFieldName);
if (originalTask instanceof TaskInjector) {
return;
}
TaskInjector taskInjector = new TaskInjector(originalTask, plugin);
Reflect.on(pendingTask).set(taskFieldName, taskInjector);
}
}
} catch (Throwable e) {
MonitorManager.log(String.format(inject_error, plugin.getName()));
}
}
public static void uninject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
BukkitScheduler scheduler = Bukkit.getScheduler();
List<BukkitTask> pendingTasks = scheduler.getPendingTasks();
for (BukkitTask pendingTask : pendingTasks) {
// 忽略异步任务
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) {
Runnable originalTask = Reflect.on(pendingTask).get("task");
if (originalTask instanceof TaskInjector) {
Reflect.on(pendingTask).set("task", ((TaskInjector) originalTask).getOriginalTask());
}
}
}
} catch (Throwable ignored) {
}
}
public Runnable getOriginalTask() {
return originalTask;
}
@Override
public void run() {
try {
long start = System.nanoTime();
originalTask.run();
long end = System.nanoTime();
long lag = end - start;
totalTime += lag;
count++;
long lagms = lag / MonitorManager.um;
long avglagms = totalTime / count / MonitorManager.um;
if (Bukkit.isPrimaryThread() && lagms > MonitorManager.lagTime && avglagms > MonitorManager.lagTime) {
MonitorManager.lagTip(String.format(warn, plugin.getName(), taskName, lagms, avglagms));
}
MonitorManager.addTask(plugin.getName(), lag);
} catch (Throwable e) {
while (e.getCause() != null) {
e = e.getCause();
}
MonitorCommand.lastError = e;
MonitorManager.printThrowable(String.format(err, plugin.getName(), taskName), e);
}
}
}
package pw.yumc.Yum.inject;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.MonitorManager;
import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.kit.StrKit;
import pw.yumc.YumCore.reflect.Reflect;
import java.util.List;
public class TaskInjector implements Runnable {
private static String prefix = "§6[§bYum §a任务监控§6] ";
private static String warn = "§c注意! §6插件 §b%s §6处理 §d%s §6任务 §c耗时 §4%sms §c平均耗时 §4%sms!";
private static String err = prefix + "§6插件 §b%s §6处理 §d%s §6任务时发生异常!";
private static String inject_error = prefix + "§6插件 §b%s §c注入能耗监控失败!";
private static String plugin_is_null = "插件不得为NULL!";
private static String taskFieldName = "task";
static {
BukkitTask task = Bukkit.getServer().getScheduler().runTask(P.instance, new Runnable() {
@Override
public void run() {}
});
try {
Reflect.on(task).get("rTask");
taskFieldName = "rTask";
} catch (Throwable ex) {
}
}
private Runnable originalTask;
private Plugin plugin;
private String taskName;
public long totalTime;
public int count;
public TaskInjector(Runnable originalTask, Plugin plugin) {
this.originalTask = originalTask;
this.plugin = plugin;
Class<? extends Runnable> taskClass = getOriginalTask().getClass();
taskName = StrKit.isBlank(taskClass.getSimpleName()) ? taskClass.getName() : taskClass.getSimpleName();
}
// 当前注入只能对TimerTask有效
// 对于单次执行的任务 我们需要注册一个动态的代理
public static void inject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
BukkitScheduler scheduler = Bukkit.getScheduler();
List<BukkitTask> pendingTasks = scheduler.getPendingTasks();
for (BukkitTask pendingTask : pendingTasks) {
// 忽略异步任务
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) {
Runnable originalTask = Reflect.on(pendingTask).get(taskFieldName);
if (originalTask instanceof TaskInjector) {
return;
}
TaskInjector taskInjector = new TaskInjector(originalTask, plugin);
Reflect.on(pendingTask).set(taskFieldName, taskInjector);
}
}
} catch (Throwable e) {
MonitorManager.log(String.format(inject_error, plugin.getName()));
}
}
public static void uninject(Plugin plugin) {
Validate.notNull(plugin, plugin_is_null);
try {
BukkitScheduler scheduler = Bukkit.getScheduler();
List<BukkitTask> pendingTasks = scheduler.getPendingTasks();
for (BukkitTask pendingTask : pendingTasks) {
// 忽略异步任务
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) {
Runnable originalTask = Reflect.on(pendingTask).get("task");
if (originalTask instanceof TaskInjector) {
Reflect.on(pendingTask).set("task", ((TaskInjector) originalTask).getOriginalTask());
}
}
}
} catch (Throwable ignored) {
}
}
public Runnable getOriginalTask() {
return originalTask;
}
@Override
public void run() {
try {
long start = System.nanoTime();
originalTask.run();
long end = System.nanoTime();
long lag = end - start;
totalTime += lag;
count++;
long lagms = lag / MonitorManager.um;
long avglagms = totalTime / count / MonitorManager.um;
if (Bukkit.isPrimaryThread() && lagms > MonitorManager.lagTime && avglagms > MonitorManager.lagTime) {
MonitorManager.lagTip(String.format(warn, plugin.getName(), taskName, lagms, avglagms));
}
MonitorManager.addTask(plugin.getName(), lag);
} catch (Throwable e) {
while (e.getCause() != null) {
e = e.getCause();
}
MonitorCommand.lastError = e;
MonitorManager.printThrowable(plugin, String.format(err, plugin.getName(), taskName), e);
}
}
}

View File

@ -1,126 +1,129 @@
package pw.yumc.Yum.managers;
import java.util.List;
import org.bukkit.plugin.java.JavaPlugin;
import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.config.FileConfig;
import pw.yumc.YumCore.sql.DataBase;
public class ConfigManager {
public static String ENABLE = "Enable";
public static String BLACK = "Black";
public static String IGNORE = "Ignore";
private static ConfigManager i = new ConfigManager(P.instance);
public FileConfig config;
public FileConfig setop;
public FileConfig network;
public FileConfig thread;
public FileConfig monitor;
public ConfigManager(JavaPlugin plugin) {
config = new FileConfig();
setop = new FileConfig("setop.yml");
network = new FileConfig("network.yml");
thread = new FileConfig("thread.yml");
monitor = new FileConfig("monitor.yml");
}
public static ConfigManager i() {
return i;
}
public List<String> getBlackList() {
return config.getStringList("blacklist");
}
public DataBase getDataBase() {
return DataBase.create(P.instance, config.getConfigurationSection(""));
}
public List<String> getIgnoreList() {
return config.getStringList("ignorelist");
}
public List<String> getMonitorIgnoreList() {
return monitor.getStringList(IGNORE);
}
public List<String> getNetworkBlackList() {
return network.getStringList(BLACK);
}
public List<String> getNetworkIgnoreList() {
return network.getStringList(IGNORE);
}
public List<String> getNetworkWhiteURL() {
return network.getStringList("WhiteURL");
}
public List<String> getSetOpBlackList() {
return setop.getStringList(BLACK);
}
public List<String> getSetOpIgnoreList() {
return setop.getStringList(IGNORE);
}
public boolean isAllowPrimaryThread() {
return network.getBoolean("AllowPrimaryThread", false);
}
public boolean isLogToFile() {
return monitor.getBoolean("LogToFile");
}
public boolean isMainThreadCheck() {
return thread.getBoolean("MainThreadCheck", true);
}
public boolean isMainThreadDebug() {
return thread.getBoolean("Debug");
}
public boolean isMonitorDebug() {
return monitor.getBoolean("Debug");
}
public boolean isMonitorEnable() {
return monitor.getBoolean(ENABLE, true);
}
public boolean isNetworkDebug() {
return network.getBoolean("NetworkDebug", false);
}
public boolean isNetworkEnable() {
return network.getBoolean(ENABLE, true);
}
public boolean isNetworkShowInfo() {
return network.getBoolean("ShowInfo", true);
}
public boolean isSetOpEnable() {
return setop.getBoolean(ENABLE, true);
}
public boolean isThreadSafe() {
return thread.getBoolean("ThreadSafe", true);
}
public List<String> getNetWorkDebug() {
return network.getStringList("Debug");
}
public void reload() {
setop.reload();
network.reload();
thread.reload();
monitor.reload();
}
}
package pw.yumc.Yum.managers;
import org.bukkit.plugin.java.JavaPlugin;
import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.config.FileConfig;
import pw.yumc.YumCore.sql.DataBase;
import java.util.List;
public class ConfigManager {
public static String ENABLE = "Enable";
public static String BLACK = "Black";
public static String IGNORE = "Ignore";
private static ConfigManager i = new ConfigManager(P.instance);
public FileConfig config;
public FileConfig setop;
public FileConfig network;
public FileConfig thread;
public FileConfig monitor;
public ConfigManager(JavaPlugin plugin) {
config = new FileConfig();
setop = new FileConfig("setop.yml");
network = new FileConfig("network.yml");
thread = new FileConfig("thread.yml");
monitor = new FileConfig("monitor.yml");
}
public static ConfigManager i() {
return i;
}
public List<String> getBlackList() {
return config.getStringList("blacklist");
}
public DataBase getDataBase() {
return DataBase.create(P.instance, config.getConfigurationSection(""));
}
public List<String> getIgnoreList() {
return config.getStringList("ignorelist");
}
public List<String> getMonitorIgnoreList() {
return monitor.getStringList(IGNORE);
}
public List<String> getMonitorIgnoreErrorList() {
return monitor.getStringList("IgnoreError");
}
public List<String> getNetworkBlackList() {
return network.getStringList(BLACK);
}
public List<String> getNetworkIgnoreList() {
return network.getStringList(IGNORE);
}
public List<String> getNetworkWhiteURL() {
return network.getStringList("WhiteURL");
}
public List<String> getSetOpBlackList() {
return setop.getStringList(BLACK);
}
public List<String> getSetOpIgnoreList() {
return setop.getStringList(IGNORE);
}
public boolean isAllowPrimaryThread() {
return network.getBoolean("AllowPrimaryThread", false);
}
public boolean isLogToFile() {
return monitor.getBoolean("LogToFile");
}
public boolean isMainThreadCheck() {
return thread.getBoolean("MainThreadCheck", true);
}
public boolean isMainThreadDebug() {
return thread.getBoolean("Debug");
}
public boolean isMonitorDebug() {
return monitor.getBoolean("Debug");
}
public boolean isMonitorEnable() {
return monitor.getBoolean(ENABLE, true);
}
public boolean isNetworkDebug() {
return network.getBoolean("NetworkDebug", false);
}
public boolean isNetworkEnable() {
return network.getBoolean(ENABLE, true);
}
public boolean isNetworkShowInfo() {
return network.getBoolean("ShowInfo", true);
}
public boolean isSetOpEnable() {
return setop.getBoolean(ENABLE, true);
}
public boolean isThreadSafe() {
return thread.getBoolean("ThreadSafe", true);
}
public List<String> getNetWorkDebug() {
return network.getStringList("Debug");
}
public void reload() {
setop.reload();
network.reload();
thread.reload();
monitor.reload();
}
}

View File

@ -1,185 +1,180 @@
package pw.yumc.Yum.managers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.kit.LogKit;
/**
* 能耗监控管理
*
* @since 2016年7月19日 下午3:55:54
* @author
*/
public class MonitorManager {
public static String prefix = "§6[§bYum §a能耗监控§6] ";
private static String errMsg = prefix + "§c命令执行异常 请反馈下列信息给腐竹!";
private static String errP = "§6插件名称: §b%s";
private static String errN = "§6异常名称: §c%s";
private static String errM = "§6异常说明: §3%s";
private static String errInfo = "§6简易错误信息如下:";
private static String errStackTrace = " §e位于 §c%s.%s(§4%s:%s§c)";
private static String devInfo = "§c开发人员调试信息如下:";
public static int lagTime = 20;
public static int um = 1000000;
public static boolean debug = ConfigManager.i().isMonitorDebug();
public static boolean log_to_file = ConfigManager.i().isLogToFile();
private static double totalTime = 0;
private static Map<String, Long> monitor = new ConcurrentHashMap<>();
private static Map<String, Long> task = new ConcurrentHashMap<>();
private static Map<String, Long> event = new ConcurrentHashMap<>();
private static Map<String, Long> cmd = new ConcurrentHashMap<>();
private static LogKit mlog = new LogKit("monitor.log");
private static LogKit elog = new LogKit("error.log");
public static void addCmd(String pname, long time) {
add(pname, time, monitor, cmd);
}
public static void addEvent(String pname, long time) {
add(pname, time, monitor, event);
}
public static void addTask(String pname, long time) {
add(pname, time, monitor, task);
}
public static void elog(String message) {
if (log_to_file) {
elog.console(message);
} else {
Log.console(message);
}
}
public static Map<String, Long> getMonitor() {
return sortMapByValue(monitor);
}
public static MonitorInfo getMonitorInfo(String pname) {
double per = 100.00;
return new MonitorInfo(monitor.get(pname) / totalTime * per, cmd.get(pname) / totalTime * per, event.get(pname) / totalTime * per, task.get(pname) / totalTime * per);
}
public static void init() {
for (Plugin p : Bukkit.getPluginManager().getPlugins()) {
reset(p.getName());
}
}
public static void lagTip(String message) {
log(prefix + message);
}
public static void log(String message) {
if (log_to_file) {
mlog.console(message);
} else {
Log.console(message);
}
}
public static void printThrowable(String title, Throwable e) {
elog(title);
elog(String.format(errN, e.getClass().getName()));
elog(String.format(errM, e.getMessage()));
elog(errInfo);
int l = e.getStackTrace().length > 5 ? 5 : e.getStackTrace().length;
for (int i = 0; i < l; i++) {
StackTraceElement ste = e.getStackTrace()[i];
elog(String.format(errStackTrace, ste.getClassName(), ste.getMethodName(), ste.getFileName() == null ? "未知" : ste.getFileName(), ste.getLineNumber()));
}
if (debug) {
Log.console(devInfo);
e.printStackTrace();
}
}
public static void reset(String pname) {
monitor.put(pname, 0L);
task.put(pname, 0L);
event.put(pname, 0L);
cmd.put(pname, 0L);
}
public static void sendError(CommandSender sender, Plugin plugin, Throwable e) {
sender.sendMessage(errMsg);
sender.sendMessage(String.format(errP, plugin.getName()));
sender.sendMessage(String.format(errN, e.getClass().getName()));
sender.sendMessage(String.format(errM, e.getMessage()));
}
/**
* 使用 Map按value进行排序
*
* @param oriMap
* @return
*/
public static Map<String, Long> sortMapByValue(Map<String, Long> oriMap) {
if (oriMap == null || oriMap.isEmpty()) { return oriMap; }
Map<String, Long> sortedMap = new LinkedHashMap<>();
List<Map.Entry<String, Long>> entryList = new ArrayList<>(oriMap.entrySet());
Collections.sort(entryList, new MonitorComparator());
Iterator<Map.Entry<String, Long>> iter = entryList.iterator();
Entry<String, Long> tmpEntry;
while (iter.hasNext()) {
tmpEntry = iter.next();
sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue());
}
return sortedMap;
}
@SafeVarargs
private static void add(String pname, long time, Map<String, Long>... maps) {
totalTime += time;
for (Map<String, Long> map : maps) {
map.put(pname, map.get(pname) + time);
}
}
private static long sum(Collection<? extends Long> numbers) {
int result = 0;
for (Long num : numbers) {
result += num;
}
return result;
}
public static class MonitorInfo {
public double monitor;
public double cmd;
public double event;
public double task;
public MonitorInfo(double monitor, double cmd, double event, double task) {
this.monitor = monitor;
this.cmd = cmd;
this.event = event;
this.task = task;
}
}
static class MonitorComparator implements Comparator<Map.Entry<String, Long>> {
@Override
public int compare(Entry<String, Long> o1, Entry<String, Long> o2) {
return o2.getValue().compareTo(o1.getValue());
}
}
}
package pw.yumc.Yum.managers;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.kit.LogKit;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
/**
* 能耗监控管理
*
* @author
* @since 2016年7月19日 下午3:55:54
*/
public class MonitorManager {
public static String prefix = "§6[§bYum §a能耗监控§6] ";
private static String errMsg = prefix + "§c命令执行异常 请反馈下列信息给腐竹!";
private static String errP = "§6插件名称: §b%s";
private static String errN = "§6异常名称: §c%s";
private static String errM = "§6异常说明: §3%s";
private static String errInfo = "§6简易错误信息如下:";
private static String errStackTrace = " §e位于 §c%s.%s(§4%s:%s§c)";
private static String devInfo = "§c开发人员调试信息如下:";
public static int lagTime = 20;
public static int um = 1000000;
public static boolean debug = ConfigManager.i().isMonitorDebug();
public static boolean log_to_file = ConfigManager.i().isLogToFile();
private static double totalTime = 0;
private static Map<String, Long> monitor = new ConcurrentHashMap<>();
private static Map<String, Long> task = new ConcurrentHashMap<>();
private static Map<String, Long> event = new ConcurrentHashMap<>();
private static Map<String, Long> cmd = new ConcurrentHashMap<>();
private static LogKit mlog = new LogKit("monitor.log");
private static LogKit elog = new LogKit("error.log");
public static void addCmd(String pname, long time) {
add(pname, time, monitor, cmd);
}
public static void addEvent(String pname, long time) {
add(pname, time, monitor, event);
}
public static void addTask(String pname, long time) {
add(pname, time, monitor, task);
}
public static void elog(String message) {
if (log_to_file) {
elog.console(message);
} else {
Log.console(message);
}
}
public static Map<String, Long> getMonitor() {
return sortMapByValue(monitor);
}
public static MonitorInfo getMonitorInfo(String pname) {
double per = 100.00;
return new MonitorInfo(monitor.get(pname) / totalTime * per, cmd.get(pname) / totalTime * per, event.get(pname) / totalTime * per, task.get(pname) / totalTime * per);
}
public static void init() {
for (Plugin p : Bukkit.getPluginManager().getPlugins()) {
reset(p.getName());
}
}
public static void lagTip(String message) {
log(prefix + message);
}
public static void log(String message) {
if (log_to_file) {
mlog.console(message);
} else {
Log.console(message);
}
}
public static void printThrowable(Plugin plugin, String title, Throwable e) {
if (ConfigManager.i().getMonitorIgnoreErrorList().contains(plugin.getName())) {
return;
}
elog(title);
elog(String.format(errN, e.getClass().getName()));
elog(String.format(errM, e.getMessage()));
elog(errInfo);
int l = Math.min(e.getStackTrace().length, 5);
for (int i = 0; i < l; i++) {
StackTraceElement ste = e.getStackTrace()[i];
elog(String.format(errStackTrace, ste.getClassName(), ste.getMethodName(), ste.getFileName() == null ? "未知" : ste.getFileName(), ste.getLineNumber()));
}
if (debug) {
Log.console(devInfo);
e.printStackTrace();
}
}
public static void reset(String pname) {
monitor.put(pname, 0L);
task.put(pname, 0L);
event.put(pname, 0L);
cmd.put(pname, 0L);
}
public static void sendError(CommandSender sender, Plugin plugin, Throwable e) {
sender.sendMessage(errMsg);
sender.sendMessage(String.format(errP, plugin.getName()));
sender.sendMessage(String.format(errN, e.getClass().getName()));
sender.sendMessage(String.format(errM, e.getMessage()));
}
/**
* 使用 Map按value进行排序
*
* @param oriMap
* @return
*/
public static Map<String, Long> sortMapByValue(Map<String, Long> oriMap) {
if (oriMap == null || oriMap.isEmpty()) { return oriMap; }
Map<String, Long> sortedMap = new LinkedHashMap<>();
List<Map.Entry<String, Long>> entryList = new ArrayList<>(oriMap.entrySet());
entryList.sort(new MonitorComparator());
Iterator<Map.Entry<String, Long>> iter = entryList.iterator();
Entry<String, Long> tmpEntry;
while (iter.hasNext()) {
tmpEntry = iter.next();
sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue());
}
return sortedMap;
}
@SafeVarargs
private static void add(String pname, long time, Map<String, Long>... maps) {
totalTime += time;
for (Map<String, Long> map : maps) {
map.put(pname, map.get(pname) + time);
}
}
private static long sum(Collection<? extends Long> numbers) {
int result = 0;
for (Long num : numbers) {
result += num;
}
return result;
}
public static class MonitorInfo {
public double monitor;
public double cmd;
public double event;
public double task;
public MonitorInfo(double monitor, double cmd, double event, double task) {
this.monitor = monitor;
this.cmd = cmd;
this.event = event;
this.task = task;
}
}
static class MonitorComparator implements Comparator<Map.Entry<String, Long>> {
@Override
public int compare(Entry<String, Long> o1, Entry<String, Long> o2) {
return o2.getValue().compareTo(o1.getValue());
}
}
}

View File

@ -1,16 +1,19 @@
############################
### 能耗监控系统配置文件
############################
#配置版本号 请勿修改!!!
Version: 1.3
#是否开启
Enable: true
#是否显示开发人员信息
Debug: false
#是否保存Lag日志到文件
LogToFile: true
#忽略检测列表
Ignore:
- PluginHelper
############################
### 能耗监控系统配置文件
############################
#配置版本号 请勿修改!!!
Version: 1.4
#是否开启
Enable: true
#是否显示开发人员信息
Debug: false
#是否保存Lag日志到文件
LogToFile: true
#忽略检测列表
Ignore:
- PluginHelper
#忽略报错的插件列表
IgnoreError:
- PluginHelper