feat: 添加全局能耗监控

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2016-07-19 19:45:57 +08:00
parent 58fe1d3f0c
commit 935a2eb4f9
9 changed files with 166 additions and 18 deletions

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>pw.yumc</groupId> <groupId>pw.yumc</groupId>
<artifactId>Yum</artifactId> <artifactId>Yum</artifactId>
<version>2.6.4</version> <version>2.6.5</version>
<name>Yum</name> <name>Yum</name>
<description>Minecraft 服务器插件管理系统</description> <description>Minecraft 服务器插件管理系统</description>
<build> <build>
@ -60,6 +60,7 @@
<properties> <properties>
<update.description>&amp;a全新 2.X 版本 更多守护与优化</update.description> <update.description>&amp;a全新 2.X 版本 更多守护与优化</update.description>
<update.changes> <update.changes>
&amp;b2.6.5 &amp;6- &amp;c修复list命令 &amp;a添加全局能耗统计...;
&amp;b2.6.4 &amp;6- &amp;e添加从&amp;bBukkitDev&amp;e下载和更新...; &amp;b2.6.4 &amp;6- &amp;e添加从&amp;bBukkitDev&amp;e下载和更新...;
&amp;b2.6.3 &amp;6- &amp;a注入操作延时执行 防止部分任务未注册 添加手动注入...; &amp;b2.6.3 &amp;6- &amp;a注入操作延时执行 防止部分任务未注册 添加手动注入...;
&amp;b2.6.2 &amp;6- &amp;d能耗监控添加忽略列表 &amp;3详见monitor.yml...; &amp;b2.6.2 &amp;6- &amp;d能耗监控添加忽略列表 &amp;3详见monitor.yml...;

View File

