有没有办法在 .net 核心 ILogger 接口中记录异常数据字典中的值?
Is there a way to log the values from the Data dictionary of an exception in .net core ILogger interface?
如果我记录一个异常,其中一些 key/value 对添加到数据,这些值不会被记录。在某些情况下,它们对于问题的诊断确实很有帮助,但我看不到任何配置方法。
例如,以下控制台应用程序:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.2" />
</ItemGroup>
</Project>
class Program
{
static void Main(string[] args)
{
var exception = new Exception("Oops!");
exception.Data.Add("useful-data-key", "useful-data-value");
ILogger<Program> logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<Program>();
logger.LogError(exception, "An error occurred in the console.");
Console.WriteLine("Logged");
Console.Read();
}
}
结果被记录到控制台:
fail: Console.Program[0]
An error occurred in the console.
System.Exception: Oops!
数据字典中没有值的迹象。
如果我在 ASP.NET 核心应用程序中登录 Azure Application Insight,情况也是如此。
有什么方法可以让我在日志中输出该数据?
If I log an exception with some key/value pairs added to Data, those values do not get logged.
Is there any way I can get that data to output in the logs?
在source code of ConsoleLogger
中,我们可以发现它并没有从Exception.Data
属性中提取用户定义的key/value对并将它们显示为输出。
为达到您的要求,您可以尝试实施和使用自定义控制台记录器,如下所示。
MyCustomConsoleLoggerProvider class
public class MyCustomConsoleLoggerProvider : ILoggerProvider
{
public void Dispose()
{
}
public ILogger CreateLogger(string categoryName)
=> new CustomConsoleLogger(categoryName);
}
CustomConsoleLogger class
internal class CustomConsoleLogger : ILogger
{
private readonly string _categoryName;
public CustomConsoleLogger(string categoryName)
=> _categoryName = categoryName;
public void Log<TState>(
LogLevel logLevel, EventId eventId, TState state, Exception exception,
Func<TState, Exception, string> formatter
)
{
if (!IsEnabled(logLevel))
{
return;
}
StringBuilder logBuilder = new StringBuilder();
logBuilder.Append($"{logLevel} {_categoryName}: {state}{(exception != null ? "\n" : string.Empty)}{exception}\n");
if (exception.Data != null)
{
logBuilder.Append("Exception Data: ");
exception.Data.Cast<DictionaryEntry>().ToList().ForEach((item) =>
{
string key = item.Key.ToString();
string vl = item.Value.ToString();
logBuilder.Append($"{key}:{vl}\n");
});
}
Console.WriteLine(logBuilder.ToString());
}
public bool IsEnabled(LogLevel logLevel)
=> true;
public IDisposable BeginScope<TState>(TState state)
=> null;
}
在控制台应用程序中
class Program
{
static void Main(string[] args)
{
var exception = new Exception("Oops!");
exception.Data.Add("useful-data-key1", "useful-data-value1");
exception.Data.Add("useful-data-key2", "useful-data-value2");
ILogger<Program> logger = LoggerFactory.Create(builder =>
{
//builder.AddConsole();
builder.AddProvider(new MyCustomConsoleLoggerProvider());
}).CreateLogger<Program>();
logger.LogError(exception, "An error occurred in the console.");
Console.WriteLine("Logged");
Console.Read();
}
}
测试结果
如果我记录一个异常,其中一些 key/value 对添加到数据,这些值不会被记录。在某些情况下,它们对于问题的诊断确实很有帮助,但我看不到任何配置方法。
例如,以下控制台应用程序:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.2" />
</ItemGroup>
</Project>
class Program
{
static void Main(string[] args)
{
var exception = new Exception("Oops!");
exception.Data.Add("useful-data-key", "useful-data-value");
ILogger<Program> logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<Program>();
logger.LogError(exception, "An error occurred in the console.");
Console.WriteLine("Logged");
Console.Read();
}
}
结果被记录到控制台:
fail: Console.Program[0]
An error occurred in the console.
System.Exception: Oops!
数据字典中没有值的迹象。
如果我在 ASP.NET 核心应用程序中登录 Azure Application Insight,情况也是如此。
有什么方法可以让我在日志中输出该数据?
If I log an exception with some key/value pairs added to Data, those values do not get logged.
Is there any way I can get that data to output in the logs?
在source code of ConsoleLogger
中,我们可以发现它并没有从Exception.Data
属性中提取用户定义的key/value对并将它们显示为输出。
为达到您的要求,您可以尝试实施和使用自定义控制台记录器,如下所示。
MyCustomConsoleLoggerProvider class
public class MyCustomConsoleLoggerProvider : ILoggerProvider
{
public void Dispose()
{
}
public ILogger CreateLogger(string categoryName)
=> new CustomConsoleLogger(categoryName);
}
CustomConsoleLogger class
internal class CustomConsoleLogger : ILogger
{
private readonly string _categoryName;
public CustomConsoleLogger(string categoryName)
=> _categoryName = categoryName;
public void Log<TState>(
LogLevel logLevel, EventId eventId, TState state, Exception exception,
Func<TState, Exception, string> formatter
)
{
if (!IsEnabled(logLevel))
{
return;
}
StringBuilder logBuilder = new StringBuilder();
logBuilder.Append($"{logLevel} {_categoryName}: {state}{(exception != null ? "\n" : string.Empty)}{exception}\n");
if (exception.Data != null)
{
logBuilder.Append("Exception Data: ");
exception.Data.Cast<DictionaryEntry>().ToList().ForEach((item) =>
{
string key = item.Key.ToString();
string vl = item.Value.ToString();
logBuilder.Append($"{key}:{vl}\n");
});
}
Console.WriteLine(logBuilder.ToString());
}
public bool IsEnabled(LogLevel logLevel)
=> true;
public IDisposable BeginScope<TState>(TState state)
=> null;
}
在控制台应用程序中
class Program
{
static void Main(string[] args)
{
var exception = new Exception("Oops!");
exception.Data.Add("useful-data-key1", "useful-data-value1");
exception.Data.Add("useful-data-key2", "useful-data-value2");
ILogger<Program> logger = LoggerFactory.Create(builder =>
{
//builder.AddConsole();
builder.AddProvider(new MyCustomConsoleLoggerProvider());
}).CreateLogger<Program>();
logger.LogError(exception, "An error occurred in the console.");
Console.WriteLine("Logged");
Console.Read();
}
}
测试结果