.Net Core 应用程序中的 Log4Net:LoggingEvent 设置不正确(LocationInformation 属性设置为“?”)
Log4Net in .Net Core application: LoggingEvent not set properly (LocationInformation porperties are set to "?")
到目前为止,我们一直在针对 .NET 4.6.1 的项目中使用 log4net,这非常有效。几个月前,我们开始实施我们的第一个 .NET 核心项目。但是 log4net 似乎有这个框架的问题。我们已经编写了自己的附加程序,将所有日志事件推送到我们的日志系统。但是,在核心项目中,LoggingEvent
对象中缺少基本信息。
我已经建立了一个名为 Log4NetUnitTest
的最小测试项目来重复该行为。
csproj
文件:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
</Project>
单元测试 class 以编程方式配置记录器(我也测试了文件配置,结果相同):
[TestClass]
public class LoggingTests
{
[TestMethod]
public void Log()
{
var logger = LogManager.GetLogger(typeof(LoggingTests));
var appender = new MyAppender();
var loggerLogger = (log4net.Repository.Hierarchy.Logger)logger.Logger;
loggerLogger.Level = Level.All;
loggerLogger.AddAppender(appender);
loggerLogger.Hierarchy.Configured = true;
try
{
throw new Exception("Some exception");
}
catch (Exception e)
{
logger.Error("Some error text", e);
}
}
}
自定义附加程序(它只是将 JSON 格式的事件写入控制台):
public sealed class MyAppender : AppenderSkeleton
{
private static readonly JsonSerializerSettings _settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Formatting = Formatting.Indented
};
protected override void Append(LoggingEvent loggingEvent)
{
var loggingObject = new
{
ApplicationName = System.Reflection.Assembly.GetEntryAssembly()?.GetName().Name ?? System.Reflection.Assembly.GetExecutingAssembly().GetName().Name,
Method = loggingEvent.LocationInformation.MethodName,
Line = loggingEvent.LocationInformation.LineNumber,
Class = loggingEvent.LocationInformation.ClassName,
loggingEvent.LoggerName,
Environment.MachineName,
ExceptionMessage = loggingEvent.ExceptionObject?.Message,
Message = loggingEvent.MessageObject,
Level = loggingEvent.Level.Name
};
string serializedLog = JsonConvert.SerializeObject(loggingObject, _settings);
Console.WriteLine(serializedLog);
}
}
当您 运行 测试时,您将得到以下输出:
{
"ApplicationName": "testhost",
"Method": "?",
"Line": "?",
"Class": "?",
"LoggerName": "Log4NetUnitTest.LoggingTests",
"MachineName": "NBG-ITSD-138",
"ExceptionMessage": "Some exception",
"Message": "Some error text",
"Level": "ERROR"
}
所以Method
、Line
和Class
无法解析。还有一些其他属性(我们没有使用),如 Domain
、Identity
和 UserName
只是设置为 "NOT AVAILABLE"。当您将 TargetFramework
更改为 net461
时,所有属性都已正确设置:
{
"ApplicationName": "Log4NetUnitTest",
"Method": "Log",
"Line": "31",
"Class": "Log4NetUnitTest.LoggingTests",
"LoggerName": "Log4NetUnitTest.LoggingTests",
"MachineName": "NBG-ITSD-138",
"ExceptionMessage": "Some exception",
"Message": "Some error text",
"Level": "ERROR"
}
几年前有人有一个类似的problem(不是NET core),可以在Append()
方法的开头添加loggingEvent.Fix = FixFlags.All;
来解决。虽然对我不起作用:-(
我想我需要添加一些配置或额外的包,但我不知道哪里出了问题。非常感谢任何建议。
查看 LocationInfo.cs 的源代码,似乎很多功能都包含在 #if !(NETCF || NETSTANDARD1_3)
块中,这就是为什么在使用 .NET Core 时设置了 none .我认为此功能在 .NET Standard 1.3 中不可用。
Apache JIRA 中存在一个问题 LOG4NET-606,其中提到更高版本的 .NET Standard 添加了缺失的功能,如果将 log4Net 升级为更高的 .NET Standard 版本,则可以恢复这些值.对此问题进行投票和评论可能会有所帮助。
到目前为止,我们一直在针对 .NET 4.6.1 的项目中使用 log4net,这非常有效。几个月前,我们开始实施我们的第一个 .NET 核心项目。但是 log4net 似乎有这个框架的问题。我们已经编写了自己的附加程序,将所有日志事件推送到我们的日志系统。但是,在核心项目中,LoggingEvent
对象中缺少基本信息。
我已经建立了一个名为 Log4NetUnitTest
的最小测试项目来重复该行为。
csproj
文件:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
</Project>
单元测试 class 以编程方式配置记录器(我也测试了文件配置,结果相同):
[TestClass]
public class LoggingTests
{
[TestMethod]
public void Log()
{
var logger = LogManager.GetLogger(typeof(LoggingTests));
var appender = new MyAppender();
var loggerLogger = (log4net.Repository.Hierarchy.Logger)logger.Logger;
loggerLogger.Level = Level.All;
loggerLogger.AddAppender(appender);
loggerLogger.Hierarchy.Configured = true;
try
{
throw new Exception("Some exception");
}
catch (Exception e)
{
logger.Error("Some error text", e);
}
}
}
自定义附加程序(它只是将 JSON 格式的事件写入控制台):
public sealed class MyAppender : AppenderSkeleton
{
private static readonly JsonSerializerSettings _settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Formatting = Formatting.Indented
};
protected override void Append(LoggingEvent loggingEvent)
{
var loggingObject = new
{
ApplicationName = System.Reflection.Assembly.GetEntryAssembly()?.GetName().Name ?? System.Reflection.Assembly.GetExecutingAssembly().GetName().Name,
Method = loggingEvent.LocationInformation.MethodName,
Line = loggingEvent.LocationInformation.LineNumber,
Class = loggingEvent.LocationInformation.ClassName,
loggingEvent.LoggerName,
Environment.MachineName,
ExceptionMessage = loggingEvent.ExceptionObject?.Message,
Message = loggingEvent.MessageObject,
Level = loggingEvent.Level.Name
};
string serializedLog = JsonConvert.SerializeObject(loggingObject, _settings);
Console.WriteLine(serializedLog);
}
}
当您 运行 测试时,您将得到以下输出:
{
"ApplicationName": "testhost",
"Method": "?",
"Line": "?",
"Class": "?",
"LoggerName": "Log4NetUnitTest.LoggingTests",
"MachineName": "NBG-ITSD-138",
"ExceptionMessage": "Some exception",
"Message": "Some error text",
"Level": "ERROR"
}
所以Method
、Line
和Class
无法解析。还有一些其他属性(我们没有使用),如 Domain
、Identity
和 UserName
只是设置为 "NOT AVAILABLE"。当您将 TargetFramework
更改为 net461
时,所有属性都已正确设置:
{
"ApplicationName": "Log4NetUnitTest",
"Method": "Log",
"Line": "31",
"Class": "Log4NetUnitTest.LoggingTests",
"LoggerName": "Log4NetUnitTest.LoggingTests",
"MachineName": "NBG-ITSD-138",
"ExceptionMessage": "Some exception",
"Message": "Some error text",
"Level": "ERROR"
}
几年前有人有一个类似的problem(不是NET core),可以在Append()
方法的开头添加loggingEvent.Fix = FixFlags.All;
来解决。虽然对我不起作用:-(
我想我需要添加一些配置或额外的包,但我不知道哪里出了问题。非常感谢任何建议。
查看 LocationInfo.cs 的源代码,似乎很多功能都包含在 #if !(NETCF || NETSTANDARD1_3)
块中,这就是为什么在使用 .NET Core 时设置了 none .我认为此功能在 .NET Standard 1.3 中不可用。
Apache JIRA 中存在一个问题 LOG4NET-606,其中提到更高版本的 .NET Standard 添加了缺失的功能,如果将 log4Net 升级为更高的 .NET Standard 版本,则可以恢复这些值.对此问题进行投票和评论可能会有所帮助。