简体   繁体   中英

How to write logs to a specific sink depending on the developement environment in Serilog?

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM