2013-09-05 30 views
1

我正在使用OnMethodBoundryAspect創建簡單的日誌記錄和執行時間方面。我想爲每種方法創建一個記錄器。但是,如果Logger未聲明爲靜態成員,則不起作用。如果聲明爲靜態,則不可能爲每個方法創建一個記錄器。PostSharp和Common.Logging Logger聲明

這裏是我的方面:

[Serializable] 
public class MonitorAttribute : OnMethodBoundaryAspect 
{ 
    [NonSerialized] 
    private Stopwatch _stopwatch; 

    private string _methodName; 
    private ILog _log; 

    public MonitorAttribute() 
    { 
    } 

    /// <summary> 
    /// overrides the method name in the logs 
    /// </summary> 
    /// <param name="method"></param> 
    public MonitorAttribute(string method) 
    { 
     _methodName = method; 
    } 

    #region Overrides 

    public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) 
    { 
     if (string.IsNullOrEmpty(_methodName)) 
      _methodName = method.Name; 

     _log = LogManager.GetLogger(_methodName); 
    } 

    public override void OnEntry(MethodExecutionArgs args) 
    { 
     _stopwatch = Stopwatch.StartNew(); 
     _log.InfoFormat("Method {0} called", _methodName); 
    } 

    public override void OnExit(MethodExecutionArgs args) 
    { 
     _stopwatch.Stop(); 
     _log.InfoFormat("Method {0} exited successfully. execution time {1} milliseconds", _methodName, _stopwatch.ElapsedMilliseconds); 
    } 

    public override void OnSuccess(MethodExecutionArgs args) 
    { 
     _stopwatch.Stop(); 
     _log.InfoFormat("Method {0} executed successfully. execution time {1} milliseconds", _methodName, _stopwatch.ElapsedMilliseconds); 
    } 

    #endregion 
} 

回答

2

正確的地方初始化記錄器_log的實例將是RuntimeInitialize方法。在您當前的示例中,僅在編譯期間創建記錄器。

我也建議初始化_stopwatch的每個OnEntry的新實例不是線程安全的,可能會導致不正確的結果。

您可以使用靜態秒錶和MethodExecutionArgs.MethodExecutionTag屬性將當前時間存儲在OnEntry中。此後,此值將傳遞給您的OnSuccessOnExit方法。

所以修改後的例子可能是這樣的:

[Serializable] 
public class MonitorAttribute : OnMethodBoundaryAspect 
{ 
    private static Stopwatch _stopwatch = Stopwatch.StartNew(); 

    [NonSerialized] private ILog _log; 

    private string _methodName; 

    public MonitorAttribute() 
    { 
    } 

    /// <summary> 
    /// overrides the method name in the logs 
    /// </summary> 
    /// <param name="method"></param> 
    public MonitorAttribute(string method) 
    { 
     _methodName = method; 
    } 

    #region Overrides 

    public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) 
    { 
     if (string.IsNullOrEmpty(_methodName)) 
      _methodName = method.Name; 
    } 

    public override void RuntimeInitialize(MethodBase method) 
    { 
     _log = LogManager.GetLogger(_methodName); 
    } 

    public override void OnEntry(MethodExecutionArgs args) 
    { 
     _log.InfoFormat("Method {0} called", _methodName); 
     args.MethodExecutionTag = _stopwatch.ElapsedMilliseconds; 
    } 

    public override void OnExit(MethodExecutionArgs args) 
    { 
     long stopwatchStart = (long) args.MethodExecutionTag; 
     _log.InfoFormat("Method {0} exited successfully. execution time {1} milliseconds", _methodName, 
      _stopwatch.ElapsedMilliseconds - stopwatchStart); 
    } 

    public override void OnSuccess(MethodExecutionArgs args) 
    { 
     long stopwatchStart = (long) args.MethodExecutionTag; 
     _log.InfoFormat("Method {0} executed successfully. execution time {1} milliseconds", _methodName, 
      _stopwatch.ElapsedMilliseconds - stopwatchStart); 
    } 

    #endregion 
} 
+0

感謝全面的回答!但是,您的StopWatch方法會產生不正確的時間。我有一個方法,其中我使用Thread.Sleep(2000),但秒錶返回1991.使用我的代碼,它返回2001. –

+0

這是一個奇怪的行爲,在我的測試中,我通常會得到2001-2002毫秒結果與相同的代碼。或者,您也可以嘗試將秒錶實例存儲在標籤中:'args.MethodExecutionTag = Stopwatch.StartNew()'。 – AlexD