[code snippet] User friendly stacktraces

Discussion in 'Resources' started by V10lator, Jun 19, 2012.

?

Is this helpfull?

  1. Yes

    3 vote(s)
    100.0%
  2. No

    0 vote(s)
    0.0%
Thread Status:
Not open for further replies.
  1. 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
    1. try
    2. {
    3. // some code that may be buggy
    4. }
    5. catch(*Excetion/Throwable e)
    6. {
    7. plugin.printStackTrace(e);
    8. }

    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
    1. void printStackTrace(Throwable t)
    2. {
    3. Logger log = getLogger();
    4. log.severe("");
    5. log.severe("Internal error!");
    6. log.severe("If this bug hasn't been reported please open a ticket at "+getDescription().getWebsite());
    7. log.severe("Include the following into your bug report:");
    8. log.severe(" ======= SNIP HERE =======");
    9. PrintWriter pw = new PrintWriter(sw);
    10. t.printStackTrace(pw);
    11. for(String l: sw.toString().replace("\r", "").split("\n"))
    12. log.severe(l);
    13. pw.close();
    14. try
    15. {
    16. sw.close();
    17. }
    18. catch(IOException e)
    19. {
    20. }
    21. log.severe(" ======= SNIP HERE =======");
    22. log.severe("");
    23. }

    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
    1. void printStackTrace(Throwable t, boolean unknown)
    2. {
    3. Logger log = getLogger();
    4. log.severe("");
    5. log.severe("Internal error!");
    6. log.severe("If this bug hasn't been reported please open a ticket at "+getDescription().getWebsite());
    7. log.severe("Include the following into your bug report:");
    8. log.severe(" ======= SNIP HERE =======");
    9. PrintWriter pw = new PrintWriter(sw);
    10. t.printStackTrace(pw);
    11. for(String l: sw.toString().replace("\r", "").split("\n"))
    12. log.severe(l);
    13. pw.close();
    14. try
    15. {
    16. sw.close();
    17. }
    18. catch(IOException e)
    19. {
    20. }
    21. log.severe(" ======= SNIP HERE =======");
    22. log.severe("");
    23. if(unknown)
    24. getServer().getPluginManager().disablePlugin(this);
    25. }

    Then add
    throws Throwable
    to every function (except it still throws something other) and finally catch it at some point and call:
    Code:java
    1. catch
    2. {
    3. plugin.printStackTrace(Throwable t, true);
    4. return;
    5. }

    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]
     
    codename_B and beleg like this.
  2. 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 :p 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 :-??
     
  3. 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. :)
     
  4. I find it alot cleaner and easier to notice errors when they're without prefix but anyway :p
     
  5. 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. ;)
     
Thread Status:
Not open for further replies.

Share This Page