问题
If I log an exception with some key/value pairs added to Data, those values do not get logged. They would be really helpful for diagnosis of the issue in some cases but I can't see any way to configure that.
For example, the following console app:
<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();
}
}
Results in this being logged to the console:
fail: Console.Program[0]
An error occurred in the console.
System.Exception: Oops!
No sign of the values in the Data dictionary.
The same is true if I log to Azure Application Insight in an ASP.NET Core app.
Is there any way I can get that data to output in the logs?
回答1:
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?
In source code of ConsoleLogger, we can find that it does not extract user-defined key/value pairs from Exception.Data
property and display them as output.
To achieve your requirement, you can try to implement and use a custom Console logger, like below.
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;
}
In Console app
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();
}
}
Test Result
来源:https://stackoverflow.com/questions/60778831/is-there-a-way-to-log-the-values-from-the-data-dictionary-of-an-exception-in-ne