为了调试启动失败的.net核心应用程序,我想从startup.cs文件中编写日志.我在文件中有日志设置,可以在startup.cs文件之外的应用程序的其余部分使用,但不知道如何从startup.cs文件本身写入日志.
pok*_*oke 98
随着ASP.NET Core 2.0的发布,这已经发生了重大变化.在ASP.NET Core 2.0中,将在主机构建器中创建日志记录.这意味着默认情况下可以通过DI获取日志记录,并且可以将其注入到Startup类中:
public class Startup
{
private readonly ILogger<Startup> _logger;
public IConfiguration Configuration { get; }
public Startup(ILogger<Startup> logger, IConfiguration configuration)
{
_logger = logger;
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
_logger.LogInformation("ConfigureServices called");
// …
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
_logger.LogInformation("Configure called");
// …
}
}
Run Code Online (Sandbox Code Playgroud)
San*_*ket 25
选项1:在启动时直接使用日志(例如Serilog) -
public class Startup
{
public Startup(IHostingEnvironment env)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "Serilog-{Date}.txt"))
.CreateLogger();
Log.Information("Inside Startup ctor");
....
}
public void ConfigureServices(IServiceCollection services)
{
Log.Information("ConfigureServices");
....
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
Log.Information("Configure");
....
}
Run Code Online (Sandbox Code Playgroud)
输出:
要在asp.net-core应用程序中设置Serilog,请查看GitHub上的Serilog.AspNetCore包.
选项2:配置program.cs中的日志记录,如下所示:
var host = new WebHostBuilder()
.UseKestrel()
.ConfigureServices(s => {
s.AddSingleton<IFormatter, LowercaseFormatter>();
})
.ConfigureLogging(f => f.AddConsole(LogLevel.Debug))
.UseStartup<Startup>()
.Build();
host.Run();
Run Code Online (Sandbox Code Playgroud)
用户loggerFactory在启动时像这样 -
public class Startup
{
ILogger _logger;
IFormatter _formatter;
public Startup(ILoggerFactory loggerFactory, IFormatter formatter)
{
_logger = loggerFactory.CreateLogger<Startup>();
_formatter = formatter;
}
public void ConfigureServices(IServiceCollection services)
{
_logger.LogDebug($"Total Services Initially: {services.Count}");
// register services
//services.AddSingleton<IFoo, Foo>();
}
public void Configure(IApplicationBuilder app, IFormatter formatter)
{
// note: can request IFormatter here as well as via constructor
_logger.LogDebug("Configure() started...");
app.Run(async (context) => await context.Response.WriteAsync(_formatter.Format("Hi!")));
_logger.LogDebug("Configure() complete.");
}
}
Run Code Online (Sandbox Code Playgroud)
此链接提供完整的详细信息
Lia*_*ang 16
在.NET Core 3.1 中,您可以直接使用 LogFactory 创建记录器。
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Startup>();
logger.LogInformation("Example log message");
Run Code Online (Sandbox Code Playgroud)
R.T*_*tov 16
对于.Net 6
var builder = WebApplication.CreateBuilder(args);
...
var app = builder.Build();
var logger = ((IApplicationBuilder)app).ApplicationServices.GetService<ILogger<Program>>();
logger.LogInformation("Some logs");
Run Code Online (Sandbox Code Playgroud)
或者更简单的方法:
var builder = WebApplication.CreateBuilder(args);
...
var app = builder.Build();
ILogger logger = app.Logger;
Run Code Online (Sandbox Code Playgroud)
目前官方的解决方案是像这样设置本地 LoggerFactory:
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Information);
builder.AddConsole();
builder.AddEventSourceLogger();
});
var logger = loggerFactory.CreateLogger("Startup");
logger.LogInformation("Hello World");
Run Code Online (Sandbox Code Playgroud)
另见:https : //github.com/dotnet/aspnetcore/issues/9337#issuecomment-539859667
使用Rolf 的答案,我将其放入我的 Startup 构造函数中:
private readonly ILogger _logger;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Information);
builder.AddConsole();
builder.AddEventSourceLogger();
});
_logger = loggerFactory.CreateLogger<Startup>();
}
public void ConfigureServices(IServiceCollection services)
{
_logger.LogInformation("ConfigureServices...");
// ...and so on...
}
Run Code Online (Sandbox Code Playgroud)
现有的答案都不适合我。我正在使用 NLog,甚至构建一个新的 ServiceCollection,在任何服务集合上调用 .CreateBuilder(),创建日志记录服务......这些都不会在 ConfigureServices 期间写入日志文件。
问题是,只有在 ServiceCollection 构建之后,日志记录才真正成为问题,而且它不是在 ConfigureServices 期间构建的。
基本上,我只想(需要)在配置扩展方法中记录启动期间发生的情况,因为我遇到问题的唯一层是 PROD,我无法附加调试器。
对我有用的解决方案是使用旧的 .NET Framework NLog 方法:
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
Run Code Online (Sandbox Code Playgroud)
将这一权利添加到扩展方法类中,并且我能够在ConfigureServices 期间及之后写入日志(“该”日志)。
我不知道这是否是一个真正发布到生产代码中的好主意(我不知道 .NET 控制的 ILogger 和这个 NLog.ILogger 是否会在任何时候发生冲突),但我只需要它来看看发生了什么在。
对于 .NET Core 3.0,官方文档是这样说的:https : //docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view= aspnetcore-3.0#create-logs-in- startup
Startup.ConfigureServices不支持在方法中完成 DI 容器设置之前写入日志:
Startup不支持将 Logger 注入到构造函数中。Startup.ConfigureServices不支持将 Logger 注入到方法签名中
但是正如他们在文档中所说,您可以配置依赖于 ILogger 的服务,因此如果您编写了一个类 StartupLogger:
public class StartupLogger
{
private readonly ILogger _logger;
public StartupLogger(ILogger<StartupLogger> logger)
{
_logger = logger;
}
public void Log(string message)
{
_logger.LogInformation(message);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在 Startup.ConfigureServices 添加服务,然后你需要构建服务提供者来访问 DI 容器:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(provider =>
{
var service = provider.GetRequiredService<ILogger<StartupLogger>>();
return new StartupLogger(service);
});
var logger = services.BuildServiceProvider().GetRequiredService<StartupLogger>();
logger.Log("Startup.ConfigureServices called");
}
Run Code Online (Sandbox Code Playgroud)
编辑:这会产生一个编译器警告,为了调试您的 StartUp 类,这应该没问题,但不适用于生产:
Startup.cs(39, 32): [ASP0000] 从应用程序代码调用“BuildServiceProvider”会导致创建一个额外的单例服务副本。考虑替代方案,例如将依赖注入服务作为“配置”的参数。
小智 5
我使用了一个解决方案,避免使用ILogger接口实现“记录器缓冲区”的 3rd 方记录器。
public class LoggerBuffered : ILogger
{
class Entry
{
public LogLevel _logLevel;
public EventId _eventId;
public string _message;
}
LogLevel _minLogLevel;
List<Entry> _buffer;
public LoggerBuffered(LogLevel minLogLevel)
{
_minLogLevel = minLogLevel;
_buffer = new List<Entry>();
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return logLevel >= _minLogLevel;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (IsEnabled(logLevel)) {
var str = formatter(state, exception);
_buffer.Add(new Entry { _logLevel = logLevel, _eventId = eventId, _message = str });
}
}
public void CopyToLogger (ILogger logger)
{
foreach (var entry in _buffer)
{
logger.Log(entry._logLevel, entry._eventId, entry._message);
}
_buffer.Clear();
}
}
Run Code Online (Sandbox Code Playgroud)
在startup.cs 中使用很简单,当然你会在调用Configure 后得到日志输出。但总比没有好。:
public class Startup
{
ILogger _logger;
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
_logger = new LoggerBuffered(LogLevel.Debug);
_logger.LogInformation($"Create Startup {env.ApplicationName} - {env.EnvironmentName}");
}
public void ConfigureServices(IServiceCollection services)
{
_logger.LogInformation("ConfigureServices");
services.AddControllersWithViews();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
(_logger as LoggerBuffered).CopyToLogger(logger);
_logger = logger; // Replace buffered by "real" logger
_logger.LogInformation("Configure");
if (env.IsDevelopment())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23548 次 |
| 最近记录: |