跟踪方法执行时间

Cat*_*lin 10 .net c# asp.net trace .net-trace

我试图在我的应用程序中"注入"自定义跟踪方法.

我希望尽可能优雅,不需要修改现有的大部分代码,并且可以轻松启用/禁用它.

我能想到的一个解决方案是创建一个自定义Attribute,我将它附加到我想要跟踪的方法.

基本理念:

public class MethodSnifferAttribute : Attribute
{
    private Stopwatch sw = null;

    public void BeforeExecution()
    {
        sw = new Stopwatch();
        sw.Start();
    }
    public void ExecutionEnd()
    {
        sw.Stop();
        LoggerManager.Logger.Log("Execution time: " + sw.ElapsedMilliseconds);
    }
}

public class MyClass
{
    [MethodSniffer]
    public void Function()
    {
        // do a long task
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有任何现有.NET属性为调用/结束方法提供回调?

Sri*_*vel 7

除非您手动调用属性的方法,否则不会调用该方法.有一些安全属性可以由CLR调用,但这超出了这个问题的主题,无论如何它都没有用.

有一些技术可以在不同的级别重写代码.源代码编织,IL编织等

您需要查看某些方法来修改IL并重写它以便执行计时.别担心,你不必写所有这些.人们已经做到了.例如,您可以使用PostSharp.

这是一篇提供示例的文章

[Serializable]
[DebuggerStepThrough]
[AttributeUsage(AttributeTargets.Method)]
public sealed class LogExecutionTimeAttribute : OnMethodInvocationAspect
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(LogExecutionTimeAttribute));

    // If no threshold is provided, then just log the execution time as debug
    public LogExecutionTimeAttribute() : this (int.MaxValue, true)
    {
    }
    // If a threshold is provided, then just flag warnning when threshold's exceeded
    public LogExecutionTimeAttribute(int threshold) : this (threshold, false)
    {
    }
    // Greediest constructor
    public LogExecutionTimeAttribute(int threshold, bool logDebug)
    {
        Threshold = threshold;
        LogDebug = logDebug;
    }

    public int Threshold { get; set; }
    public bool LogDebug { get; set; }

    // Record time spent executing the method
    public override void OnInvocation(MethodInvocationEventArgs eventArgs)
    {
        var sw = Stopwatch.StartNew();
        eventArgs.Proceed();
        sw.Stop();
        var timeSpent = sw.ElapsedMilliseconds;

        if (LogDebug)
        {
            Log.DebugFormat(
                "Method [{0}{1}] took [{2}] milliseconds to execute",
                eventArgs.Method.DeclaringType.Name,
                eventArgs.Method.Name,
                timeSpent);
        }

        if (timeSpent > Threshold)
        {
            Log.WarnFormat(
                "Method [{0}{1}] was expected to finish within [{2}] milliseconds, but took [{3}] instead!",
                eventArgs.Method.DeclaringType.Name,
                eventArgs.Method.Name,
                Threshold,
                timeSpent);
       }
}
Run Code Online (Sandbox Code Playgroud)

注意:我已经修改了文章中使用的示例StopWatch而不是DateTime因为DateTime不准确.

  • 使用`Stopwatch`代替`DateTime`做得好 (2认同)