@ -33,6 +33,7 @@ import pw.yumc.Yum.runnables.MainThreadCheckTask;
* @since 2015年8月21日下午5:14:39 * @since 2015年8月21日下午5:14:39
*/ */
public class Yum extends JavaPlugin { public class Yum extends JavaPlugin {
public static boolean disable = false;;
public static Thread mainThread = null; public static Thread mainThread = null;
public static Timer task = new Timer(); public static Timer task = new Timer();
public static TimerTask tt; public static TimerTask tt;
@ -45,6 +46,7 @@ public class Yum extends JavaPlugin {
@Override @Override
public void onDisable() { public void onDisable() {
NetworkManager.unregister(); NetworkManager.unregister();
disable = true;
} }
@Override @Override
@ -59,6 +61,10 @@ public class Yum extends JavaPlugin {
new VersionChecker(this); new VersionChecker(this);
YumAPI.updateRepo(Bukkit.getConsoleSender()); YumAPI.updateRepo(Bukkit.getConsoleSender());
YumAPI.updateCheck(Bukkit.getConsoleSender()); YumAPI.updateCheck(Bukkit.getConsoleSender());
if (disable) {
YumAPI.updateInject();
disable = false;
}
} }
@Override @Override

View File

@ -32,6 +32,8 @@ import pw.yumc.Yum.inject.CommandInjector;
import pw.yumc.Yum.inject.ListenerInjector; import pw.yumc.Yum.inject.ListenerInjector;
import pw.yumc.Yum.inject.TaskInjector; import pw.yumc.Yum.inject.TaskInjector;
import pw.yumc.Yum.managers.ConfigManager; import pw.yumc.Yum.managers.ConfigManager;
import pw.yumc.Yum.managers.MonitorManager;
import pw.yumc.Yum.managers.MonitorManager.MonitorInfo;
/** /**
* *
@ -49,16 +51,20 @@ public class MonitorCommand implements HandlerCommands {
private final String avg = "§6平均耗时: §d%.5f毫秒!"; private final String avg = "§6平均耗时: §d%.5f毫秒!";
private final String avg_warn = "§6平均耗时: §c%.5f毫秒!"; private final String avg_warn = "§6平均耗时: §c%.5f毫秒!";
private final String injected = "§a插件 §b%s §a成功注入能耗监控器!"; private final String reinject = prefix + "§a能耗监控器重载完毕!";
private final String uninjected = "§a插件 §b%s §a成功撤销能耗监控器!"; private final String injected = prefix + "§a插件 §b%s §a成功注入能耗监控器!";
private final String notEnable = "§c插件 §b%s §c未成功加载 无法执行注入!"; private final String uninjected = prefix + "§a插件 §b%s §a成功撤销能耗监控器!";
private final String notEnable = prefix + "§c插件 §b%s §c未成功加载 无法执行注入!";
private final String lagprefix = "§6插件名称 §c主线程耗时 §a命令耗时 §b事件耗时 §d任务耗时";
private final String laglist = "§b%-15s §c%-11.2f §a%-9.2f §b%-9.2f §d%-9.2f";
private final String no_error = prefix + "§a自服务器启动以来尚未发现报错!"; private final String no_error = prefix + "§a自服务器启动以来尚未发现报错!";
private final String last_error = prefix + "§c最后一次错误异常由 §b%s §c造成 详细如下:"; private final String last_error = prefix + "§c最后一次错误异常由 §b%s §c造成 详细如下:";
private final String p_n_f = prefix + "§c插件 §b%s §c不存在!"; private final String p_n_f = prefix + "§c插件 §b%s §c不存在!";
private final double um = 1000000.0; private final double um = 1000000.00;
public MonitorCommand(final Yum yum) { public MonitorCommand(final Yum yum) {
final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "monitor"); final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "monitor");
@ -140,7 +146,7 @@ public class MonitorCommand implements HandlerCommands {
} }
for (final String event : eventTotalTime.keySet()) { for (final String event : eventTotalTime.keySet()) {
final StringBuffer str = new StringBuffer(); final StringBuffer str = new StringBuffer();
str.append("§6- §e" + event + " "); str.append(String.format("§6- §e%-25s ", event));
str.append(String.format(total, eventTotalTime.get(event) / um)); str.append(String.format(total, eventTotalTime.get(event) / um));
str.append(String.format(count, eventCount.get(event))); str.append(String.format(count, eventCount.get(event)));
if (eventCount.get(event) != 0) { if (eventCount.get(event) != 0) {
@ -162,9 +168,24 @@ public class MonitorCommand implements HandlerCommands {
} }
if (plugin.isEnabled()) { if (plugin.isEnabled()) {
YumAPI.inject(plugin); YumAPI.inject(plugin);
sender.sendMessage(String.format(prefix + injected, pname)); sender.sendMessage(String.format(injected, pname));
} else { } else {
sender.sendMessage(String.format(prefix + notEnable, pname)); sender.sendMessage(String.format(notEnable, pname));
}
}
@HandlerCommand(name = "lag", aliases = "l", description = "查看插件总耗时")
public void lag(final InvokeCommandEvent e) {
final CommandSender sender = e.getSender();
final Map<String, Long> mm = MonitorManager.getMonitor();
int i = 0;
sender.sendMessage(lagprefix);
for (final Entry<String, Long> entry : mm.entrySet()) {
if (i++ > 5) {
break;
}
final MonitorInfo mi = MonitorManager.getMonitorInfo(entry.getKey());
sender.sendMessage(String.format(laglist, entry.getKey(), mi.monitor, mi.cmd, mi.event, mi.task));
} }
} }
@ -182,6 +203,13 @@ public class MonitorCommand implements HandlerCommands {
} }
} }
@HandlerCommand(name = "reinject", aliases = "i", description = "重载能耗监控器")
public void reinject(final InvokeCommandEvent e) {
final CommandSender sender = e.getSender();
YumAPI.updateInject();
sender.sendMessage(reinject);
}
@HandlerCommand(name = "task", description = "查看插件任务能耗", minimumArguments = 1, possibleArguments = "[插件名称]") @HandlerCommand(name = "task", description = "查看插件任务能耗", minimumArguments = 1, possibleArguments = "[插件名称]")
public void task(final InvokeCommandEvent e) { public void task(final InvokeCommandEvent e) {
final String pname = e.getArgs()[0]; final String pname = e.getArgs()[0];
@ -199,8 +227,7 @@ public class MonitorCommand implements HandlerCommands {
if (task instanceof TaskInjector) { if (task instanceof TaskInjector) {
final TaskInjector executor = (TaskInjector) task; final TaskInjector executor = (TaskInjector) task;
final StringBuffer str = new StringBuffer(); final StringBuffer str = new StringBuffer();
final Class<? extends Runnable> taskName = executor.getOriginalTask().getClass(); str.append("§6- §e" + getClassName(executor.getOriginalTask().getClass()) + " ");
str.append("§6- §e" + (StrKit.isBlank(taskName.getSimpleName()) ? taskName.getName() : taskName.getSimpleName()) + " ");
str.append(String.format(total, executor.totalTime / um)); str.append(String.format(total, executor.totalTime / um));
str.append(String.format(count, executor.count)); str.append(String.format(count, executor.count));
if (executor.count != 0) { if (executor.count != 0) {
@ -223,7 +250,11 @@ public class MonitorCommand implements HandlerCommands {
} }
if (plugin.isEnabled()) { if (plugin.isEnabled()) {
YumAPI.uninject(plugin); YumAPI.uninject(plugin);
sender.sendMessage(String.format(prefix + uninjected, pname)); sender.sendMessage(String.format(uninjected, pname));
} }
} }
private String getClassName(final Class<?> clazz) {
return StrKit.isBlank(clazz.getSimpleName()) ? clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1) : clazz.getSimpleName();
}
} }

View File

@ -253,7 +253,9 @@ public class YumCommand implements HandlerCommands, Listener {
fm.then(unload).command("yum unload " + pname); fm.then(unload).command("yum unload " + pname);
fm.then(" "); fm.then(" ");
fm.then(reload).command("yum re " + pname); fm.then(reload).command("yum re " + pname);
fm.then(" ");
fm.then(delete).command("yum del " + pname); fm.then(delete).command("yum del " + pname);
fm.send(sender);
} }
} }

View File

@ -18,6 +18,7 @@ import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.kit.PluginKit; import cn.citycraft.PluginHelper.kit.PluginKit;
import cn.citycraft.PluginHelper.kit.StrKit; import cn.citycraft.PluginHelper.kit.StrKit;
import pw.yumc.Yum.commands.MonitorCommand; import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.MonitorManager;
public class CommandInjector implements TabExecutor { public class CommandInjector implements TabExecutor {
private final String prefix = "§6[§bYum §a命令监控§6] "; private final String prefix = "§6[§bYum §a命令监控§6] ";
@ -43,11 +44,13 @@ public class CommandInjector implements TabExecutor {
final PluginCommand pluginCommand = (PluginCommand) command; final PluginCommand pluginCommand = (PluginCommand) command;
final Plugin plugin = pluginCommand.getPlugin(); final Plugin plugin = pluginCommand.getPlugin();
if (plugin.equals(toInjectPlugin)) { if (plugin.equals(toInjectPlugin)) {
final CommandExecutor executor = Reflect.on(command).get("executor"); CommandExecutor executor = Reflect.on(command).get("executor");
TabCompleter completer = Reflect.on(command).get("completer");;
if (executor instanceof CommandInjector) { if (executor instanceof CommandInjector) {
return; final CommandInjector cInjector = (CommandInjector) executor;
executor = cInjector.getOriginalExecutor();
completer = cInjector.getOriginalCompleter();
} }
final TabCompleter completer = Reflect.on(command).get("completer");
final CommandInjector commandInjector = new CommandInjector(executor, completer, toInjectPlugin); final CommandInjector commandInjector = new CommandInjector(executor, completer, toInjectPlugin);
Reflect.on(command).set("executor", commandInjector); Reflect.on(command).set("executor", commandInjector);
Reflect.on(command).set("completer", commandInjector); Reflect.on(command).set("completer", commandInjector);
@ -100,6 +103,7 @@ public class CommandInjector implements TabExecutor {
} }
totalTime += lag; totalTime += lag;
count++; count++;
MonitorManager.addCmd(plugin.getName(), lag);
return result; return result;
} catch (Throwable e) { } catch (Throwable e) {
while (e.getCause() != null) { while (e.getCause() != null) {

View File

@ -17,6 +17,7 @@ import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.kit.PluginKit; import cn.citycraft.PluginHelper.kit.PluginKit;
import pw.yumc.Yum.commands.MonitorCommand; import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.ConfigManager; import pw.yumc.Yum.managers.ConfigManager;
import pw.yumc.Yum.managers.MonitorManager;
public class ListenerInjector implements EventExecutor { public class ListenerInjector implements EventExecutor {
private final String prefix = "§6[§bYum §a事件监控§6] "; private final String prefix = "§6[§bYum §a事件监控§6] ";
@ -40,9 +41,9 @@ public class ListenerInjector implements EventExecutor {
if (listener instanceof TimedRegisteredListener) { if (listener instanceof TimedRegisteredListener) {
return; return;
} }
final EventExecutor originalExecutor = Reflect.on(listener).get("executor"); EventExecutor originalExecutor = Reflect.on(listener).get("executor");
if (originalExecutor instanceof ListenerInjector) { if (originalExecutor instanceof ListenerInjector) {
return; originalExecutor = ((ListenerInjector) originalExecutor).getOriginalExecutor();
} }
final ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin); final ListenerInjector listenerInjector = new ListenerInjector(originalExecutor, plugin);
Reflect.on(listener).set("executor", listenerInjector); Reflect.on(listener).set("executor", listenerInjector);
@ -82,6 +83,7 @@ public class ListenerInjector implements EventExecutor {
eventTotalTime.put(en, end - start); eventTotalTime.put(en, end - start);
eventCount.put(en, 1); eventCount.put(en, 1);
} }
MonitorManager.addEvent(plugin.getName(), lag);
} else { } else {
originalExecutor.execute(listener, event); originalExecutor.execute(listener, event);
} }

View File

@ -11,6 +11,7 @@ import cn.citycraft.PluginHelper.ext.kit.Reflect;
import cn.citycraft.PluginHelper.kit.PluginKit; import cn.citycraft.PluginHelper.kit.PluginKit;
import cn.citycraft.PluginHelper.kit.StrKit; import cn.citycraft.PluginHelper.kit.StrKit;
import pw.yumc.Yum.commands.MonitorCommand; import pw.yumc.Yum.commands.MonitorCommand;
import pw.yumc.Yum.managers.MonitorManager;
public class TaskInjector implements Runnable { public class TaskInjector implements Runnable {
private final String prefix = "§6[§bYum §a任务监控§6] "; private final String prefix = "§6[§bYum §a任务监控§6] ";
@ -38,9 +39,9 @@ public class TaskInjector implements Runnable {
for (final BukkitTask pendingTask : pendingTasks) { for (final BukkitTask pendingTask : pendingTasks) {
// 忽略异步任务 // 忽略异步任务
if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) { if (pendingTask.isSync() && pendingTask.getOwner().equals(plugin)) {
final Runnable originalTask = Reflect.on(pendingTask).get("task"); Runnable originalTask = Reflect.on(pendingTask).get("task");
if (originalTask instanceof TaskInjector) { if (originalTask instanceof TaskInjector) {
return; originalTask = ((TaskInjector) originalTask).getOriginalTask();
} }
final TaskInjector taskInjector = new TaskInjector(originalTask, plugin); final TaskInjector taskInjector = new TaskInjector(originalTask, plugin);
Reflect.on(pendingTask).set("task", taskInjector); Reflect.on(pendingTask).set("task", taskInjector);
@ -80,6 +81,7 @@ public class TaskInjector implements Runnable {
} }
totalTime += lag; totalTime += lag;
count++; count++;
MonitorManager.addTask(plugin.getName(), lag);
} catch (Throwable e) { } catch (Throwable e) {
while (e.getCause() != null) { while (e.getCause() != null) {
e = e.getCause(); e = e.getCause();

View File

@ -9,6 +9,7 @@ import org.bukkit.event.server.PluginEnableEvent;
import cn.citycraft.PluginHelper.kit.PKit; import cn.citycraft.PluginHelper.kit.PKit;
import cn.citycraft.PluginHelper.kit.PluginKit; import cn.citycraft.PluginHelper.kit.PluginKit;
import pw.yumc.Yum.api.YumAPI; import pw.yumc.Yum.api.YumAPI;
import pw.yumc.Yum.managers.MonitorManager;
/** /**
* *
@ -29,6 +30,7 @@ public class PluginListener implements Listener {
@EventHandler @EventHandler
public void onPluginEnable(final PluginEnableEvent e) { public void onPluginEnable(final PluginEnableEvent e) {
MonitorManager.reset(e.getPlugin().getName());
PluginKit.runTaskLater(new Runnable() { PluginKit.runTaskLater(new Runnable() {
@Override @Override
public void run() { public void run() {

View File

@ -0,0 +1,98 @@
package pw.yumc.Yum.managers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
*
* @since 2016年7月19日 下午3:55:54
* @author
*/
public class MonitorManager {
private static Map<String, Long> monitor = new HashMap<>();
private static Map<String, Long> task = new HashMap<>();
private static Map<String, Long> event = new HashMap<>();
private static Map<String, Long> cmd = new HashMap<>();
private final static double um = 1000000.00;
public static void addCmd(final String pname, final long time) {
monitor.put(pname, monitor.get(pname) + time);
cmd.put(pname, cmd.get(pname) + time);
}
public static void addEvent(final String pname, final long time) {
monitor.put(pname, monitor.get(pname) + time);
event.put(pname, event.get(pname) + time);
}
public static void addTask(final String pname, final long time) {
monitor.put(pname, monitor.get(pname) + time);
task.put(pname, task.get(pname) + time);
}
public static Map<String, Long> getMonitor() {
return sortMapByValue(monitor);
}
public static MonitorInfo getMonitorInfo(final String pname) {
return new MonitorInfo(monitor.get(pname) / um, cmd.get(pname) / um, event.get(pname) / um, task.get(pname) / um);
}
public static void reset(final String pname) {
monitor.put(pname, 0L);
task.put(pname, 0L);
event.put(pname, 0L);
cmd.put(pname, 0L);
}
/**
* 使用 Map按value进行排序
*
* @param map
* @return
*/
public static Map<String, Long> sortMapByValue(final Map<String, Long> oriMap) {
if (oriMap == null || oriMap.isEmpty()) {
return null;
}
final Map<String, Long> sortedMap = new LinkedHashMap<String, Long>();
final List<Map.Entry<String, Long>> entryList = new ArrayList<Map.Entry<String, Long>>(oriMap.entrySet());
Collections.sort(entryList, new MonitorComparator());
final Iterator<Map.Entry<String, Long>> iter = entryList.iterator();
Entry<String, Long> tmpEntry = null;
while (iter.hasNext()) {
tmpEntry = iter.next();
sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue());
}
return sortedMap;
}
public static class MonitorInfo {
public double monitor;
public double cmd;
public double event;
public double task;
public MonitorInfo(final double monitor, final double cmd, final double event, final 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(final Entry<String, Long> o1, final Entry<String, Long> o2) {
return o2.getValue().compareTo(o1.getValue());
}
}
}