これは可能ですか?スタックトレースに特定のクラスタイプが含まれないように例外をスローする
問題は、巨大なアプリケーションには、例えばサーブレットフィルタがたくさんあることです。そして、HTTPリクエストに関してスローされた各例外は、160行がcatalina/tomcatスタックからのものであれば250行を含みますが、これは絶対に重要ではありません。
250行のスタックトレースを持つことは非常に困難です。
これは可能ですか?スタックトレースに特定のクラスタイプが含まれないように例外をスローする
問題は、巨大なアプリケーションには、例えばサーブレットフィルタがたくさんあることです。そして、HTTPリクエストに関してスローされた各例外は、160行がcatalina/tomcatスタックからのものであれば250行を含みますが、これは絶対に重要ではありません。
250行のスタックトレースを持つことは非常に困難です。
はい、スタックトレースを操作することは可能です。言われているように、それはあなたがどこに問題を攻撃したいか(そしてできるか)によって決まります。一例として、
は、(下のいくつかのStackTraceElementsを遮断していますリフレクション付きのターゲットメソッドの実際の呼び出しまで常に同じです)、スタックトレースの重要な部分を含む例外を呼び出し側に送信します。
ここでは、(送信された)スタックトレースで例外を再構築し、それを現在のスタックトレースとマージします。このため 、我々はまた、トップに(リモートコール・フレームワークの呼び出しのみが含まれている)現在のスタックトレースのいくつかの要素を削除します。
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);
}
これは、例えば、このトレースが印刷され、与えられる:
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)
もちろん、あなたの場合は、配列を繰り返し処理し、重要な要素をリストにコピーして、これを新しいstackTraceとして設定することをお勧めします。原因(リンクされたスローアブル)についてもこれを行うようにしてください。
例外のコンストラクタ、またはスタックトレースを印刷する場所、またはその間のどこか(例外を捕捉し、操作し、再実行する場所)でこれを行うことができます。
行を読み込み、特定の正規表現に一致するものを排除する出力ストリームを作成することができます。
次に、Exception.printStackTrace(YourFilteredOutputStream)を使用します。
log4jを使用している場合は、これを行うAppenderを作成できます。架空のAppender使用
Log4jの構成(Examples):
<appender name="TRACE" class="com.example.YourAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%t] %-5p %c - %m%n" />
</layout>
</appender>
私を、私はおそらくサブクラスFileAppenderを希望は:
public class YourAppender extends FileAppender {
public YourAppender(...) {
super(...);
}
public void doAppend(LoggingEvent ev) {
String message = ev.getMessage(); // or ev.getRenderedMessage();
// build new LoggingEvent
LoggingEvent newEv = new LoggingEvent(/* params from old loggingg event */);
super.doAppend(newEv);
}
}
あなたがキャッチ例外のためのあなたのスタックトレースからエントリを削除することができます。例外に対してprintStackTraceをオーバーライドすることができます。カスタムロガーを作成して、特定の行を無視することもできます。あなたがコントロールしているものによって大きく異なります。
私は共感します。 望ましくないStackTraceElementsを隠し、独自のスタックトレース出力を生成する方法はありますか?カスタムロガーでこのようなコードを使用することができます
Set<String> hideClassNames = ....;
...
void print(Throwable t, PrintStream out) {
for (Throwable c = e; c != null;) {
for (StackTraceElement e : c.getStackTrace()) {
if (!hideClassNames.contains(e.getClassName())) {
out.println(e.getClassName() +
"." + e.getMethodName() +
" (" + e.getFileName() +
":" + e.getLineNumber()) + ")";
}
}
c = c.getCause();
if (c != null) {
out.println("Caused by");
}
}
:このような
何か。キャッチされない例外をログに記録することもできます。
Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
print(t, System.err);
}
};
Thread.setDefaultUncaughtExceptionHandler(handler);
これはちょっと古い投稿ですが、Log4JまたはSL4Jを使用する場合は、必要な項目のみを表示するようにプロパティを設定できます。それは非常に柔軟です。
これはまだフィルタリングを逃しています:-p –
@Paulo、私はコードでそれを逃していました - 今修正。 –