Is it possible to do this ?
The problem is, that huge applications have tons of servlet filters for instance. And each exception that is thrown regarding http request contains 250 lines when 160 of them is from catalina/tomcat stack, which is absolutely not important.
And having 250 lines long stack traces is very hard to work with.
Yes, it is possible to manipulate the stack trace. As said, it depends on where you want to (and can) attack the problem.
As an example:
For a remote method-call protocol I implemented for our project, in the case of an exception we catch it at the target side, cut off the lower some StackTraceElements (which are always the same, until the actual calling of the target method with reflection), and send the exception with the important part of the stack trace to the caller side.
There I reconstruct the exception with its (sent) stack trace, and then merge it with the current Stack trace. For this, we also remove the top some elements of the current stack trace (which contain only calls of the remote-call framework):
private void mergeStackTraces(Throwable error)
{
StackTraceElement[] currentStack =
new Throwable().getStackTrace();
int currentStackLimit = 4; // TODO: raussuchen
// We simply cut off the top 4 elements, which is just
// right for our framework. A more stable solution
// would be to filter by class name or such.
StackTraceElement[] oldStack =
error.getStackTrace();
StackTraceElement[] zusammen =
new StackTraceElement[currentStack.length - currentStackLimit +
oldStack.length + 1];
System.arraycopy(oldStack, 0, zusammen, 0, oldStack.length);
zusammen[oldStack.length] =
new StackTraceElement("══════════════════════════",
"<remote call %" +callID+ ">",
"", -3);
System.arraycopy(currentStack, currentStackLimit,
zusammen, oldStack.length+1,
currentStack.length - currentStackLimit);
error.setStackTrace(zusammen);
}
This gives, for example, this trace printed:
java.lang.SecurityException: The user example does not exist
at de.fencing_game.db.userdb.Db4oUserDB.login(Db4oUserDB.java:306)
at de.fencing_game.server.impl.StandardServers$SSServer$1.run(StandardServers.java:316)
at de.fencing_game.server.impl.StandardServers$SSServer$1.run(StandardServers.java:314)
at java.security.AccessController.doPrivileged(Native Method)
at de.fencing_game.server.impl.StandardServers$SSServer.login(StandardServers.java:313)
at de.fencing_game.transport.server.ServerTransport$ConnectionInfo$4.login(ServerTransport.java:460)
at ══════════════════════════.<remote call %2>()
at $Proxy1.login(Unknown Source)
at de.fencing_game.gui.basics.LoginUtils.login(LoginUtils.java:80)
at de.fencing_game.gui.Lobby.connectTo(Lobby.java:302)
at de.fencing_game.gui.Lobby$20.run(Lobby.java:849)
Of course, for your case you would better simply iterate through your array, copy the important elements into a list, and then set this as the new stackTrace. Make sure to do this for the causes (i.e. linked throwables), too.
You can do this in the constructor of your exceptions, or where you print the stack traces, or anywhere between (where you catch, manipulate and rethrow the exception).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With