Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在包装NLog时保留呼叫站点信息_C#_Logging_Nlog - Fatal编程技术网

C# 如何在包装NLog时保留呼叫站点信息

C# 如何在包装NLog时保留呼叫站点信息,c#,logging,nlog,C#,Logging,Nlog,我有一个类包装NLog(称为NLOGER)。我的日志保存到我的数据库中。 我遇到的问题是如何显示日志记录发生的位置。 我有这个 <parameter name="@Logger" layout="${callsite}"/> 问题是您的包装器包装不正确。以下是如何正确包装NLog的示例,直接取自: 内部字符串GetCallingMethodName() { 字符串结果=“未知”; StackTrace trace=新的StackTrace(假); 对于(int i=0;i1)

我有一个类包装NLog(称为NLOGER)。我的日志保存到我的数据库中。 我遇到的问题是如何显示日志记录发生的位置。 我有这个

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

问题是您的包装器包装不正确。以下是如何正确包装NLog的示例,直接取自:

内部字符串GetCallingMethodName()
{
字符串结果=“未知”;
StackTrace trace=新的StackTrace(假);
对于(int i=0;i
资料来源:


我使用上面发布的代码简单地提取调用方法名,并将其作为“message”参数的一部分传递给布局。这使我可以将调用日志包装器的原始方法名写入日志文件(而不是日志包装器的类名)。

我一直在解决这个问题

真正重要的是日志文件中的调用站点(FullyQualified命名空间)

首先,我尝试从Stacktrace中获取正确的记录器:

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static NLog.Logger GetLogger()
    {
        var stackTrace = new StackTrace(false);
        StackFrame[] frames = stackTrace.GetFrames();
        if (null == frames) throw new ArgumentException("Stack frame array is null.");
        StackFrame stackFrame;
        switch (frames.Length)
        {
            case 0:
                throw new ArgumentException("Length of stack frames is 0.");
            case 1:
            case 2:
                stackFrame = frames[frames.Length - 1];
                break;
            default:
                stackFrame = stackTrace.GetFrame(2);
                break;
        }

        Type declaringType = stackFrame.GetMethod()
                                       .DeclaringType;

        return declaringType == null ? LogManager.GetCurrentClassLogger() :                 LogManager.GetLogger(declaringType.FullName);
    }
但遗憾的是,带有MEF的Stacktrace非常长,我无法清楚地为ILogger的请求者识别正确的调用方

因此,我没有通过构造函数注入注入ILogger接口,而是创建了一个ILogFactory接口,它可以通过构造函数注入注入,然后调用工厂上的Create方法

    public interface ILogFactory
    {
        #region Public Methods and Operators

        /// <summary>
        ///     Creates a logger with the Callsite of the given Type
        /// </summary>
        /// <example>
        ///     factory.Create(GetType());
        /// </example>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        ILogger Create(Type type);

        #endregion
    }
使用ILogger:

    public interface ILogger
    {
        #region Public Properties

        bool IsDebugEnabled { get; }

        bool IsErrorEnabled { get; }

        bool IsFatalEnabled { get; }

        bool IsInfoEnabled { get; }

        bool IsTraceEnabled { get; }

        bool IsWarnEnabled { get; }

        #endregion

        #region Public Methods and Operators

        void Debug(Exception exception);
        void Debug(string format, params object[] args);
        void Debug(Exception exception, string format, params object[] args);
        void Error(Exception exception);
        void Error(string format, params object[] args);
        void Error(Exception exception, string format, params object[] args);
        void Fatal(Exception exception);
        void Fatal(string format, params object[] args);
        void Fatal(Exception exception, string format, params object[] args);
        void Info(Exception exception);
        void Info(string format, params object[] args);
        void Info(Exception exception, string format, params object[] args);
        void Trace(Exception exception);
        void Trace(string format, params object[] args);
        void Trace(Exception exception, string format, params object[] args);
        void Warn(Exception exception);
        void Warn(string format, params object[] args);
        void Warn(Exception exception, string format, params object[] args);

        #endregion
    }
和执行:

    using System;

      using NLog;
      using NLog.Config;

      /// <summary>
      ///     The logging service.
      /// </summary>
      public class Logger : NLog.Logger, ILogger
      {
          #region Fields

          private string _loggerName;

          #endregion

          #region Public Methods and Operators

          /// <summary>
          ///     The get logging service.
          /// </summary>
          /// <returns>
          ///     The <see cref="ILogger" />.
          /// </returns>
          public ILogger CreateLogger(Type type)
          {
              if (type == null) throw new ArgumentNullException("type");               

              _loggerName = type.FullName;

              var logger = (ILogger)LogManager.GetLogger(_loggerName, typeof(Logger));

              return logger;
          }

希望这有助于跳过几帧,深入到App.config或著名的修饰符程序中设置的包装调用程序上下文:

skipFrames=1

示例: 有关
${callsite:skipFrames=Integer}
对于
${callsite linenumber:skipFrames=Integer}

我建议您在包装器中使用此格式:

${callsite:fileName=true:includeSourcePath=false:skipFrames=1}
此设置的输出如下所示:

。。。{LicenseServer.LSCore.MainThreadFunction(LSCore.cs:220)}


或者,您可以避免NLog设置中的本机解决方案,并在包装器代码中检索文件|方法|行信息:

using System.Diagnostics;
...
static private string GetCallsite()
{
  StackFrame sf = new StackTrace(2/*Skip two frames - dive to the callers context*/, true/*Yes I want the file info !*/).GetFrame(0);
  return "{" + sf.GetFileName() + " | " + sf.GetMethod().Name + "-" + sf.GetFileLineNumber() + "} ";
}
然后您只需调用静态方法并在消息之前添加callsite:

LogManager.GetCurrentClassLogger().Trace(GetCallsite() + "My Trace Message.");
伙计们 经过几天的艰苦工作和搜索。最后,我只使用一个简单的类构建了Nlog包装器,它可以保留${callsite},并在创建Nlog包装器实例时获得正确的日志程序名称。我将把代码放在下面简单的注释中。如您所见,我使用Stacktrace获得正确的记录器名称。使用write和writewithex注册logevnet,以便保留callsite

  public  class NlogWrapper 
    {  
        private  readonly NLog.Logger _logger; //NLog logger

    /// <summary>
    /// This is the construtor, which get the correct logger name when instance created  
    /// </summary>

    public NlogWrapper()
        {
        StackTrace trace = new StackTrace();

        if (trace.FrameCount > 1)
        {
            _logger = LogManager.GetLogger(trace.GetFrame(1).GetMethod().ReflectedType.FullName);
        }
        else //This would go back to the stated problem
        {
            _logger = LogManager.GetCurrentClassLogger();
        }
    }
    /// <summary>
    /// These two method are used to retain the ${callsite} for all the Nlog method  
    /// </summary>
    /// <param name="level">LogLevel.</param>
    ///  <param name="format">Passed message.</param>
    ///  <param name="ex">Exception.</param>
    private void Write(LogLevel level, string format, params object[] args)
    {
        LogEventInfo le = new LogEventInfo(level, _logger.Name, null, format, args);
        _logger.Log(typeof(NlogWrapper), le);
    }
    private void WriteWithEx(LogLevel level, string format,Exception ex, params object[] args)
    {
        LogEventInfo le = new LogEventInfo(level, _logger.Name, null, format, args);
        le.Exception = ex;
        _logger.Log(typeof(NlogWrapper), le);
    }


    #region  Methods
    /// <summary>
    /// This method writes the Debug information to trace file
    /// </summary>
    /// <param name="message">The message.</param>
    public  void Debug(String message)
        {
            if (!_logger.IsDebugEnabled) return;

        Write(LogLevel.Debug, message);
    }  

    public  void Debug(string message, Exception exception, params object[] args)
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Debug, message, exception);
    }

    /// <summary>
    /// This method writes the Information to trace file
    /// </summary>
    /// <param name="message">The message.</param>
    public  void Info(String message)
        {
            if (!_logger.IsInfoEnabled) return;
        Write(LogLevel.Info, message);
    }

    public  void Info(string message, Exception exception, params object[] args) 
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Info, message, exception);
    }
    /// <summary>
    /// This method writes the Warning information to trace file
    /// </summary>
    /// <param name="message">The message.</param>
    public  void Warn(String message)
        {
            if (!_logger.IsWarnEnabled) return;
          Write(LogLevel.Warn, message); 
        }

    public  void Warn(string message, Exception exception, params object[] args)
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Warn, message, exception);
    }

    /// <summary>
    /// This method writes the Error Information to trace file
    /// </summary>
    /// <param name="error">The error.</param>
    /// <param name="exception">The exception.</param>
    //   public static void Error( string message)
    //  {
    //    if (!_logger.IsErrorEnabled) return;
    //  _logger.Error(message);
    //}

    public  void Error(String message) 
    {
        if (!_logger.IsWarnEnabled) return;
        //_logger.Warn(message);
        Write(LogLevel.Error, message);
    }
    public void Error(string message, Exception exception, params object[] args)
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Error, message, exception);
    }  


    /// <summary>
    /// This method writes the Fatal exception information to trace target
    /// </summary>
    /// <param name="message">The message.</param>
    public void Fatal(String message)
        {
            if (!_logger.IsFatalEnabled) return;
         Write(LogLevel.Fatal, message);
    }

    public void Fatal(string message, Exception exception, params object[] args)
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Fatal, message, exception);
    }

    /// <summary>
    /// This method writes the trace information to trace target
    /// </summary>
    /// <param name="message">The message.</param>
    /// 
    public  void Trace(string message, Exception exception, params object[] args)  
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Trace, message, exception);
    }
    public  void Trace(String message)
        {
            if (!_logger.IsTraceEnabled) return;
            Write(LogLevel.Trace, message);
    }

        #endregion

    }
