log4net转换模式不适用于Asp.net Core

Are*_*eff 4 log4net asp.net-web-api asp.net-core .net-standard

我在Asp.Net Web API Core 2.0中使用log4net-core-preview(2.0.6),而我的log4net配置布局是

 <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-5p %d{hh:mm:ss} %logger [%M %line] %message%newline" />
 </layout>
Run Code Online (Sandbox Code Playgroud)

和在Startup.ConfigureServices

//log4net stuff goes here ...
var logRepo = LogManager.GetRepository(Assembly.GetEntryAssembly());
XmlConfigurator.Configure(logRepo, File.OpenRead("log4net.config"));
ILog log = LogManager.GetLogger(this.GetType());
log.Info("App is starting");
Run Code Online (Sandbox Code Playgroud)

但我不知道为什么我的日志看起来像这样

调试01:29:10 MyNameSpace.Controllers.XYZController [??],一些消息

谁能告诉我这是怎么回事

谢谢

Chi*_*hih 5

有点晚了,但最近才遇到这个问题,结果表明.NET Standard框架不支持某些模式。

根据Apache的文档,不支持以下功能:

  • ADO.NET附加程序
  • 与ASP.NET相关的任何内容(跟踪附加程序几个模式转换器
  • .NET远程处理
  • 彩色控制台附加程序
  • 事件日志追加器
  • NetSendAppender
  • SMTP附加程序
  • DOMConfigurator
  • 堆栈跟踪模式
  • 访问appSettings(既不是log4net部分本身,也不是使用AppSettingsPatternConverter)
  • 使用EnvironmentFolderPathPatternConverter访问“特殊路径”
  • 模拟Windows帐户

有两种解决方法:

  1. 在自定义日志包装程序中使用C#5.0的Caller Info属性,这里有一些很好的示例:
  2. 创建自定义PatternConverterStackTrace.NET标准2.0和以后需要)中示出,如下

StackTraceConverter.cs

namespace MyWebApp
{
    public class StackTraceConverter : PatternConverter
    {
        protected override void Convert(TextWriter writer, object state)
        {
            try
            {
                StackTrace st = new StackTrace(true);
                int idx = 1;
                while (st.GetFrame(idx).GetMethod().DeclaringType.Assembly == typeof(LogManager).Assembly)
                    idx++;
                //I have to create a new StackTrace object in order to get the line number.
                var targetSt = new StackTrace(st.GetFrame(idx));
                writer.Write($"{targetSt.GetFrame(0).GetMethod().DeclaringType.FullName}.{targetSt.GetFrame(0).GetMethod().Name}({targetSt.GetFrame(0).GetFileLineNumber()})");
            }
            catch (Exception)
            {
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

StackTracePatternLayout.cs

namespace MyWebApp
{
    public class StackTracePatternLayout : PatternLayout
    {
        public StackTracePatternLayout()
        {
            AddConverter(new ConverterInfo
            {
                Name = "stack_trace", //your pattern name here
                Type = typeof(StackTraceConverter)
            }
        );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

log4net.config

<appender name="RollingFileAppenderCustomPattern" type="log4net.Appender.RollingFileAppender">
    ...
    <layout type="MyWebApp.StackTracePatternLayout, MyWebApp">
        <conversionPattern value="%-5p %date{yyyy/MM/dd HH:mm:ss} [tread-%t] %stack_trace - %m%n" />
    </layout>
    ...
</appender>
<root>
    <level value="ALL" />
    <appender-ref ref="RollingFileAppenderCustomPattern" />
</root>
Run Code Online (Sandbox Code Playgroud)

然后照常登录

public class HomeController : Controller
{
    ...
    public IActionResult LogForNetTest()
    {
        if (Logger.IsDebugEnabled)
            Logger.Debug($"Log4Net is ready to log!");
        ...
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

结果是这样的

DEBUG 2018/07/02 15:30:59 [tread-9] MyWebApp.Controllers.HomeController.LogForNetTest(46) - Log4Net is ready to log!
Run Code Online (Sandbox Code Playgroud)

尚未完全测试,但是到目前为止这两种方法都可以正常工作,尽管它们之间存在一些差异:

希望这会有所帮助。

蒂米