serilog-extensions-logging: Destructuring operator doesn't work

I’m playing with Serilog.Framework.Logging and I noticed the following issue when using the Serilog destructuring paramter (“@”): I think it’s best if I illustrate it with some code. Here my test code:

class Foo
{
    public string SValue { get; set; }
    public int IValue { get; set; }
}

[Test]
public void StructuredLogging()
{
    Log.Logger = new LoggerConfiguration().MinimumLevel.Information()
        .WriteTo.Seq("http://localhost:5341")
        .CreateLogger();

    var loggerFactory = new LoggerFactory();
    loggerFactory.AddSerilog(Log.Logger);

    var logger = loggerFactory.CreateLogger(typeof(SerilogTests).FullName);

    var foo = new Foo { SValue = "some value", IValue = 42 };
    Log.Information("Serilog message {@value}", foo);
    logger.LogInformation("M.F.L message: {value}", foo);
    logger.LogInformation("M.F.L message: {@value}", foo);
}

I.e. I’m writing a log message to Microsoft.Framework.Logging after configuring it to use Serilog as well as writing a log message directly through the Serilog API. Here the result:

screenshot

As you can see the message I wrote using the Serilog API directly (last one in the screenshot) properly destructures the Foo object. However, the message written through M.F.Logging doesn’t.

I did some debugging and I noticed that writing to Serilog directly ends up calling

Logger.Write(LogEventLevel.Information, exception, messageTemplate, propertyValues);

where propertyValues is an array of 1 element containing the Foo object.

Serilog.Framework.Logging also ends up calling this method, however the call looks as follows (see SerilogLogger.Log():

logger.Write(level, exception, messageTemplate);

Here we don’t provide the Foo object as parameter. Instead it was added using ForContext() a couple of lines earlier.

Now, it seems that approach works fine when using “regular” placeholders in the message template string (e.g. “{value}”), but it doesn’t seem to properly work with the destructuring parameter (e.g. “{@value}”).

Is there anything I can do to get this working? Or is this a known issue/limitation?

Thanks for your help!

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 17 (12 by maintainers)

Commits related to this issue

Most upvoted comments

Doing some build work so dropped this change in; @alecor191 did you find the null-check necessary in:

if ((property.Key != null) && (property.Key.StartsWith("@")))

? I left it off since I think it’d probably violate the intentions if not the contract of ILogValues to return null for the key, but if you hit it in practice it’d be great to know.

Thanks again for the suggestion!

That’s great news! Looking forward to your decision.

BTW I updated in a similar way SerilogLoggerProvider.Enrich(), specifically the following line

var property = propertyFactory.CreateProperty(keyValue.Key, keyValue.Value);

That allows me to write code like:

var foo = ... // some object
var myLogValues = new MyLogValues(); // Implements ILogValues
myLogValues.Add("@Foo", foo); // Use destructuring parameter

using (logger.BeginScope(myLogValues))
{
    logger.LogInformation("Some message");
}

This way I can attach destructured objects to my logging messages in cases where I don’t want them to be part of the message template (essentially get a similar behavior as with ForContext()).