Luke
Luke

Reputation: 23

Serilog: Usage of additional properties

I'm trying to write additional properties to the log using {Properties} (which are not in the message template):

Used (FileSink) template:

"[{Level}] {Message}{NewLine}{Properties}{NewLine}{Exception}"

Log operation (simplified, normally the object array is given by a method parameter):

Log.Information("Start logging",
    new object[]{
        new { Version = "VersionString"},
        new { StartDate = DateTime.Now },
        new { Id = Guid.NewGuid() }
    });

I also tired:

Log.Information("Start logging",
    new object[]{
        "VersionString",
        DateTime.Now,
        Guid.NewGuid()
    });

I had a look on LogEventPropertyCapturingTests and this PR, but I couldn't get it working...


Update I use wrapper functions like this:

public static void Information(string messageTemplate, object[] propertyValues, bool show = false, [CallerMemberName] string callerMethodeName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumer = -1)
{
    using (LogContext.PushProperty("CallingContext", new { callerMethodeName, callerFilePath, callerLineNumer }))
    {
        _MainLog.Information(messageTemplate, propertyValues);
    }

    if(show)
    {
        // Code to show a the event to the user
    }
}

Update2 Found a way but it's not very nice, as the template-property-matching rudimentary.

public static void Information(string messageTemplate, object[] propertyValues, bool show = false, [CallerMemberName] string callerMethodeName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumer = -1)
{
    using (LogContext.PushProperty("CallingContext", new { callerMethodeName, callerFilePath, callerLineNumer }))
    {
        Regex matchProperties = new Regex("{[^}]+}");

        int usedPropertiesCount = matchProperties.Matches(messageTemplate).Cast<Match>().Select(m => m.Value).Distinct().Count();

        if (propertyValues.Length > usedPropertiesCount)
        {
            using (LogContext.PushProperty("AdditionalData", propertyValues.Skip(usedPropertiesCount)))
            {
                _MainLog.Information(messageTemplate, propertyValues);
            }
        }
        else
        {
            _MainLog.Information(messageTemplate, propertyValues);
        }
    }

    if(show)
    {
        // Code to show a the event to the user
    }
}

Upvotes: 1

Views: 1474

Answers (1)

Nicholas Blumhardt
Nicholas Blumhardt

Reputation: 31877

The ForContext() method will do this:

Log.ForContext("Version", "VersionString")
    .ForContext("Id", Guid.NewGuid())
    .Information("Start logging");

(I've omitted StartDate because all Serilog events are already timestamped.)

This blog post series includes some posts on message templates plus context and correlation that cover this plus other alternatives.

Upvotes: 2

Related Questions