2016-10-01 2 views
0

Есть много других сообщений, касающихся записи времени выполнения метода (например, через postsharp, через action filters или через собственный атрибут метода).C# MVC Выполнение и выполнение протокола ведения журнала MVC

Таким образом, для записи времени для завершения метода относительно прямолинейно.

Однако я хочу, чтобы получить более мелкие показатели производительности для каждого запроса, используя, например, идентификатор сеанса для отслеживания всех операций, выполняемых для данного запроса, - и время истекает для все они, а не только родительский (т.е. контроллер действия).

Например, я хотел бы быть в состоянии сделать что-то вроде:

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

В идеале я хочу, чтобы связать все эти операции (родительский метод, вызова службы и вызов дб) вместе - скорее всего, кандидат будет через идентификатор сеанса, но это означает, что для каждого вызова потребуется доступ к идентификатору сеанса.

Из того, что я прочитал, лучшим способом добиться этого было бы использовать атрибут метода для записи родительского времени выполнения, а затем некоторую функцию пользовательской библиотеки для хранения различных сроков вызовов (возможно, используя nlog для записи).

То, что я прошу, - это мнения о том, какой лучший способ (если вообще возможно) выполнить вышеизложенное?

Я пропустил что-то с любыми имеющимися сторонними библиотеками - т. Е. Поддерживает ли Unity или Postsharp эту функциональность (или какую-то другую библиотеку)?

Можно ли связать все эти записи с помощью идентификатора сеанса? Например, я не вижу, как через postsharp (1) хранить вызовы отдельных методов INSIDE в действии 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(); 
     } 
    } 
} 

В приведенном выше коде мы берем значение ключа из идентификатора сеанса сервера (автоматически сгенерированного) для всех записей группы.

подпись методы 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 сеанса.

Как вы можете видеть выше, есть некоторые определения типа записи в журнале: предупреждение и ошибки, предположим, что вы добавляете примерки поймать блок для обработки ошибок, внутри улова блока, если есть исключение вы можете зарегистрировать ее:

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

В качестве дополнительного момента лучше реализовать асинхронные операции, чтобы избежать блокировки сервера для запросов.

Если этот ответ имеет смысл, мы можем улучшить концепции, это основная идея, как вы можете решить свою проблему.

Смежные вопросы