0

I'm working on an ASP.NET Core 8 Web API project using Serilog to log to both the console and a file.

Everything works perfectly in development (when running locally via Visual Studio), but when I publish to IIS, no log file is created in the specified path.

My Serilog config in appsettings.json:

"Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": {
        "Default": "Information",
        "Override": {
            "Microsoft": "Warning",
            "System": "Warning"
        }
    },
    "WriteTo": [
        { "Name": "Console" },
        { "Name": "File",
            "Args": {
                "path": "C:\\NotificationSystemLogs\\log-.txt",
                "rollingInterval": "Day",
                "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
            }
        }
    ],
    "Enrich": [ "FromLogContext" ],
    "Properties": {
        "Application": "NotificationSystem"
    }
}

In Program.cs, I have:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateBootstrapLogger();

Log.Information("Starting up...");

builder.Host.UseSerilog((ctx, services, configuration) =>
    new LoggerConfiguration()
        .ReadFrom.Configuration(ctx.Configuration)
        .ReadFrom.Services(services)
        .Enrich.FromLogContext()
        .CreateLogger()
);

What I tried so far:

  • Manually created C:\NotificationSystemLogs and gave "Everyone" full access
  • Also gave IIS APPPOOL\NotificationSystem modify permissions to the folder
  • Set correct path in appsettings.json (used double backslashes)
  • Tried writing logs from background service and middleware — no output
  • Used SelfLog.Enable(...) for debugging Serilog itself — no errors are captured

Still no file is created in production (IIS).

The app runs fine and I can access it, but Serilog just silently doesn't write to file.

Environment:

  • ASP.NET Core 8 Web API
  • Hosted on IIS (Windows Server)
  • AppPool Identity: ApplicationPoolIdentity
  • Log folder path: C:\NotificationSystemLogs

Question

What could be causing Serilog to not write logs to file in IIS, even though:

  • The folder exists
  • Permissions are correct
  • No exception is thrown
  • Works locally

Any ideas?

5
  • Can you try with a shorter path? It may exceed max URL length. Commented Jul 22 at 9:56
  • Maybe ASPNETCORE_ENVIRONMENT not set to to Production? Maybe you have also deployed the development json or another file and it uses that? Commented Jul 22 at 14:55
  • You can use Process Monitor to see if indeed the worker process (w3wp.exe) tries to write to that path, learn.microsoft.com/en-us/sysinternals/downloads/procmon and if not, it is a Serilog issue. Commented Jul 22 at 16:39
  • @ErkinD39 I already tries this but no Worthy Commented Aug 27 at 10:19
  • Not also this @Patric Commented Aug 27 at 10:19

2 Answers 2

0
var path = Path.Combine(builder.Environment.ContentRootPath,"NotificationSystemLogs");
var isExists = Directory.Exists(path);
if(!isExists)
{
Directory.CreateDirectory(path)
}
Right click appsettings.json -> properties -> Copy to Output Directory = Copy always
Sign up to request clarification or add additional context in comments.

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0

Why it worked locally but not on IIS

Locally the app runs under your user account (via Visual Studio) which typically has full write access to C:\….
On IIS the app runs under the ApplicationPoolIdentity and writing to the root of C:\ is often blocked or restricted by ACLs/Group Policy/Controlled Folder Access, even if you think you granted “Everyone” or the app pool user permissions. As a result the file sink simply never manages to create/open the target file and you see no log file in production.

There was also a subtle configuration issue: I was creating a new LoggerConfiguration inside UseSerilog(...) instead of composing the one provided by the host. That can cause the configuration from appsettings.json/DI to be ignored depending on how you wire it.

Fix

  1. Log to a path inside the app folder (content root) and ensure the directory exists at startup.

  2. Use the loggerConfiguration instance passed into UseSerilog(...) (don’t new LoggerConfiguration() there).

    // Bootstrap (early) logger
    Log.Logger = new LoggerConfiguration()
        .WriteTo.Console()
        .CreateBootstrapLogger();
    
    try
    {
        var builder = WebApplication.CreateBuilder(args);
    
        // Build a writable path under the app's content root
        var logDir  = Path.Combine(AppContext.BaseDirectory, "Logs");
        Directory.CreateDirectory(logDir); // safe if it already exists
        var logPath = Path.Combine(logDir, "Notification-log-.txt");
    
        // IMPORTANT: use the provided 'config' (loggerConfiguration) here
        builder.Host.UseSerilog((ctx, services, config) =>
        {
            config.MinimumLevel.Debug()
                  .Enrich.FromLogContext()
                  .ReadFrom.Configuration(ctx.Configuration)
                  .ReadFrom.Services(services)
                  .WriteTo.Console()
                  .WriteTo.File(
                      path: logPath,
                      rollingInterval: RollingInterval.Day,
                      outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
                  );
        });
    
        var app = builder.Build();
    
        app.UseSerilogRequestLogging();
        app.Run();
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "Application failed to start correctly");
    }
    finally
    {
        Log.CloseAndFlush();
    }
    
    

    Notes

    • If you insist on an absolute path outside the site folder, grant Modify to IIS AppPool\<YourAppPoolName> (and/or IIS_IUSRS) and make sure the folder actually exists.

    • Ensure the correct appsettings.*.json is deployed and being read; optionally set Copy to Output Directory = Copy always for appsettings.json.

    After moving the log path under AppContext.BaseDirectory/Logs, creating the directory, and wiring UseSerilog correctly, file logging started working on IIS.

Comments

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.