0

I'm using Serilog to log information on my app. I'm using an appsettings.json file (see below) to setup the configuration settings of the logger. In that file, I have two configurations - one for writing to a file and another for writing to the console output. What I would like to be able to do is to only write to a file if my application is running in the IIS context. Otherwise, it should only output the log to the console. However, I'm a bit stuck on how to do this.

appsettings.json

{
    "Serilog": {
        "Using": [ "SeriLog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Async" ],
        "MinimumLevel": {
            "Default": "Information",
            "Override": {
                "Microsoft": "Information",
                "Microsoft.AspNetCore": "Warning",
                "System": "Warning"
            }
        },
        "WriteTo": [
            {
                "Name": "File",
                "Args": {
                    "outputTemplate": "RC  [{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}",
                    "path": "logs/mylog-.txt",
                    "rollingInterval": "Day"
                }
            },
            {
                "Name": "Console",
                "Args": {
                    "outputTemplate": "RC  [{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
                }
            }
        ],
        "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
        "Properties": {
            "Application": "MyApplication"
        }
    },
    "AllowedHosts": "*"
}

Program.cs

public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables()
    .Build();

public static void Main(string[] args)
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
    Config.Load();
    Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(Configuration)
    .Filter.ByExcluding("RequestPath in ['/healthcheck', '/favicon.ico']")
    .CreateLogger();

    var host = Host.CreateDefaultBuilder(args)
        .UseSerilog()
        .ConfigureWebHostDefaults(webBuilder =>
        {
            var b = webBuilder.ConfigureKestrel((context, options) =>
            {
                // Handle requests up to 50 MB
                options.Limits.MaxRequestBodySize = Config.MaxRequestSize;
            })
            .UseIISIntegration()
            .UseStartup<Startup>()
            .CaptureStartupErrors(true);
        }).Build();

    var logger = host.Services.GetRequiredService<ILogger<ReverseProxyModule>>();
    ReverseProxyModule.InitializeConcurrentRequestLogging(logger);

    host.Run();
}

2 Answers 2

1

You could also try to use the is below code in the program.cs file to generate file logs for the iis environment only.

using Serilog;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

var builder = WebApplication.CreateBuilder(args);

// Load configuration
var configuration = builder.Configuration;

//  Detect if running under IIS or Azure App Service
bool isRunningUnderIIS = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_HTTPAUTH") != null
    || Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID") != null; // Azure App Service support

// Debugging logs
Console.WriteLine($"Environment: {builder.Environment.EnvironmentName}");
Console.WriteLine($"ASPNETCORE_IIS_HTTPAUTH: {Environment.GetEnvironmentVariable("ASPNETCORE_IIS_HTTPAUTH")}");
Console.WriteLine($"WEBSITE_INSTANCE_ID: {Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID")}");
Console.WriteLine($"Is running under IIS: {isRunningUnderIIS}");

//  Configure Serilog dynamically and IGNORE `appsettings.json` for logging sinks
var loggerConfig = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .Enrich.WithMachineName()
    .Enrich.WithThreadId();

if (isRunningUnderIIS)
{
    Console.WriteLine(" Running under IIS, enabling File logging...");
    loggerConfig.WriteTo.File("logs/mylog-.txt", rollingInterval: RollingInterval.Day,
        outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}");
}
else
{
    Console.WriteLine(" Running Locally, enabling Console logging...");
    loggerConfig.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}");
}

//  Apply Serilog
Log.Logger = loggerConfig.CreateLogger();
builder.Host.UseSerilog();

// Add services to the container
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build(); 

// Configure the HTTP request pipeline
if (app.Environment.IsDevelopment() || app.Environment.IsProduction())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseSerilogRequestLogging();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

Result from visual studio:

enter image description here

Result after deploying on iis: enter image description here

Sign up to request clarification or add additional context in comments.

Comments

0

If you mean one sink for when it is live in production and one for when developing on your local computer, you could have an appsettings.production.json and an appsettings.development.json, and keep the appsettings.json for configurations that should apply to both.

3 Comments

You wrote appsettings.development.json twice... Are they supposed to have different names? Do I have to add any settings to my main function to tell it when to use which json file?
Yes, I fixed it now.
You just add each appsettings the same way. .AddJsonFile("appsettings.production.json", optional: false, reloadOnChange: true), .AddJsonFile("appsettings.development.json", optional: false, reloadOnChange: true) and .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true). Hope that answers your question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.