# Orchardcore Logging Serilog

> Skill for configuring Serilog logging in Orchard Core. Covers Serilog integration setup, appsettings.json logging configuration with Console and File sinks, Program.cs Serilog initialization, tenant-aware logging with TenantName enrichment, and output template customization. Use this skill when requests mention Orchard Core Serilog Logging, Configure Serilog Structured Logging, Enabling the Feature, Serilog Configuration in appsettings.json, Output Template Tokens, Minimum Level Overrides, or closely related Orchard Core implementation, setup, extension, or troubleshooting work. Strong matches include work with OrchardCore.Logging.Serilog, FromLogContext, SourceContext, CreateBuilder, ProductService, appsettings.json, Program.cs, UseSerilog(), ReadFrom.Configuration(). It also helps with Output Template Tokens, Minimum Level Overrides, Program.cs Serilog Initialization, plus the code patterns, admin flows, recipe steps, and referenced examples captured in this skill.

- Skill: `crestapps/orchardcore-logging-serilog` (Agent Skill)
- Install (CLI): `npx skillmds@latest add crestapps/orchardcore-logging-serilog`
- Raw SKILL.md: https://api.skillmd.com/api/skills/crestapps/orchardcore-logging-serilog/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: CrestApps (https://skillmd.com/u/crestapps)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/crestapps/orchardcore-logging-serilog

---


# 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.Serilog` to enable Serilog integration.
- Configure Serilog in `appsettings.json` under the `Serilog` section.
- Initialize Serilog in `Program.cs` using `UseSerilog()` and `ReadFrom.Configuration()`.
- Always call `Enrich.FromLogContext()` to enable log context enrichment.
- Call `UseSerilogTenantNameLogging()` in the Orchard Core pipeline to add `TenantName` to 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 `restrictedToMinimumLevel` on 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 `sealed` modifier.

### Enabling the Feature

```json
{
  "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:

```json
{
  "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:

```json
{
  "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:

```csharp
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:

```json
{
  "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:

```json
{
  "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:

```json
{
  "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"
        }
      }
    ]
  }
}
```

