Reputation:
My goal in the code below is to create a root exception handler which will handle all otherwise unhandled errors. When I run my web app under IIS on Azure it immediately crashes. The log file is shown below. When I run the program at the command line I can see the error.
My questions are:
Why is the error not logged?
How can I write the handler such that all errors are logged?
Program.cs
public class Program
{
public static void Main(string[] args)
{
string env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
string logRoot = null;
if (env == "Development")
logRoot = "c:\\serilog\\myDomain.Web\\log";
else
logRoot = "..\\..\\serilog\\myDomain.Web\\log"; // Create logs in D:\home\serilog
Log.Logger = new LoggerConfiguration()
.WriteTo.File(logRoot, rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information)
.CreateLogger();
try
{
Log.Information("myDomain.Web - Program.Main started.");
Log.Information("Environment is: {env}", env);
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
finally
{
Log.CloseAndFlush();
}
}
2021-01-07 15:58:44.833 +00:00 [INF] myDomain.Web - Program.Main started.
2021-01-07 15:58:45.009 +00:00 [INF] Environment is: null
D:\home\site\wwwroot>myDomain.Web.exe crit: Microsoft.AspNetCore.Hosting.Diagnostics[6] Application startup exception System.IO.DirectoryNotFoundException: D:\home\site\wwwroot\StaticHTML
at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root, ExclusionFilters filters) at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root) at LeaderAnalytics.myDomain.Web.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env) in D:\a\1\s\myDomain.Web\Startup.cs:line 57 at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
The exception handler shown is the root exception handler. To demonstrate it should be handling the specific exception I cited I replaced my code with a throw statement
(because my code works in dev but fails in prod) and observed the handler being called as shown in the image below.
throw new Exception("boo");
app.UseStaticFiles(new StaticFileOptions // this line fails in prod
Upvotes: 2
Views: 2786
Reputation: 1813
If the process response code matters the initial example will return status 0 for success.
From cmd prompt run dotnet run
then run echo %errorlevel%
The code below will log and re-throw the exception to maintane the behavior of returning a non 0 errorLevel when the process fails to start.
public static class ConfigureSerilogExtensions
{
public static void SetupSerilogStartupLogger(Action action)
{
var logPath = "App_Data/logs/app.log";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console()
.WriteTo.File(logPath, rollingInterval: RollingInterval.Day)
.CreateLogger();
try
{
Log.Information("Starting web host");
action();
Log.CloseAndFlush();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
Log.CloseAndFlush();
throw;
}
}
}
Usage
ConfigureSerilogExtensions.SetupSerilogStartupLogger(() => {
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
var app = builder.Build();
app.UseSerilog();
app.Run();
});
Upvotes: 0
Reputation: 327
It looks ok.but have you add dependency(DI) of log or relateable class of logging framework in your configureservice method in startup.cs?
like this : public void ConfigureServices(IServiceCollection services) { services.AddSingleton<ILogger, Logger>(); }
Upvotes: 0
Reputation:
I finally got it thanks to Nicholas comment above.
https://nblumhardt.com/2019/10/serilog-in-aspnetcore-3/
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog() // <- Add this line
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Upvotes: 1