Overview
Silky integrates Serilog as its structured logging framework via the Silky.Logging.Serilog module. Serilog provides a rich Sink ecosystem for writing logs to console, file, Elasticsearch, Seq, and more, with deep SkyAPM integration (automatic TraceId injection into every log entry).
Installation
<PackageReference Include="Silky.Logging.Serilog" Version="3.9.2" />
Silky.Logging.Serilogis already included inSilky.Agent.Host— no separate installation needed if you use that package.
Quick Start
Enable Serilog with a single method call in Program.cs:
var hostBuilder = Host.CreateDefaultBuilder(args)
.ConfigureSilkyGeneralHostDefaults()
.UseSerilogDefault(); // enable Serilog (default: Console + File)
await hostBuilder.Build().RunAsync();
UseSerilogDefault() behavior:
- Reads the
Serilogconfig section fromappsettings.json/appsettings.yamlif present. - If
Serilog:WriteTois not configured, automatically enables:- Console: format
[HH:mm:ss LVL] Message {Properties} - File: rolling file
logs/application.log, daily rotation, UTF-8
- Console: format
Configuration File
Serilog:
MinimumLevel:
Default: Information
Override:
Microsoft: Warning
Microsoft.Hosting.Lifetime: Information
System: Warning
WriteTo:
- Name: Console
Args:
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}"
- Name: File
Args:
path: logs/application.log
rollingInterval: Day
retainedFileCountLimit: 30
outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}"
Enrich:
- FromLogContext
When Serilog:WriteTo is present in configuration, UseSerilogDefault() uses only the configured sinks — no automatic Console/File.
Custom Configuration (Code)
.UseSerilogDefault(config =>
{
config
.WriteTo.Console()
.WriteTo.File("logs/app.log", rollingInterval: RollingInterval.Day)
.WriteTo.Seq("http://localhost:5341");
});
Elasticsearch Integration
Serilog:
WriteTo:
- Name: Elasticsearch
Args:
nodeUris: "http://localhost:9200"
indexFormat: "silky-logs-{0:yyyy.MM}"
autoRegisterTemplate: true
Structured Logging Best Practices
Caution
Always use structured logging placeholders {PropertyName}, not string interpolation.
// ✅ Correct — structured, searchable in Seq/ELK
_logger.LogInformation("RPC call starting for {ServiceId} with timeout {Timeout}ms", serviceId, timeout);
// ❌ Wrong — destroys structure, incompatible with Seq/ELK
_logger.LogInformation($"RPC call starting for {serviceId} with timeout {timeout}ms");
Log Levels
| Level | When to use |
|---|---|
Trace / Debug | Internal diagnostic detail — disabled in production |
Information | Lifecycle events: startup, shutdown, significant state changes |
Warning | Recoverable errors: retry succeeded, fallback activated |
Error | Failures requiring attention: unhandled exceptions, data corruption |
Critical | System-level failures that require immediate action |
SkyAPM TraceId Integration
When Silky.SkyApm.Agent is installed, every log entry automatically includes the current TraceId and SpanId. This correlates log entries with distributed traces in SkyWalking:
[2026-04-23 10:15:00 INF] Order created {OrderId: 1001, TraceId: "abc123", SpanId: "1.1"}
