英文:
Logging to Console with DI in C#
问题
在这个简短的示例中,如果我只保留在 ConfigureServices
中的 .AddConsole()
,无论 LogLevel 如何设置,都不会将任何消息记录到控制台。但如果我添加 .AddConsole().AddDebug()
,所有消息都会记录到控制台,而且会记录三次!我漏掉了什么?谢谢!
namespace samples
{
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
public class Program
{
public static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
var app = serviceProvider.GetService<Application>();
app.Run();
}
private static void ConfigureServices(IServiceCollection services)
{
// 添加日志记录器
services.AddLogging(configure => configure.AddConsole().AddDebug());
// 注册应用程序
services.AddTransient<Application>();
}
}
public class Application {
private readonly ILogger logger;
public Application(ILogger<Application> logger)
{
this.logger = logger;
this.logger.LogInformation("在 Application::ctor 中");
}
public void Run()
{
this.logger.LogInformation("信息:在 Application::Run 中");
this.logger.LogWarning("警告:在 Application::Run 中");
this.logger.LogError("错误:在 Application::Run 中");
this.logger.LogCritical("严重错误:在 Application::Run 中");
}
}
}
对于每个 Log*() 调用,显示如下内容:
fail: samples.Application[0]
错误:在 Application::Run 中
samples.Application: 错误:错误:在 Application::Run 中
更新/解决方案
感谢 @panoskarajohn 找出了这个问题。App.Run()
需要是异步的:
将 app.Run(); => Task.Run(() => app.Run()).Wait();
更改为
public void Run() => public async Task Run()
,
并且不需要调用 AddDebug()
选项,应该可以正常工作。
我找不到关于为什么会发生这种情况的任何信息。
有人知道为什么吗?
英文:
in this short sample, if I keep just the .AddConsole()
in ConfigureServices
nothing gets logged to console regardless of the LogLevel, but if I add .AddConsole().AddDebug()
all messages get logged to Console 3 times! What am I missing? Thanks!
namespace samples
{
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
public class Program
{
public static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
var app = serviceProvider.GetService<Application>();
app.Run();
}
private static void ConfigureServices(IServiceCollection services)
{
// Add Logger
services.AddLogging(configure => configure.AddConsole().AddDebug());
// Register Application
services.AddTransient<Application>();
}
}
public class Application {
private readonly ILogger logger;
public Application(ILogger<Application> logger)
{
this.logger = logger;
this.logger.LogInformation("In Application::ctor");
}
public void Run()
{
this.logger.LogInformation("Info: In Application::Run");
this.logger.LogWarning("Warn: In Application::Run");
this.logger.LogError("Error: In Application::Run");
this.logger.LogCritical("Critical: In Application::Run");
}
}
}
And this is what gets displayed for each Log*() call:
fail: samples.Application[0]
Error: In Application::Run
samples.Application: Error: Error: In Application::Run
Update/Solution
Thanks @panoskarajohn for figuring this out. App.Run() needed to be an async:
Change app.Run(); => Task.Run(() => app.Run()).Wait();
public void Run() => public async Task Run()
And should work without debugging() option
I cannot find anything on why this happens
Anyone knows why?
答案1
得分: 4
我不知道为什么addDebug()
选项不起作用。
我想AddDebug()
可能有一些特殊的配置,并在程序退出之前刷新输出。 如果你有任何线索,请 enlighten 我们。
#为什么addConsole()
不起作用?
控制台日志记录发生在后台线程上。所以如果应用程序退出得太快,那么记录器就没有时间记录 -> https://github.com/aspnet/Logging/issues/631
所以问题不是它不起作用,而是它没有时间写入控制台。应用程序退出得太快。
为了在你的代码中修复这个问题。在程序的末尾添加Console.Read()
,这样它就不会退出。
public static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
var app = serviceProvider.GetService<Application>();
app.Run();
Console.Read(); // 所以应用程序不会退出,后台线程有时间完成其工作
}
我还找到了另一个解决方案,即创建一个异步的
Task
并等待它。
更新代码如下:
public static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
var app = serviceProvider.GetService<Application>();
Task.Run(() => app.Run()).Wait();
}
// 还要更新你的 Application run 方法
public async Task Run()
{
logger.LogInformation("Info: In Application::Run");
logger.LogWarning("Warn: In Application::Run");
logger.LogError("Error: In Application::Run");
logger.LogCritical("Critical: In Application::Run");
}
###最终结果应该是这样的。
public class Program
{
public static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
var app = serviceProvider.GetService<Application>();
Task.Run(() => app.Run()).Wait();
Console.Read();
}
private static void ConfigureServices(IServiceCollection services)
{
// 添加日志记录器
services.AddLogging(configure =>
{
configure.AddConsole();
}).AddTransient<Application>();
}
}
public class Application
{
private readonly ILogger<Application> logger;
public Application(ILogger<Application> logger)
{
this.logger = logger;
this.logger.LogInformation("In Application::ctor");
}
public async Task Run()
{
logger.LogInformation("Info: In Application::Run");
logger.LogWarning("Warn: In Application::Run");
logger.LogError("Error: In Application::Run");
logger.LogCritical("Critical: In Application::Run");
}
}
英文:
>I am not aware why this is not happening for the addDebug()
option.
I suppose the AddDebug()
has some special configuration, and flushes the output before the program exits. Please if you have any clues enlighten us.
#Why the addConsole() does not work?
Console logging is happening on a background thread. So if the application exits too fast then the logger doesn't have time to log -> https://github.com/aspnet/Logging/issues/631
So it is not that it is not happening. It is that it does not have time to write to the console. The application exits too fast.
In order to fix this in your code. Add a Console.Read()
at the end of your program so that it won't exit.
public static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
var app = serviceProvider.GetService<Application>();
app.Run();
Console.Read(); // So the application will not exit and there will be time for the background thread to do its job
}
>Also i came across another solution which is create an asynchronous Task
and wait upon it.
Update the code like this.
public static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
var app = serviceProvider.GetService<Application>();
Task.Run(() => app.Run()).Wait();
}
// also update your Application run method
public async Task Run()
{
logger.LogInformation("Info: In Application::Run");
logger.LogWarning("Warn: In Application::Run");
logger.LogError("Error: In Application::Run");
logger.LogCritical("Critical: In Application::Run");
}
###The end result should look like this.
public class Program
{
public static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
var app = serviceProvider.GetService<Application>();
Task.Run(() => app.Run()).Wait();
Console.Read();
}
private static void ConfigureServices(IServiceCollection services)
{
// Add Logger
services.AddLogging(configure =>
{
configure.AddConsole();
}).AddTransient<Application>();
}
}
public class Application
{
private readonly ILogger<Application> logger;
public Application(ILogger<Application> logger)
{
this.logger = logger;
this.logger.LogInformation("In Application::ctor");
}
public async Task Run()
{
logger.LogInformation("Info: In Application::Run");
logger.LogWarning("Warn: In Application::Run");
logger.LogError("Error: In Application::Run");
logger.LogCritical("Critical: In Application::Run");
}
//public void Run()
//{
// logger.LogInformation("Info: In Application::Run");
// logger.LogWarning("Warn: In Application::Run");
// logger.LogError("Error: In Application::Run");
// logger.LogCritical("Critical: In Application::Run");
//}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论