Serilog File Logging
Overview
EasyAdminBlazor ships with database logging (viewable on the admin “Error Log” page). For production troubleshooting, file logging is often needed: write logs to the server disk with daily/size-based rotation so they can be inspected and archived directly. Serilog is the recommended way — a few lines of configuration, and it can coexist with the framework’s built-in database logger.
Installation
Add the NuGet packages to your project (pick the latest stable versions matching your .NET version):
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.File
Quick Start
Add the following in Program.cs before building the builder:
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((ctx, cfg) => cfg
.MinimumLevel.Information()
.WriteTo.File("logs/log-.log",
rollingInterval: RollingInterval.Day, // rotate daily
retainedFileCountLimit: 30, // keep at most 30 files
fileSizeLimitBytes: 20 * 1024 * 1024, // max 20MB per file
rollOnFileSizeLimit: true, // roll to a new file when the size limit is hit
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}")
, writeToProviders: true); // ⚠️ important: keep the framework’s built-in logger providers
builder.AddEasyAdminBlazor(...);
⚠️
writeToProviders: trueis required: by defaultUseSerilogreplaces the ASP.NET Core logging providers, so the framework’s database logger stops receiving entries (the admin “Error Log” page goes quiet). With this parameter, Serilog file logging and database logging coexist.
Configuration-Driven Setup (Recommended)
For production, keep the log level and paths in configuration. First install Serilog.Settings.Configuration:
dotnet add package Serilog.Settings.Configuration
Program.cs:
builder.Host.UseSerilog((ctx, cfg) => cfg.ReadFrom.Configuration(ctx.Configuration), writeToProviders: true);
appsettings.json:
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "logs/log-.log",
"rollingInterval": "Day",
"retainedFileCountLimit": 30,
"fileSizeLimitBytes": 20971520,
"rollOnFileSizeLimit": true,
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
Common Options
| Option | Description | Example |
|---|---|---|
rollingInterval |
Rotation interval | Day / Hour / Minute / Infinite |
retainedFileCountLimit |
Max log files to keep; older files are deleted | 30 |
fileSizeLimitBytes |
Max size per file | 20971520 (20MB) |
rollOnFileSizeLimit |
Roll to a new file when the size limit is hit | true |
shared |
Allow multiple processes to write the same file (multi-instance) | true |
outputTemplate |
Per-line output format | see above |
MinimumLevel |
Minimum log level | Warning (recommended for production) |
MinimumLevel.Override |
Per-namespace level override | "Microsoft": "Warning" |
Coexisting with the Framework’s Database Logger
The two loggers serve different purposes:
- Database logger (built-in): viewed on the admin “Error Log” page for in-console troubleshooting
- File logger (Serilog): written to the server disk for direct inspection, archiving and auditing
The key to coexistence is writeToProviders: true. If you want file logging only (no database logger), remove the parameter (or set it to false); note that the admin “Error Log” page will then stop receiving entries.
Note: the framework’s database logger only records Error level and above (the admin “Error Log” page is for troubleshooting errors), so normal Information entries will not appear there; use the file log for full logging.
Multi-Instance Deployment Notes
- By default, do not use
shared: true; multiple processes writing the same file will conflict. Let each instance write to its own directory. - If multiple instances must share one log directory, add
shared: trueto the File sink and watch for file-lock and performance issues. - Disk space: control it with the retention policy (
retainedFileCountLimit) so logs do not fill the disk.
Performance Tips
- For high-throughput scenarios, add
Serilog.Sinks.Asyncfor asynchronous disk writes so logging does not slow down requests. - In production, start at
Warningto avoid flooding the disk withInformationentries.
Troubleshooting
- No log file is created: check that the directory exists and is writable; check whether
MinimumLevelfilters out the target level. - The admin “Error Log” page has no new entries:
UseSerilogreplaced the default providers — verifywriteToProviders: trueis present. - Chinese characters garbled: Serilog writes UTF-8 by default; if you need another encoding, specify
encoding.