如何包装NLOG时保留调用点信息 [英] How to retain callsite information when wrapping NLog

查看:166
本文介绍了如何包装NLOG时保留调用点信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个封装NLOG(称为NLogger)的类。我的日志保存到我的数据库。
我有一个问题,问题是如何显示记录发生在哪里。
我有这个

 <参数名称=@记录器布局=$ {}调用点/>

不过这正说明Cor​​e.Logging.Loggers.NLogLogger.Log哪个是哪个叫我的包装我NlogWrapper不是类。

这是我的包装方法

 公共无效日志(LOGTYPE为messageType,类型方面,字符串消息,异常除外)
        {
            NLog.Logger记录= NLog.LogManager.GetLogger(context.Name);
            LogLevel的LOGLEVEL = LogLevel.Info; //默认级别信息            开关(为messageType)
            {
                案例LogType.Debug:
                    LOGLEVEL = LogLevel.Debug;
                    打破;
                案例LogType.Info:
                    LOGLEVEL = LogLevel.Info;
                    打破;
                案例LogType.Warning:
                    LOGLEVEL = LogLevel.Warn;
                    打破;
                案例LogType.Error:
                    LOGLEVEL = LogLevel.Error;
                    打破;
                案例LogType.Fatal:
                    LOGLEVEL = LogLevel.Fatal;
                    打破;
                默认:
                    抛出(日志消息类型是不支持)新的ArgumentException;
            }            logger.Log(LOGLEVEL,消息除外);
        }


解决方案

的问题是,你的包装是不正确的包装。下面是如何正确地包装NLOG,直接从NLOG 的源代码树采取了一个例子:

 使用系统;
使用System.Text;
使用NLOG;命名空间LoggerWrapper
{
  ///<总结>
  ///提供方法来编写与事件ID消息 - 在事件日志中的目标是有用的。
  ///包装了一个Logger实例。
  ///< /总结>
  类MyLogger
  {
    私人记录仪_logger;    公共MyLogger(字符串名称)
    {
      _logger = LogManager.GetLogger(名);
    }    公共无效的WriteMessage(字符串EVENTID,字符串消息)
    {
      ///
      ///从传递信息创建日志事件
      ///
      LogEventInfo LOGEVENT =新LogEventInfo(LogLevel.Info,_logger.Name,消息);
      //
      //设置特定事件context参数
      //这种情况下参数可以使用$检索{事件背景:事件ID}
      //
      logEvent.Context [事件ID] = EVENTID;
      //
      //调用log()方法。通过typeof运算(MyLogger)作为重要的是
      //第一个参数。如果你不这样做,$ {}调用点和其他调用堆栈相关
      //布局渲染器将不能正常工作。
      //
      _logger.Log(typeof运算(MyLogger),LOGEVENT);
    }
  }
}

的关键是通过您的记录器的包装的类型的呼叫日志。当NLOG尝试查找调用点,这是不言而喻堆栈直到第一个调用的方法,其声明类型是不传递到日志呼叫的类型。这将是code,实际上是调用你的包装。

在你的情况,你会记录看起来是这样的:

 公共无效日志(LOGTYPE为messageType,类型方面,字符串消息,异常除外)
    {
        NLog.Logger记录= NLog.LogManager.GetLogger(context.Name);
        LogLevel的LOGLEVEL = LogLevel.Info; //默认级别信息        开关(为messageType)
        {
            案例LogType.Debug:
                LOGLEVEL = LogLevel.Debug;
                打破;
            案例LogType.Info:
                LOGLEVEL = LogLevel.Info;
                打破;
            案例LogType.Warning:
                LOGLEVEL = LogLevel.Warn;
                打破;
            案例LogType.Error:
                LOGLEVEL = LogLevel.Error;
                打破;
            案例LogType.Fatal:
                LOGLEVEL = LogLevel.Fatal;
                打破;
            默认:
                抛出(日志消息类型是不支持)新的ArgumentException;
        }        //
        //在这里建立的LogEvent ...
        //
        LogEventInfo LOGEVENT =新LogEventInfo(日志级别context.Name,消息);
        logEvent.Exception =除外;        //
        //这里通过你的包装类的类型...
        //
        logger.Log(typeof运算(YourWrapperClass),LOGEVENT);
    }

