This is a little code snippet I just developed. You can use it to catch exceptions in your code and point your users in the right direction what do do with this stacktraces. To use it just put in in your main class, then call Code:java try{ // some code that may be buggy}catch(*Excetion/Throwable e){ plugin.printStackTrace(e);} Feel free to modify it, but don't modify it to much cause if we could reach some kind of standard for error handling users will be way less confused. Here it is: Code:java void printStackTrace(Throwable t) { Logger log = getLogger(); log.severe(""); log.severe("Internal error!"); log.severe("If this bug hasn't been reported please open a ticket at "+getDescription().getWebsite()); log.severe("Include the following into your bug report:"); log.severe(" ======= SNIP HERE ======="); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); t.printStackTrace(pw); for(String l: sw.toString().replace("\r", "").split("\n")) log.severe(l); pw.close(); try { sw.close(); } catch(IOException e) { } log.severe(" ======= SNIP HERE ======="); log.severe(""); } Please note that it works best if the website in the plugin.yml points to the project site at bukkitdev. Hardcore usage: You could change the code to something like this: Code:java void printStackTrace(Throwable t, boolean unknown) { Logger log = getLogger(); log.severe(""); log.severe("Internal error!"); log.severe("If this bug hasn't been reported please open a ticket at "+getDescription().getWebsite()); log.severe("Include the following into your bug report:"); log.severe(" ======= SNIP HERE ======="); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); t.printStackTrace(pw); for(String l: sw.toString().replace("\r", "").split("\n")) log.severe(l); pw.close(); try { sw.close(); } catch(IOException e) { } log.severe(" ======= SNIP HERE ======="); log.severe(""); if(unknown) getServer().getPluginManager().disablePlugin(this); } Then add throws Throwable to every function (except it still throws something other) and finally catch it at some point and call: Code:java catch{ plugin.printStackTrace(Throwable t, true); return;} while you could call the same with false if you expect some bugs but you're sure they won't harm future code execution. Example output (thanks to @beleg ): Code: 14:49:28 [SEVERE] [ColoredTablist] 14:49:28 [SEVERE] [ColoredTablist] Internal error! 14:49:28 [SEVERE] [ColoredTablist] If this bug hasn't been reported please open a ticket at www.mcheaven.com 14:49:28 [SEVERE] [ColoredTablist] Include the following into your bug report: 14:49:28 [SEVERE] [ColoredTablist] ======= SNIP HERE ======= 14:49:28 [SEVERE] [ColoredTablist] java.lang.ArrayIndexOutOfBoundsException: 3 14:49:28 [SEVERE] [ColoredTablist] at com.mcheaven.coloredtablist.CT_Comman ds.onCommand(CT_Commands.java:189) 14:49:28 [SEVERE] [ColoredTablist] at org.bukkit.command.PluginCommand.exec ute(PluginCommand.java:40) 14:49:28 [SEVERE] [ColoredTablist] at org.bukkit.command.SimpleCommandMap.d ispatch(SimpleCommandMap.java:166) 14:49:28 [SEVERE] [ColoredTablist] at org.bukkit.craftbukkit.CraftServer.di spatchCommand(CraftServer.java:479) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.NetServerHandler .handleCommand(NetServerHandler.java:821) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.NetServerHandler .chat(NetServerHandler.java:781) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.NetServerHandler .a(NetServerHandler.java:764) 14:49:28 [SEVERE] [ColoredTablist] at org.getspout.spout.SpoutNetServerHand ler.a(SpoutNetServerHandler.java:103) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.Packet3Chat.hand le(Packet3Chat.java:34) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.NetworkManager.b (NetworkManager.java:229) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.NetServerHandler .a(NetServerHandler.java:113) 14:49:28 [SEVERE] [ColoredTablist] at org.getspout.spout.SpoutNetServerHand ler.a(SpoutNetServerHandler.java:169) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.NetworkListenThr ead.a(NetworkListenThread.java:78) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.MinecraftServer. w(MinecraftServer.java:567) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.MinecraftServer. run(MinecraftServer.java:459) 14:49:28 [SEVERE] [ColoredTablist] at net.minecraft.server.ThreadServerAppl ication.run(SourceFile:492) 14:49:28 [SEVERE] [ColoredTablist] ======= SNIP HERE ======= 14:49:28 [SEVERE] [ColoredTablist]
Interesting :} I want to suggest to allow better reading and copy/paste-ability by making the stacktrace a single buffered string with newlines... Your example edited so you understand what I'm saying: Code: 14:49:28 [SEVERE] [ColoredTablist] 14:49:28 [SEVERE] [ColoredTablist] Internal error! 14:49:28 [SEVERE] [ColoredTablist] If this bug hasn't been reported please open a ticket at www.mcheaven.com 14:49:28 [SEVERE] [ColoredTablist] Include the following into your bug report: 14:49:28 [SEVERE] [ColoredTablist] ======= SNIP HERE ======= java.lang.ArrayIndexOutOfBoundsException: 3 at com.mcheaven.coloredtablist.CT_Commands.onCommand(CT_Commands.java:189) at org.bukkit.command.PluginCommand.execute(PluginCommand.java:40) at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:166) at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:479) at net.minecraft.server.NetServerHandler.handleCommand(NetServerHandler.java:821) at net.minecraft.server.NetServerHandler.chat(NetServerHandler.java:781) at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:764) at org.getspout.spout.SpoutNetServerHandler.a(SpoutNetServerHandler.java:103) at net.minecraft.server.Packet3Chat.handle(Packet3Chat.java:34) at net.minecraft.server.NetworkManager.b(NetworkManager.java:229) at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:113) at org.getspout.spout.SpoutNetServerHandler.a(SpoutNetServerHandler.java:169) at net.minecraft.server.NetworkListenThread.a(NetworkListenThread.java:78) at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:567) at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:459) at net.minecraft.server.ThreadServerApplication.run(SourceFile:492) 14:49:28 [SEVERE] [ColoredTablist] ======= SNIP HERE ======= 14:49:28 [SEVERE] [ColoredTablist] You could also make the messages coloured to pop-out but add spaces after the colors so they can be read in server.log since not everybody uses the "-log-strip-color=true" param :/ EDIT: actually, I don't know why you're using all those methods for printing the message with log.severe() when exception.printStackTrace(); already does that as far as I can see in the logs :-??
This is because some server wrappers seem to cut things printed to the console directly instead of using the logger. I developed some plugins for some guys in the past and they all had the same problem: They were unable to provide stacktraces (cause they didn't see them at the web interface and they where to lazy/noobish/whatever to find them in the server.log file). By using the logger I'm getting sure the stacktrace will be visible everywhere. So I shouldn't use the logger for the stacktrace? But I use it for a reason (see above). Also: For the user it's better to understand if all lines have the same prefix and for the dev it shouldn't be that hard to filter them out by reading the stacktrace.
But you see with the eyes of a developer. Try to see it with the eyes of the average user that just sees some wired lines and not a stacktrace.