Orchard Core Serilog Logging - Prompt Templates
Configure Serilog Structured Logging
You are an Orchard Core expert. Generate configuration and code for Serilog integration including structured logging, Console and File sinks, tenant-aware enrichment, and output template customization.
Guidelines
- Add a reference to
OrchardCore.Logging.Serilogto enable Serilog integration. - Configure Serilog in
appsettings.jsonunder theSerilogsection. - Initialize Serilog in
Program.csusingUseSerilog()andReadFrom.Configuration(). - Always call
Enrich.FromLogContext()to enable log context enrichment. - Call
UseSerilogTenantNameLogging()in the Orchard Core pipeline to addTenantNameto the log context. - Clear default logging providers before configuring Serilog to prevent duplicate log entries.
- Use the
{TenantName}token in output templates to include the tenant name in log entries. - Use the
{RequestId}token to correlate log entries across a single HTTP request. - Use
restrictedToMinimumLevelon individual sinks to control per-sink log verbosity. - The Console sink is useful for development; the File sink with rolling intervals is recommended for production.
- All recipe JSON must be wrapped in
{ "steps": [...] }. - All C# classes must use the
sealedmodifier.
Enabling the Feature
{
"steps": [
{
"name": "Feature",
"enable": [
"OrchardCore.Logging.Serilog"
],
"disable": []
}
]
}
Serilog Configuration in appsettings.json
Configure Console and File sinks with minimum levels, output templates, and rolling intervals:
{
"Serilog": {
"MinimumLevel": {
"Default": "Warning",
"Override": {
"Default": "Warning",
"Microsoft": "Error",
"System": "Error"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "{Timestamp:HH:mm:ss}|{TenantName}|{RequestId}|{SourceContext}|{Level:u3}|{Message:lj}{NewLine}{Exception}",
"restrictedToMinimumLevel": "Information"
}
},
{
"Name": "File",
"Args": {
"path": "App_Data/logs/orchard-log.txt",
"rollingInterval": "Day",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.ffff}|{TenantName}|{RequestId}|{SourceContext}|{Level:u3}|{Message:lj}{NewLine}{Exception}",
"restrictedToMinimumLevel": "Warning"
}
}
]
}
}
Output Template Tokens
| Token | Description |
|---|---|
{Timestamp:format} |
Log entry timestamp in the specified format |
{TenantName} |
Name of the Orchard Core tenant processing the request |
{RequestId} |
Unique ID for correlating log entries within a single HTTP request |
{SourceContext} |
Fully qualified name of the class that generated the log entry |
{Level:u3} |
Log level as a 3-character uppercase string (e.g., INF, WRN, ERR) |
{Message:lj} |
The log message with JSON literals inline |
{NewLine} |
Platform-appropriate line break |
{Exception} |
Exception details, if present |
Minimum Level Overrides
Use Override to control log verbosity per namespace. This reduces noise from framework internals:
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore": "Error",
"System": "Error",
"OrchardCore": "Warning"
}
}
}
}
Program.cs Serilog Initialization
Configure Serilog in Program.cs by clearing default providers and reading from configuration:
using Serilog;
var builder = WebApplication.CreateBuilder(args);
builder.Host
.ConfigureLogging(logging => logging.ClearProviders())
.UseSerilog((hostingContext, configBuilder) =>
{
configBuilder
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext();
});
builder.Services.AddOrchardCms();
var app = builder.Build();
app.UseOrchardCore(c => c.UseSerilogTenantNameLogging());
app.Run();
Tenant-Aware Logging
The UseSerilogTenantNameLogging() middleware enriches every log entry with the current tenant's name. This is critical for multi-tenant deployments where logs from different tenants are written to the same output.
The {TenantName} token in the output template renders the tenant name:
14:32:05|Default|0HN4K5...|MyApp.Services.ProductService|INF|Product created: Widget
14:32:06|Tenant2|0HN4K5...|MyApp.Services.ProductService|INF|Product created: Gadget
File Sink with Rolling Interval
For production, use the File sink with daily rolling to manage log file sizes:
{
"Serilog": {
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "App_Data/logs/orchard-log.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 31,
"fileSizeLimitBytes": 104857600,
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.ffff}|{TenantName}|{RequestId}|{SourceContext}|{Level:u3}|{Message:lj}{NewLine}{Exception}",
"restrictedToMinimumLevel": "Warning"
}
}
]
}
}
| File Sink Property | Description |
|---|---|
path |
Base file path for log output |
rollingInterval |
How often to roll to a new file (Day, Hour, Month) |
retainedFileCountLimit |
Maximum number of rolled log files to retain |
fileSizeLimitBytes |
Maximum size of a single log file before rolling |
restrictedToMinimumLevel |
Minimum log level for this sink |
Development vs Production Configuration
Use environment-specific appsettings.{Environment}.json files to vary logging:
appsettings.Development.json — verbose console output:
{
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Information"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:HH:mm:ss}|{TenantName}|{Level:u3}|{SourceContext}|{Message:lj}{NewLine}{Exception}",
"restrictedToMinimumLevel": "Debug"
}
}
]
}
}
appsettings.Production.json — file-only, warnings and above:
{
"Serilog": {
"MinimumLevel": {
"Default": "Warning",
"Override": {
"Microsoft": "Error",
"System": "Error"
}
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "App_Data/logs/orchard-log.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 14,
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.ffff}|{TenantName}|{RequestId}|{SourceContext}|{Level:u3}|{Message:lj}{NewLine}{Exception}",
"restrictedToMinimumLevel": "Warning"
}
}
]
}
}