This really threw me, and I've spent lots of time trying to understand something that was really simple and logical. Don't you just hate those issues?
An app I'm developing is using Serilog. Serilog is awesome. The app is running ASP.NET Core 2.2 and hosted on Azure App Service.
Getting Serilog to work locally was easy peasy, just install it with Nuget, add the Sinks needed and configure it in Program.cs
public static void Main(string[] args) {
// Create the Logger configuration
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.WriteTo.Console()
.CreateLogger();
// ...
try
{
Log.Debug("Application Starting at {date} ({EnvironmentName}).", DateTime.Now, EnvironmentName);
CreateWebHostBuilder(args)
.Build()
.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application died");
}
finally
{
Log.CloseAndFlush();
}
}
Then just add .UseSerilog()
the IWebHostBuilder
method CreateWebHostBuilder
(assuming you are using standard dotnet CLI initialised, or Visual Studio crated project).
However, I wanted Serilog to read from my application settings and environment variables in order to configure things using the Azure portal. Adding the Serilog.Settings.Configuration
package takes care of that and a simple ReadFrom.Configuration()
is added just before CreateLogger()
Again, this is FINE on my local dev environment. However, when building and publishing to Azure, nothing was being logged.
Oddly enough, it seems Azure doesn't pickup environment variables and/or configuration before the CreateWebHostBuild
method is called. This is troubling if you want to be able to log anything that might happen when the app STARTS (like, in the actual CreateWebHostBuilder
, or even before that.
Here's an easy way to solve it; Configure the logger with a hard coded file path that is accessible on Azure (D:\home\LogFiles\Application\
for instance) and re-configure it in Startup.cs (ConfigureServices
).
public void ConfigureServices(IServiceCollection services)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.ReadFrom.Configuration(Configuration) // << THIS!!
.Enrich.FromLogContext()
.CreateLogger();
// All other goodies
}
Now, running this on a mac, or Windows without a D:\ would introduce new problems. I solved that part by checking for an environment variable that I know Azure sets: WEBSITE_SITE_NAME
Here's the updated Program.cs
Main function:
public static void Main(string[] args)
{
// Check if app is running on Azure, the WEBSITE_SITE_NAME environment variable will be set if it is.
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME")))
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.Enrich.FromLogContext()
.WriteTo.File(path: @"D:\home\LogFiles\Application\log.txt", fileSizeLimitBytes: 1_000_000,
flushToDiskInterval: TimeSpan.FromSeconds(5), shared: true,
restrictedToMinimumLevel: LogEventLevel.Debug)
.CreateLogger();
}
else
{
// Not Azure, just log to Console, no need to persist
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.WriteTo.Console()
.CreateLogger();
}
try
{
Log.Debug("Application Starting at {date} ({EnvironmentName}).", DateTime.Now, EnvironmentName);
CreateWebHostBuilder(args)
.Build()
.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application died 💀");
}
finally
{
Log.CloseAndFlush();
}
}
Top comments (0)