public-class-NlogWrapper
{  
私有只读NLog.Logger u Logger;//NLog Logger
/// 
///这是construtor,它在创建实例时获得正确的记录器名称
/// 
公共说唱者()
{
StackTrace trace=新的StackTrace();
如果(trace.FrameCount>1)
{
_logger=LogManager.GetLogger(trace.GetFrame(1.GetMethod().ReflectedType.FullName);
}
否则//这将回到所述问题
{
_logger=LogManager.GetCurrentClassLogger();
}
}
/// 
///这两个方法用于为所有Nlog方法保留${callsite}
/// 
///日志级别。
///传递消息。
///例外。
私有void写入(日志级别、字符串格式、参数对象[]args)
{
LogEventInfo le=新的LogEventInfo(级别,_logger.Name,null,格式,args);
_logger.Log(类型(NlogWrapper),le);
}
私有void WriteWithEx(日志级别、字符串格式、异常ex、参数对象[]args)
{
LogEventInfo le=新的LogEventInfo(级别,_logger.Name,null,格式,args);
le.例外=例外;
_logger.Log(类型(NlogWrapper),le);
}
#区域方法
/// 
///此方法将调试信息写入跟踪文件
/// 
///信息。
公共void调试(字符串消息)
{
如果(!\u logger.IsDebugEnabled)返回;
写入(LogLevel.Debug,消息);
}  
公共void调试(字符串消息、异常、参数对象[]args)
{
如果(!\u logger.IsFatalEnabled)返回;
写入X(LogLevel.Debug、消息、异常);
}
/// 
///此方法将信息写入跟踪文件
/// 
///信息。
公共无效信息(字符串消息)
{
如果(!\u logger.isinfo已启用)返回;
写入(LogLevel.Info、消息);
}
公共无效信息(字符串消息、异常、参数对象[]args)
{
如果(!\u logger.IsFatalEnabled)返回;
写入X(LogLevel.Info、消息、异常);
}
/// 
///此方法将警告信息写入跟踪文件
/// 
///信息。
公共无效警告(字符串消息)
{
如果(!\u logger.iswarn已启用)返回;
写入(LogLevel.Warn、消息);
}
公共无效警告(字符串消息、异常、参数对象[]args)
{
如果(!\u logger.IsFatalEnabled)返回;
写入X(LogLevel.Warn、消息、异常);
}
/// 
///此方法将错误信息写入跟踪文件
/// 
///错误。
///例外。
//公共静态无效错误(字符串消息)
//  {
//如果(!\u logger.IsErrorEnabled)返回;
//_记录器错误(消息);
//}
公共无效错误(字符串消息)
{
如果(!\u logger.iswarn已启用)返回;
//_logger.Warn(消息);
写入(LogLevel.Error,消息);
}
公共空间
    using System;

      using NLog;
      using NLog.Config;

      /// <summary>
      ///     The logging service.
      /// </summary>
      public class Logger : NLog.Logger, ILogger
      {
          #region Fields

          private string _loggerName;

          #endregion

          #region Public Methods and Operators

          /// <summary>
          ///     The get logging service.
          /// </summary>
          /// <returns>
          ///     The <see cref="ILogger" />.
          /// </returns>
          public ILogger CreateLogger(Type type)
          {
              if (type == null) throw new ArgumentNullException("type");               

              _loggerName = type.FullName;

              var logger = (ILogger)LogManager.GetLogger(_loggerName, typeof(Logger));

              return logger;
          }
      [ImportingConstructor]
      public MyConstructor(          
        ILogFactory logFactory)
       {
        _logger = logFactory.Create(GetType());
        }
${callsite:fileName=true:includeSourcePath=false:skipFrames=1}
using System.Diagnostics;
...
static private string GetCallsite()
{
  StackFrame sf = new StackTrace(2/*Skip two frames - dive to the callers context*/, true/*Yes I want the file info !*/).GetFrame(0);
  return "{" + sf.GetFileName() + " | " + sf.GetMethod().Name + "-" + sf.GetFileLineNumber() + "} ";
}
LogManager.GetCurrentClassLogger().Trace(GetCallsite() + "My Trace Message.");
  public  class NlogWrapper 
    {  
        private  readonly NLog.Logger _logger; //NLog logger

    /// <summary>
    /// This is the construtor, which get the correct logger name when instance created  
    /// </summary>

    public NlogWrapper()
        {
        StackTrace trace = new StackTrace();

        if (trace.FrameCount > 1)
        {
            _logger = LogManager.GetLogger(trace.GetFrame(1).GetMethod().ReflectedType.FullName);
        }
        else //This would go back to the stated problem
        {
            _logger = LogManager.GetCurrentClassLogger();
        }
    }
    /// <summary>
    /// These two method are used to retain the ${callsite} for all the Nlog method  
    /// </summary>
    /// <param name="level">LogLevel.</param>
    ///  <param name="format">Passed message.</param>
    ///  <param name="ex">Exception.</param>
    private void Write(LogLevel level, string format, params object[] args)
    {
        LogEventInfo le = new LogEventInfo(level, _logger.Name, null, format, args);
        _logger.Log(typeof(NlogWrapper), le);
    }
    private void WriteWithEx(LogLevel level, string format,Exception ex, params object[] args)
    {
        LogEventInfo le = new LogEventInfo(level, _logger.Name, null, format, args);
        le.Exception = ex;
        _logger.Log(typeof(NlogWrapper), le);
    }


    #region  Methods
    /// <summary>
    /// This method writes the Debug information to trace file
    /// </summary>
    /// <param name="message">The message.</param>
    public  void Debug(String message)
        {
            if (!_logger.IsDebugEnabled) return;

        Write(LogLevel.Debug, message);
    }  

    public  void Debug(string message, Exception exception, params object[] args)
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Debug, message, exception);
    }

    /// <summary>
    /// This method writes the Information to trace file
    /// </summary>
    /// <param name="message">The message.</param>
    public  void Info(String message)
        {
            if (!_logger.IsInfoEnabled) return;
        Write(LogLevel.Info, message);
    }

    public  void Info(string message, Exception exception, params object[] args) 
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Info, message, exception);
    }
    /// <summary>
    /// This method writes the Warning information to trace file
    /// </summary>
    /// <param name="message">The message.</param>
    public  void Warn(String message)
        {
            if (!_logger.IsWarnEnabled) return;
          Write(LogLevel.Warn, message); 
        }

    public  void Warn(string message, Exception exception, params object[] args)
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Warn, message, exception);
    }

    /// <summary>
    /// This method writes the Error Information to trace file
    /// </summary>
    /// <param name="error">The error.</param>
    /// <param name="exception">The exception.</param>
    //   public static void Error( string message)
    //  {
    //    if (!_logger.IsErrorEnabled) return;
    //  _logger.Error(message);
    //}

    public  void Error(String message) 
    {
        if (!_logger.IsWarnEnabled) return;
        //_logger.Warn(message);
        Write(LogLevel.Error, message);
    }
    public void Error(string message, Exception exception, params object[] args)
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Error, message, exception);
    }  


    /// <summary>
    /// This method writes the Fatal exception information to trace target
    /// </summary>
    /// <param name="message">The message.</param>
    public void Fatal(String message)
        {
            if (!_logger.IsFatalEnabled) return;
         Write(LogLevel.Fatal, message);
    }

    public void Fatal(string message, Exception exception, params object[] args)
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Fatal, message, exception);
    }

    /// <summary>
    /// This method writes the trace information to trace target
    /// </summary>
    /// <param name="message">The message.</param>
    /// 
    public  void Trace(string message, Exception exception, params object[] args)  
    {
        if (!_logger.IsFatalEnabled) return;
        WriteWithEx(LogLevel.Trace, message, exception);
    }
    public  void Trace(String message)
        {
            if (!_logger.IsTraceEnabled) return;
            Write(LogLevel.Trace, message);
    }

        #endregion

    }
void Log(LogSeverity severity, string message, [CallerFilePath] string fileName = null, [CallerMemberName] string member = null, [CallerLineNumber] int? lineNumber = null);
LogManager.AddHiddenAssembly(yourAssembly);