Some of Serilog's standard template properties can be customised, e.g. {Timestamp:HH:mm:ss}
, {Level:u3}
and {Message:lj}
. Not so for {Exception}
, which prints both message and stack trace, on multiple lines.
For the human-readable console sink, a stack trace adds significant noise and friction, especially when tailing a remote docker container which is already ugly (no colour, for example). If I need the stack trace, I would consult a durable sink, e.g. file, Seq.
How can I log just the exception message to the console sink?
(I'm aware of Serilog.Expressions, but for something so simple I hope there's a solution without another dependency.)
As per a comment on the repo, here's a solution using a custom enricher.
Create the enricher ExceptionMessageEnricher.cs
:
using Serilog.Core;
using Serilog.Events;
namespace Serilog.Enrichers;
public sealed class ExceptionMessageEnricher : ILogEventEnricher
{
public const string PROPERTY_NAME = "ExceptionMessage";
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
ArgumentNullException.ThrowIfNull(logEvent, nameof(logEvent));
ArgumentNullException.ThrowIfNull(propertyFactory, nameof(propertyFactory));
if (logEvent.Exception == null) return;
var property = propertyFactory.CreateProperty(PROPERTY_NAME, $"\"{logEvent.Exception.Message}\"");
logEvent.AddPropertyIfAbsent(property);
}
}
Then use it in the Serilog config:
var outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {ExceptionMessage}{NewLine}";
services.AddSerilog((services, config) => config
// ...
.WriteTo.Logger(x => x
.Enrich.With<ExceptionMessageEnricher>()
.WriteTo.Console(outputTemplate:outputTemplate)
)
);
A rendered message would look something like this:
[13:04:44 ERR] Something bad happened "The exception message"
Notes:
ExceptionMessage
property, which is then referenced in the log templateExceptionMessage
property is not needed in durable sinks (e.g. file, Seq) as they receive the full exception anyway; thus the console sink and custom enricher are defined in a sub-logger - I'm unaware whether there are perf considerations, but I suspect it should be fineAn alternative approach, using Serilog.Expressions: {Inspect(@x).Message}
.