How do I render a template and its arguments manually in Serilog?

1.5k Views Asked by At

How do I implement the following method?

string BuildSerilogMessage(string messageTemplate, params object[] propertyValues);

The arguments are the same as the ones accepted by ILogger.Debug etc.

The reason why I want this is because I want to preserve template/values in an intermediate exception which needs to have single string Message as well. It is basically something like this:

// this exception is designed to be easily loggable by serilog
[Serializable]
public class StructuredException : Exception {
    public string MessageTemplate { get; private set; }
    public object[] PropertyValues { get; private set; }

    public StructuredException(string messageTemplate, params object[] propertyValues)
        : base(BuildMessage(messageTemplate, propertyValues))
    {
        MessageTemplate = messageTemplate;
        PropertyValues = propertyValues;
    }

    public StructuredException(Exception inner, string messageTemplate, params object[] propertyValues)
        : base(BuildMessage(messageTemplate, propertyValues), inner)
    {
        MessageTemplate = messageTemplate;
        PropertyValues = propertyValues;
    }

    private static string BuildMessage(string messageTemplate, object[] propertyValues) {
        // ???
    }
}
1

There are 1 best solutions below

1
Nicholas Blumhardt On

There's an example in the Akka.NET repo of this being done, though only scalar values are supported in the arguments.

The basic notion is to use MessageTemplateParser to get the template:

var parser = new MessageTemplateParser();
var template = parser.Parse(messageTemplate);

Then zip the tokens from the template up with the arguments:

var properties = template.Tokens
    .OfType<PropertyToken>()
    .Zip(propertyValues, Tuple.Create)
    .ToDictionary(
        p => p.Item1.PropertyName,
        p => new ScalarValue(p.Item2));

Finally rendering:

var rendered = template.Render(properties);

(Apologies in advance for the bits that may not compile here.)