如何在Log4Net中记录已用时间

时间:2016-02-22 09:26:12

标签: c# .net logging log4net

我想记录API的已用时间。我在这里看到两种不同的方法:

  1. 使用stopwatch。在输入API后立即创建一个新的秒表,然后在退出之前调用stop()(在日志本身上打印已用时间)。

  2. 制作两个日志打印输出,一个在输入API之后,另一个在退出之前。经过的时间将被"存储"作为两个日志时间戳之间的时差。

  3. 您认为哪种方法最好?

    第一个似乎很好,但我需要到处创建一个新的秒表。第二个是更清洁,但在回读日志时必须完成一些数学计算

2 个答案:

答案 0 :(得分:12)

我选择第一个选项。创建Stopwatch非常便宜。使用一个好的包装器,每个API方法中所需的代码可以简单如下:

public int MyApiMethod()
{
    using (new ExecutionTimeLogger())
    {
        // All API functionality goes inside this using block.
        var theResultValue = 23;
        return theResultValue;
    }
}

班级ExecutionTimeLogger看起来像这样:

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using log4net;

public class ExecutionTimeLogger : IDisposable
{
    private readonly ILog log = LogManager.GetLogger("ExecutionTimes");
    private readonly string methodName;
    private readonly Stopwatch stopwatch;

    public ExecutionTimeLogger([CallerMemberName] string methodName = "")
    {
        this.methodName = methodName;
        stopwatch = Stopwatch.StartNew();
    }

    public void Dispose()
    {
        log.Debug(methodName + "() took " + stopwatch.ElapsedMilliseconds + " ms.");
        GC.SuppressFinalize(this);
    }
}

根据您的记录器实现,输出可能如下所示:

  

15:04:23.4477 |调试|执行时间| MyApiMethod()用了42毫秒。

请注意,当API方法在using内部引发异常时,也会生成日志输出,因为ExecutionTimeLogger实例将被处理掉。

methodName参数将由编译器自动填充,因为它具有[CallerMemberName] attribute。每次创建ExecutionTimeLogger时,都需要传递它。

GC.SuppressFinalize(this)告诉垃圾收集器调用ExecutionTimeLogger实例的终结器并不需要调度,因为我们知道它从未创建过非托管资源。

如果您使用Unity作为DI框架,您还可以编写一个UnityContainerExtension,它包含具有特定自定义属性的每个方法(例如,例如LogExecutionTimeAttribute),并包含所需的度量和日志记录代码。但这要复杂得多。

答案 1 :(得分:1)

我更喜欢第一种方法(使用stopwatch) 如果您的方法被称为同步,则不必为每个API调用创建新的Stopwatch对象。您可以定义Stopwatch的全局实例,并在致电Stop()后致电Reset() ,或Restart()从头开始计算。