1

EDIT2 @paradigmatic
は、例外をスローするのではなく、リダイレクトすることを提案することで適切な指摘をしました。これにより、ログの問題が解決されます。Play 2 の問題は、リダイレクトがいわゆるActionスコープ内で発生する必要があることです。これは、日付パーサー呼び出しの場合は必ずしもそうではありません。

回避策として、おそらく Java サーブレット フィルターに相当する Play のグローバル インターセプターを使用しました。

val ymdMatcher = "\\d{8}".r // matcher for yyyyMMdd URI param
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
def ymd2Date(ymd: String) = ymdFormat.parseDateTime(ymd)

override def onRouteRequest(r: RequestHeader): Option[Handler] = {
  import play.api.i18n.Messages
  ymdMatcher.findFirstIn(r.uri) map{ ymd=>
    try { ymd2Date( ymd); super.onRouteRequest(r) }
    catch { case e:Exception => // kick to "bad" action handler on invalid date 
      Some(controllers.Application.bad(Messages("bad.date.format"))) 
    }
  } getOrElse(super.onRouteRequest(r))
}

EDIT
ここで作業するための小さなコンテキストです:

// String "pimp": transforms ymdString.to_date call into JodaTime instance
class String2Date(ymd: String) {
  def to_date = {  
    import play.api.i18n.Messages
    try{ ymdFormat.parseDateTime(ymd) } 
    catch { case e:Exception => throw new NoTrace(Messages("bad.date.format")) }
  }
  val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
}
@inline implicit final def string2Date(ymd: String) = new String2Date(ymd)

およびテスト カスタム例外ハンドラー:

public class NoTrace extends Exception {
  static final long serialVersionUID = -3387516993124229948L;

  @Override
  public Throwable fillInStackTrace() {
      return null;
  }      
  public NoTrace(String message) {
    super(message);
  }
}

無効な yyyyMMdd 文字列で日付パーサーを呼び出すと、30 行のスタック トレースがログに記録されます (これは Play フレームワーク/Netty コンテナーによって上流で発生し、デフォルトの 100 行のトレースよりも優れています):

"20120099".to_date

オリジナル
有効な uri 日付があれば成功するはずの uri 日付パーサー操作に関連するエラーで application.log がいっぱいになるという問題がありyyyyMMddます。

ただし、一部のユーザーは、有料の加入者限定コンテンツに無料でアクセスできることを期待して、無効な日付を入力することでこれを回避しようとします. 単純に機能しないので意味がありませんが、いずれにせよ、アプリケーション ログにこれらのエラー トレースが何 MB も記録されています。

本当にトリミングされExceptionたものを丸太に投げる方法はありますか? 私はこの SO answerを見つけましたが、私のアプリケーションでは、コンテナー (Netty の Play フレームワーク) が混在しているように見え、独自の 30 行のスタック トレースをログに記録します (30 行は 100 行よりも優れていますが、それでも 29 行が多すぎます)。

同様に、Java 7 とスタック トレースを抑制する新しいオプションに関して、このスレッドを見つけました。ただし、何らかの理由で、Java 1.7 上にあり、Java 1.7 用に構成された Eclipse を使用しているにもかかわらず、Throwable の古い 2 パラメータ メソッドしか使用できません (そして、Throwable クラスをクリックすると 4 パラメータ メソッドが表示されます。おそらく Scala 2.9.2 ライブラリの問題?)

いずれにせよ、キッチン シンクではなく、1 行の例外メッセージをログに記録できることが理想的です。

4

3 に答える 3

3

カスタム例外クラスでこのメソッドをオーバーライドするだけです。

@Override
public Throwable fillInStackTrace() {
    return this;
}      

このメソッドを追加した後、トレース メソッドは印刷されません

于 2018-12-10T05:24:58.940 に答える
2

問題は、独自のコードがスローした例外のスタックトレースを抑制することはできますが、フレームワークによってラップされる例外については何もできないことです。私が見ることができる唯一の手段は、フレームワークが例外をまったくキャッチできないようにする (独自のトップレベル処理を行う) か、ロギング構成を微調整することです。

于 2012-11-17T11:59:32.183 に答える
2

次の 2 つのオプションがあると思います。

  1. 一部の例外のスタック トレースを保存しないようにログを制御します。
  2. ログ ファイルからトレースを除外するポスト プロセッサを記述します。

ディスク容量が不足する危険がない限り、#2 の方が適切なオプションだと思います。なぜなら、バグがある場合は、完全なログに戻って、すべての例外履歴を取得できるからです。

アイデア 2 の背後にある哲学は、ディスク容量は安価ですが、デバッグ中は情報が貴重になる可能性があるというものです。大量のデータをログに記録します。通常、ログがディスクに書き込まれた後、スクリプトを使用してログを調べます。

たとえば、表示されるとはまったく予想していないが、表示された場合はすぐに対処する必要があるタイプのログ エントリがある場合は、それを検索するスクリプトを作成し、見つかった場合は電子メールを送信します。

このアプローチで最も有用なスクリプト形式の 1 つは、スタック トレース行をドロップするものです。通常、どのような例外が発生しているかを知る必要があるだけで、スタック トレースは多くの情報を提供せずに多くの画面スペースを占有します。例外を調査する必要がある場合は、完全なログに戻って例外行を見つけ、スタック トレースと例外の直前に何が起こっていたかを調べます。

日付の例外が多すぎる場合は、スクリプトで例外行を削除します。発生頻度を追跡する場合は、1 時間あたりの日付例外をカウントするスクリプトを実行します。

通常、この種のスクリプトは、お気に入りの正規表現対応スクリプト言語でプログラミングするのに数分かかります。

于 2012-11-17T12:13:00.253 に答える