2016-10-01 4 views
0

메서드 실행 시간 기록과 관련하여 다른 게시물이 많이 있습니다 (예 : postsharp ~ action filters 통해 또는 사용자 지정 메서드 특성을 통해).C# MVC 로깅 메서드 실행 및 성능

따라서 메소드 완료 시간을 기록하는 것은이 시점에서 비교적 간단합니다.

그러나 내가 바라는 것은 예를 들어 주어진 요청에 대해 발생한 모든 작업을 추적하기 위해 세션 ID를 사용하여 요청별로 더 세분화 된 성능 메트릭을 얻는 것입니다. 그들 모두는 부모 (즉, 액션 컨트롤러) 메소드가 아닙니다.

예를 들어, 내가 좋아하는 뭔가를 할 수 있도록하고 싶습니다 : 함께

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 
    } 
} 

가 이상적으로 이러한 작업 (부모 방법, 서비스 호출과 DB 호출)을 모두 연결할을 - 가장 가능성있는 후보는 세션 ID를 통해 이루어 지지만 각 호출이 세션 ID에 액세스해야한다는 의미입니다.

내가 읽은 바로는이 작업을 수행하는 가장 좋은 방법은 상위 성능 시간을 기록하는 메소드 속성을 활용 한 다음 호출의 다양한 타이밍을 저장하는 일종의 맞춤 라이브러리 함수 (아마도 기록 할 nlog).

위 질문을 수행하는 데 가장 좋은 방법이 무엇인지에 대한 의견이 있습니까?

존재하는 제 3 자 라이브러리에 누락 된 항목이 있습니까? 즉, 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)에 저장하면 다음에 하나의 세션 ID 이벤트에 대한 모든 정보가 추출됩니다. 위에서 볼 수 있듯이

, 일부 로그 항목 유형 정의가 있습니다 : 경고 및 오류, 당신이 그것을 기록 할 수 있습니다 예외가있을 경우 내부 catch 블록의 오류 처리를 위해 시도-catch 블록을 추가하는 것이 가정 :

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

추가 포인트로 비동기 작업을 구현하여 서버가 요청을 차단하지 않도록하는 것이 좋습니다.

이 대답이 개념을 개선 할 수있는 것이라면이 문제를 어떻게 해결할 수 있는지에 대한 기본적인 아이디어입니다.