I have a class that wraps NLog (called NLogger). My logs are saved to my database. The thing I'm having a problem with is how do I show where the logging occured. I have this

<parameter name="@Logger" layout="${callsite}"/>  

but this just shows Core.Logging.Loggers.NLogLogger.Log which is my NlogWrapper not the class which calls my wrapper.

This is my wrapper method

        public void Log(LogType messageType, Type context, string message, Exception exception)
        {
            NLog.Logger logger = NLog.LogManager.GetLogger(context.Name);
            LogLevel logLevel = LogLevel.Info; // Default level to info

            switch (messageType)
            {
                case LogType.Debug:
                    logLevel = LogLevel.Debug;
                    break;
                case LogType.Info:
                    logLevel = LogLevel.Info;
                    break;
                case LogType.Warning:
                    logLevel = LogLevel.Warn;
                    break;
                case LogType.Error:
                    logLevel = LogLevel.Error;
                    break;
                case LogType.Fatal:
                    logLevel = LogLevel.Fatal;
                    break;
                default:
                    throw new ArgumentException("Log message type is not supported");                    
            }

            logger.Log(logLevel, message, exception);
        }

解决方案

The problem is that your wrapper is not wrapping correctly. Here is an example of how to wrap NLog correctly, taken directly from the source tree of NLog:

using System;
using System.Text;
using NLog;

namespace LoggerWrapper
{    
  /// <summary>    
  /// Provides methods to write messages with event IDs - useful for the Event Log target.    
  /// Wraps a Logger instance.    
  /// </summary>    
  class MyLogger    
  {        
    private Logger _logger;        

    public MyLogger(string name)        
    {            
      _logger = LogManager.GetLogger(name);        
    }        

    public void WriteMessage(string eventID, string message)           
    {            
      ///            
      /// create log event from the passed message            
      ///             
      LogEventInfo logEvent = new LogEventInfo(LogLevel.Info, _logger.Name, message);


      //
      // set event-specific context parameter            
      // this context parameter can be retrieved using ${event-context:EventID}            
      //            
      logEvent.Context["EventID"] = eventID;            
      //             
      // Call the Log() method. It is important to pass typeof(MyLogger) as the            
      // first parameter. If you don't, ${callsite} and other callstack-related             
      // layout renderers will not work properly.            
      //            
      _logger.Log(typeof(MyLogger), logEvent);        
    }    
  }
}

The key is passing the type of your logger wrapper to the call to Log. When NLog tries to find the callsite, it goes up the stack until the first calling method whose declaring type is NOT the type passed to the Log call. This will be the code that is actually calling your wrapper.

In your case, your logger would look something like this:

    public void Log(LogType messageType, Type context, string message, Exception exception)
    {
        NLog.Logger logger = NLog.LogManager.GetLogger(context.Name);
        LogLevel logLevel = LogLevel.Info; // Default level to info

        switch (messageType)
        {
            case LogType.Debug:
                logLevel = LogLevel.Debug;
                break;
            case LogType.Info:
                logLevel = LogLevel.Info;
                break;
            case LogType.Warning:
                logLevel = LogLevel.Warn;
                break;
            case LogType.Error:
                logLevel = LogLevel.Error;
                break;
            case LogType.Fatal:
                logLevel = LogLevel.Fatal;
                break;
            default:
                throw new ArgumentException("Log message type is not supported");                    
        }

        //
        // Build LogEvent here...
        //
        LogEventInfo logEvent = new LogEventInfo(logLevel, context.Name, message);
        logEvent.Exception = exception;

        //
        // Pass the type of your wrapper class here...
        //
        logger.Log(typeof(YourWrapperClass), logEvent);
    }

这篇关于如何包装NLOG时保留调用点信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