在哪里可以记录ASP.NET Core应用程序的启动/停止/错误事件?

k4emjkb1  于 2023-06-07  发布在  .NET
关注(0)|答案(4)|浏览(162)

在旧的ASP.NET中,在Global.asax.cs类中,我会记录应用程序何时启动,停止和抛出未处理的异常:

  • Application_Start()
  • Application_End()
  • Application_Error()

如何在ASP.NET Core中执行相同的操作?它有一个Startup类,但它用于配置。
我在哪里挂钩到应用程序的开始/停止/错误事件?

webghufk

webghufk1#

注意:对于.NET Core 3.0或更高版本,此答案已过时。看看这个答案。
您需要使用Microsoft.AspNetCore.Hosting.IApplicationLifetime

/// <summary>
    /// Triggered when the application host has fully started and is about to wait
    /// for a graceful shutdown.
    /// </summary>
    CancellationToken ApplicationStarted { get; }

    /// <summary>
    /// Triggered when the application host is performing a graceful shutdown.
    /// Requests may still be in flight. Shutdown will block until this event completes.
    /// </summary>
    CancellationToken ApplicationStopping { get; }

    /// <summary>
    /// Triggered when the application host is performing a graceful shutdown.
    /// All requests should be complete at this point. Shutdown will block
    /// until this event completes.
    /// </summary>
    CancellationToken ApplicationStopped { get; }

IApplicationLifetime的示例可以通过Configure方法获得。在这里添加ILoggerFactory:

public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory)
{
    // use applicationLifetime
}

有了ILoggerFactory,你可以ILoggercreate示例:

var logger = loggerFactory.CreateLogger("StartupLogger");

所以你只需要在Startup类中创建一个属性来持久化ILogger的示例(或者ILoggerFactory,如果你想为不同的事件创建不同的ligger示例)。总结如下:

public class Startup 
{
    private ILogger _logger;

    public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime, ILoggerFactory loggerFactory) 
    {
        applicationLifetime.ApplicationStopping.Register(OnShutdown);
        ... 
        // add logger providers
        // loggerFactory.AddConsole()
        ...
        _logger = loggerFactory.CreateLogger("StartupLogger");
    }

    private void OnShutdown()
    {
         // use _logger here;
    }
}
cgvd09ve

cgvd09ve2#

我不喜欢@neustart47的回答,因为它不必要地复杂,但他是对的,IApplicationLifetime是过时的。
取自Microsoft Docs

//  1. Add the interface `IHostedService` to the class you would like
//     to be called during an application event. 
internal class LifetimeEventsHostedService : IHostedService
{
    private readonly ILogger _logger;
    private readonly IHostApplicationLifetime _appLifetime;

    // 2. Inject `IHostApplicationLifetime` through dependency injection in the constructor.
    public LifetimeEventsHostedService(
        ILogger<LifetimeEventsHostedService> logger, 
        IHostApplicationLifetime appLifetime)
    {
        _logger = logger;
        _appLifetime = appLifetime;
    }

    // 3. Implemented by `IHostedService`, setup here your event registration. 
    public Task StartAsync(CancellationToken cancellationToken)
    {
        _appLifetime.ApplicationStarted.Register(OnStarted);
        _appLifetime.ApplicationStopping.Register(OnStopping);
        _appLifetime.ApplicationStopped.Register(OnStopped);

        return Task.CompletedTask;
    }

    // 4. Implemented by `IHostedService`, setup here your shutdown registration.
    //    If you have nothing to stop, then just return `Task.CompletedTask`
    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    private void OnStarted()
    {
        _logger.LogInformation("OnStarted has been called.");

        // Perform post-startup activities here
    }

    private void OnStopping()
    {
        _logger.LogInformation("OnStopping has been called.");

        // Perform on-stopping activities here
    }

    private void OnStopped()
    {
        _logger.LogInformation("OnStopped has been called.");

        // Perform post-stopped activities here
    }
}

附加信息

将上面的类添加到项目后,转到Program.cs文件并添加如下调用以注入服务(并示例化类):builder.Services.AddHostedService<LifetimeEventsHostedService>();
一旦你添加了它,构建并再次运行应用程序,你会看到日志语句...

"OnStarted has been called."

等等的。
成交!

utugiqy6

utugiqy63#

请参阅CaptureStartupErrors和方法.CaptureStartupErrors(true),它将帮助您找到问题。
当某些东西在localhost上运行完美但在Azure中失败时,这特别方便。
以下是我对NetCore Web Apps的常用配置:

public static IWebHost BuildWebHost(string[] args) => WebHost
            .CreateDefaultBuilder(args)
            .CaptureStartupErrors(true)
            .UseKestrel()
            .UseIISIntegration()
            .UseStartup<Startup>()
            .UseAzureAppServices()
            .Build();

在Azure应用服务中,您可以在Kudu Tools https://<appname>.scm.azurewebsites.net/api/logstream的日志流中找到日志

jaql4c8m

jaql4c8m4#

使用顶部答案中建议的Microsoft.AspNetCore.Hosting.IApplicationLifetime现在已经过时了。

[Obsolete("This type is obsolete and will be removed in a future version. The recommended alternative is Microsoft.Extensions.Hosting.IHostApplicationLifetime.", false)]
public interface IApplicationLifetime

使用IHostApplicationLifetime在应用程序关闭时触发回调。
在某处添加:

public static async Task WaitForShutdownAsync(this IHost host)
{
    // Get the lifetime object from the DI container
    var applicationLifetime = host.Services.GetService<IHostApplicationLifetime>();

    // Create a new TaskCompletionSource called waitForStop
    var waitForStop = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);

    // Register a callback with the ApplicationStopping cancellation token
    applicationLifetime.ApplicationStopping.Register(obj =>
    {
        var tcs = (TaskCompletionSource<object>)obj;

        //PUT YOUR CODE HERE 

        // When the application stopping event is fired, set 
        // the result for the waitForStop task, completing it
        tcs.TrySetResult(null);
    }, waitForStop);

    // Await the Task. This will block until ApplicationStopping is triggered,
    // and TrySetResult(null) is called
    await waitForStop.Task;

    // We're shutting down, so call StopAsync on IHost
    await host.StopAsync();
}

然后我在Program.cs中使用它:

var host = CreateHostBuilder(args).Build();
host.WaitForShutdownAsync();

其他回调也是如此。更多信息,请访问here
如果我错过了什么请让我知道

相关问题