6

改善が必要なやや不十分な設計の WCF サービスを継承しました。問題の 1 つは、(2 つの異なるインターフェイス上に) 100 を超えるメソッドがあり、そのほとんどが使用されていないことです。各メソッドにログを記録して、いつ、どのように呼び出されたかを追跡することにしました。トレース コードをリファクタリングしやすく、入力ミスを防止するために、次のように実装しました。

public void LogUsage()
{
    try
    {
        MethodBase callingMethod = new StackTrace().GetFrame(1).GetMethod();
        string interfaceName = callingMethod.DeclaringType.GetInterfaces()[0].Name;
        _loggingDao.LogUsage(interfaceName, callingMethod.Name, GetClientAddress(), GetCallingUrl());
    }
    catch (Exception exception)
    {
        _legacyLogger.Error("Error in usage tracking", exception);
    }
}

LogUsage()次に、トレースする各メソッドの開始時に呼び出されます。

このサービスは非常にトラフィックが多く、1 日あたり 500,000 件以上の通話があります。99.95% の確率で、このコードは美しく実行されます。しかし、残りの 0.05% の時間GetInterfaces()は、空の (しかし ではないnull) 配列を返します。

GetInterfaces()一貫性のない結果が時々返されるのはなぜですか?

これは些細なことのように思えるかもしれません。0.05% のエラー率は、私たちが通常夢見ることしかできないものです。しかし、要点はすべてのサービス タッチポイントを特定することです。このエラーが常に 1 つ (またはいくつか) のメソッド呼び出しから発生する場合、トレースは不完全です。サービスのすべてのメソッドを呼び出して、開発環境でこのエラーを再現しようとしましたが、役に立ちませんでした。

4

2 に答える 2

4

StackTrace特にマルチスレッド環境では、信頼性が低いことで有名です。というか、信頼性は高いですが、あまり実用的ではありません。「最後に呼び出されたメソッド」を尋ねると、予期しない結果になる可能性があります。DeclaringType をログに記録してみてください。そこで見つけたものに驚くかもしれません。これは現在 0.05% の失敗率ですが、アプリケーションの複雑さによって簡単に増加する可能性があることに注意してください。

再利用可能なトレース コードを適切に実装するには、動的プロキシ (例: Castle Dynamic Proxy ) を使用するか、 PostSharpなどの AOP フレームワークを使用して、.NET 4.5 機能のCaller Informationに依存する必要があります。または、手動でトレースをコーディングすることもできます。

于 2012-09-20T20:46:30.990 に答える
3

Erik Lippert (MS の C# コンパイラ チームで働いている)から、Getting Type T from a StackFrameへの応答:

スタック フレームは、誰がメソッドを呼び出したかを実際には通知しません。スタック フレームは、制御がどこに戻るかを示します。スタック フレームは継続の具体化です。誰がメソッドを呼び出し、どこに制御が戻るかがほぼ常に同じであるという事実が混乱の原因ですが、それらが同じである必要はないことを保証します。

投稿全体を読む価値があります...

于 2012-09-21T14:33:21.600 に答える