【问题标题】:Log method entry and exit in .NET using NLog使用 NLog 在 .NET 中记录方法进入和退出
【发布时间】:2016-07-12 10:09:01
【问题描述】:

我想使用 NLog 记录方法的进入和退出。我找到了两种方法。 第一个,使用PostSharp,但需要购买。 第二种方法,使用unity,但是我们只能在有接口的方法上实现。

例如, 我有一个控制器,名为SampleController

SampleController.cs

 public string Get()
        {
            BusinessLayerClass businessLayer = new BusinessLayerClass();
            return businessLayer.BusinessLayerMethod();
        }

BusinessLayerClass.cs

public class BusinessLayerClass
    {
        public string BusinessLayerMethod()
        {
            DataLayerClass dataLayerClass = new DataLayerClass();
           return  dataLayerClass.DataLayerMethod();
        }
    }

DataLayerClass.cs

public class DataLayerClass
    {
        public string DataLayerMethod()
        {
            return "Hi";
        }
    }

我在示例控制器中有两个类BusinessLayerClassDataLayerClass.Get 方法在BusinessLayerClass 中调用BusinessLayerMethod,并从中调用DataLayerMethod。 我有一个 NLogging 类用于记录目的

NLogging.cs

public static class NLogging
    {
        public static bool Enabled
        {
            get { return LogManager.IsLoggingEnabled(); }
            set
            {
                if (value)
                {
                    while (!Enabled) LogManager.EnableLogging();
                }
                else
                {
                    while (Enabled) LogManager.DisableLogging();
                }
            }
        }

        public static void Fatal(string message, Exception exception = null, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Fatal, message, exception, callerPath, callerMember, callerLine);
        }
        public static void Trace(string message, Exception exception = null, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Trace, message, exception, callerPath, callerMember, callerLine);
        }

        public static void Debug(string message, Exception exception = null, [CallerFilePathAttribute] string callerPath = "", [CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Debug, message, exception, callerPath, callerMember, callerLine);
        }

        public static void Info(string message, Exception exception = null, [CallerFilePathAttribute] string callerPath = "", [CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Info, message, exception, callerPath, callerMember, callerLine);
        }

        public static void Warn(string message, Exception exception = null, [CallerFilePathAttribute] string callerPath = "", [CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Warn, message, exception, callerPath, callerMember, callerLine);
        }

        public static void Error(string message, Exception exception = null, [CallerFilePathAttribute] string callerPath = "", [CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLine = 0)
        {
            Log(LogLevel.Error, message, exception, callerPath, callerMember, callerLine);
        }

        private static void Log(LogLevel level, string message, Exception exception = null, string callerPath = "", string callerMember = "", int callerLine = 0)
        {
            LogManager.ThrowExceptions = true;
            var logger = LogManager.GetLogger(callerPath);

            if (!logger.IsEnabled(level)) return;

            var logEvent = new LogEventInfo(level, callerPath, message) { Exception = exception };
            logEvent.Properties.Add("callerpath", callerPath);
            logEvent.Properties.Add("callermember", callerMember);
            logEvent.Properties.Add("callerline", callerLine);

            logger.Log(logEvent);
        }
    }

我不能在这里使用 Unity,因为 BusinessLayerClassDataLayerClass 不实现接口。

在每种方法中调用NLogging.Trace(methodname) 会很不方便。例如,如果我更改了我的方法名称,我还需要更改日志记录代码,例如 NLogging.Trace("Entered into ModifiedBusinessLayerMethod")

有没有其他方法可以在不使用这两种方法的情况下记录方法的进入和退出?

【问题讨论】:

  • 使用 C# 6,您可以执行 NLogging.trace(nameof(BusinessLayerMethod)) 以避免方法名称更改时出现问题。
  • 感谢您的回复。这是一个很好的答案。但是如果我在项目中添加10个类并且这些类有很多方法。此时,无法添加NLogging.trace( nameof(MathodName)) 在所有这些方法中。还有其他方法吗?我的意思是我想要一个全局日志记录方法,它将在实际方法执行之前执行。
  • 我不知道有什么好方法可以做你想做的事。 here 之前讨论过非常相似的问题。我会去或与 IoC 或大量的痕迹。
  • 谢谢,我认为这会有所帮助。

标签: c# asp.net nlog


【解决方案1】:

您可以使用 FodyMethodDecorator.Fody 加载项。 Fody 是一个免费的开源代码编织库。

如何设置:

1。安装包

PM> Install-Package MethodDecorator.Fody

2。装饰方法

public class BusinessLayerClass
    {
        [LogMethod] 
        public string BusinessLayerMethod()
        {
            DataLayerClass dataLayerClass = new DataLayerClass();
           return  dataLayerClass.DataLayerMethod();
        }
    }

3。编写拦截器

 using System;
 using System.Reflection;

[module: LogMethod] // Atribute should be "registered" by adding as module or assembly custom attribute

// Any attribute which provides OnEntry/OnExit/OnException with proper args
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Assembly | AttributeTargets.Module)]
public class LogMethodAttribute : Attribute, IMethodDecorator
{
    private MethodBase _method;
    // instance, method and args can be captured here and stored in attribute instance fields
    // for future usage in OnEntry/OnExit/OnException
    public void Init(object instance, MethodBase method, object[] args)
    {
        _method = method;
    }
    public void OnEntry()
    {
        NLogging.Trace("Entering into {0}", _method.Name);
    }

    public void OnExit()
    {
        NLogging.Trace("Exiting into {0}", _method.Name);
    }

    public void OnException(Exception exception)
    {
        NLogging.Trace(exception, "Exception {0}", _method.Name);
    }
}

【讨论】:

  • 遗憾的是,这个 nuget 包不再更新/支持。
  • @WahidBitar 2新版本已经上传,最新版本为1.0.2
【解决方案2】:

为 Fody 使用示踪剂

它是高度可配置的,并且可以立即为您提供结果,而无需强迫您修饰代码。您可以自动记录每个方法调用或通过显式包含和排除特定类和方法来进行细粒度控制。

https://github.com/csnemes/tracer

在大多数情况下,与 Tracer 提供的优雅相比,其他建议的答案过于复杂和耗时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    • 2013-04-05
    相关资源
    最近更新 更多