2016-10-01 1 views
0

メソッドの実行時間の記録については、他にも多くの投稿があります(たとえば、postsharpaction filters、またはカスタムメソッド属性を通じて)。C#MVCロギングメソッドの実行とパフォーマンス

したがって、メソッドの完了時間を記録することは、この時点では比較的簡単です。

しかし、私は何を望んでいるのですか?たとえば、要求ごとに発生したすべての操作を追跡するために、セッションIDを使用して、要求ごとにより詳細なパフォーマンスメトリックを取得することです。それらのすべては、親(つまりアクションコントローラ)メソッドだけではありません。

例えば、私のような何かをできるようにしたいと思います:理想的には私が一緒にこれらの操作のすべての(親メソッド、サービスコールとDBの呼び出し)をリンクさせたい

namespace MvcApplication1.Controllers 
{ 
    public class ProductController : Controller 
    { 
     //record start of method 
     public ActionResult Index() 
     { 
      //record start of service1.method call 
      var data = service1.method(); 
      //store total time of service1.method call 

      //record start of db call 
      var objects = db.select(obj).where(id=0) 
      //store total time of db call 

      return View(); 
     } 
     //record total time of method 
    } 
} 

を - 最も可能性の高い候補はセッションIDを介していますが、それは各呼び出しがセッションIDにアクセスする必要があることを意味します。

これを達成する最良の方法は、親のパフォーマンス時間を記録するためにメソッド属性を使用し、次にコールのさまざまなタイミングを格納するカスタムライブラリ関数を使用することです(おそらく記録するnlog)。

私が尋ねるのは、上記を達成するための最良の方法(可能な限り)についての意見です。

UnityやPostsharpがこの機能(または他のライブラリ)を提供しているサードパーティのライブラリで何か不足していますか?

これらのレコードをすべてセッションIDでリンクすることはできますか?例えば、postsharp(1)MVCアクションの中の個々のメソッド呼び出しを格納する方法、(2)呼び出しの間で変数を渡す方法はありません。

答えて

0

ご質問に応じて、リクエストに関連するすべての操作を記録する必要があります。私は私の視点を提供するつもりです、私は役に立つと思います。

既存のフレームワークを使用するかどうかは、さまざまな理由によって異なりますが、ここでは焦点を合わせてカスタム実装に焦点を当てます。

ログ構造を必要とするこの問題を達成するために、まず:

using System; 

public enum LogEntryType 
{ 
    Event, 
    Message, 
    Warning, 
    Error 
} 

public class LogEntry 
{ 
    public int? LogEntryID { get; set; } 

    public int? LogEntryType { get; set; } 

    public DateTime? EntryDate { get; set; } 

    public TimeSpan? ElapsedTime { get; set; } 

    public string Key { get; set; } 

    public string Description { get; set; } 
} 

次に、あなたはロガーオブジェクトを作成し、たとえば、ログインする各点を呼び出す必要があります。

namespace MvcApp.Controllers 
{ 
    public class ProductController : Controller 
    { 
     protected ILogger Logger; 

     public ProductController(ILogger logger;) 
     { 
      Logger = logger; 
     } 

     public ActionResult Index() 
     { 
      Logger.Write(LogEntry.Event, Server.SessionID, "Start of '{0}' action call", "Index"); 


      var serviceStopwatch = Stopwatch.StartNew(); 

      Logger.Write(LogEntry.Task, Server.SessionID, "Start of '{0}' task's execution", "GetData"); 

      var data = service.GetData(); 

      serviceStopwatch.Stop(); 

      Logger.Write(LogEntry.Task, Server.SessionID, serviceStopwatch.Elapsed, "End of '{0}' task's execution", "GetData"); 


      var dbCallStopwatch = Stopwatch.StartNew(); 

      Logger.Write(LogEntry.Task, Server.SessionID, "Start of '{0}' db call", "GetObjects"); 

      var objects = repository.GetObjects(); 

      dbCallStopwatch.Stop(); 

      Logger.Write(LogEntry.Task, Server.SessionID, dbCallStopwatch.Elapsed, "End of '{0}' db call", "GetObjects"); 


      Logger.Write(LogEntry.Event, Server.SessionID, "End of '{0}' action call", "Index"); 

      return View(); 
     } 
    } 
} 

上記のコードでは、グループのすべてのエントリについて、サーバーのセッションID(自動生成)からキーの値を取得します。

Logger.Writeメソッドのシグネチャはこれらのようなものでなければなりません:

public void Write(LogEntryType logEntryType, string key, string message, params string[] args) 
{ 
    var item = new LogEntry 
    { 
     LogEntryType = (int?)logEntryType, 
     EntryDate = DateTime.Now, 
     Key = key, 
     Description = string.Format(message, args) 
    }; 

    // Code for save log entry to text file, database, send email if it's an error, etc. 
} 

public void Write(LogEntryType logEntryType, string key, TimeSpan elapsedTime, string message, params string[] args) 
{ 
    var item = new LogEntry 
    { 
     LogEntryType = (int?)logEntryType, 
     EntryDate = DateTime.Now, 
     ElapsedTime = elapsedTime, 
     Key = key, 
     Description = string.Format(message, args) 
    }; 

    // Code for save log entry to text file, database, send email if it's an error, etc. 
} 

通常、実際のビジネスアプリケーションでは、我々は実行メトリックおよび他の詰め込むためのワークフロー定義を持っている必要がありますが、現時点では私はしないでくださいこの機能をどれだけ複雑に開発したいのか分かります。

必要なポイントにすべてのロガー呼び出しを追加し、それらをすべてデータベース(sqlまたはnosql)に保存すると、次に1つのセッションIDイベントに関するすべての情報が抽出されます。

あなたが上見ることができるように、いくつかのログ・エントリ・タイプ定義があります:警告およびエラーは、あなたがそれをログに記録することができます例外がある場合は、catchブロックの内部で、エラー処理のためのtry-catchブロックを追加することとします

Logger.Write(LogEntry.Error, Server.SessionID, "There was an error on '{0}' task. Details: '{1}'", "Index", ex.Message); 

さらに、非同期操作を実装して、要求に対するサーバーブロックを回避する方がよいでしょう。

この回答がコンセプトを改善できると思われる場合は、これがどのように問題を解決できるかという基本的な考え方です。

関連する問題