I'm using Serilog with Azure Functions v4 and .NET 7. I am trying to write logs to both the local console and Application Insights. I already spent hours trying different solutions and the situation at the time of writing seems to be that this technology stack (Azure Functions + Application Insights) is not mature or too recent, and not yet very well documented.
Setting up appsettings.{env}.json
files by environment and trying to add a different Serilog config by environment does not work with Azure Functions. Depending on the solution I tried, either Microsoft logger is used or there are no logs.
The code below is working for the console but I get duplicate logs on Application Insights. And if I remove Console sink, it works well in Application Insights but I get no more local logs:
.UseSerilog((hostBuilderContext, serviceProvider, loggerConfiguration) =>
loggerConfiguration
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.ApplicationInsights(
serviceProvider.GetRequiredService<TelemetryConfiguration>(),
TelemetryConverter.Traces)
)
I also tried other ways of setting up the logger, for example in .ConfigureServices(...
, injecting it differently in the function code, but no luck. Many samples talk about a Startup
method that I don't have. If it helps I can post the whole Program.cs
and the function code here.
So I now added .Enrich.WithEnvironmentName()
to get the environment name from an environment variable, and the question is: how can I filter the logs using ByIncludingOnly
in the code above (not config file) to include logs depending on the environment name (Local
or Development
)? Same question for ByExcluding
- I guess answer will be similar.
This is the way to do it. I ended up not using the Environment enricher because it is at the time of writing not supporting the Azure environment variable for Azure Functions (AZURE_FUNCTIONS_ENVIRONMENT
). See this issue:
https://github.com/serilog/serilog-enrichers-environment/issues/49
This is how I got this working:
First option enriching the log event:
// Careful: Serilog is not able to enrich with the value of this variable and will default to 'Production'
var value = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") ?? "Development";
var predicate = $"EnvironmentName = 'Local'";
Log.Logger = new LoggerConfiguration()
.Enrich.WithProperty("EnvironmentName", value)
.MinimumLevel.Debug()
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(predicate)
.WriteTo.Console(outputTemplate: "{Properties} {Message}"))
.WriteTo.Logger(lc => lc
.WriteTo.File(path: Directory.GetCurrentDirectory() + @"\test.txt"))
.CreateLogger();
Second option without enriching the log event:
var value = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") ?? "Development";
var predicate = $"{value} = 'Local'";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(predicate)
.WriteTo.Console(outputTemplate: "{Properties} {Message}"))
.WriteTo.Logger(lc => lc
.WriteTo.File(path: Directory.GetCurrentDirectory() + @"\test.txt"))
.CreateLogger();