9

I'm new to Serilog - trying it out to see if it will help. I'm using Serilog v2 and Serilog.Sinks.MsSqlServer v5

I have the following console app code:

static void Main(string[] args)
    {
        var logger = CreateLogger();

        var employee = new Person()
        {
            Name = "Rob",
            Age = 45
        };

        logger.Debug("Employee details {Employee}", employee);

        Console.ReadKey();

    }

private static ILogger CreateLogger()
    {

        string levelString = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
                            "LCC.Common", "Serilog.MinimumLevel");

        SerilogLevel level = (SerilogLevel)Enum.Parse(typeof(SerilogLevel), levelString);

        string conString = SSOSettingsFileManager.SSOSettingsFileReader.ReadString(
                            "LCC.Common", "Serilog.ConnectionString");

        var levelSwitch = new LoggingLevelSwitch();
        levelSwitch.MinimumLevel = (Serilog.Events.LogEventLevel)level;

        return new LoggerConfiguration()
            .MinimumLevel.ControlledBy(levelSwitch)
            .WriteTo.MSSqlServer(connectionString: conString, tableName: "Logs", autoCreateSqlTable: true)
            .CreateLogger();
    }

I would have expected the details of Person to be logged i.e. Name Rob and Age 45. However, I find the following logged to the Properties column on my Sql Server Sink:

<properties><property key='Employee'>ConsoleApplication1.Person</property></properties>

Where did I go wrong?

Rob Bowman
  • 7,632
  • 22
  • 93
  • 200

3 Answers3

27

here is Serilog documentation

For this task, Serilog provides the @ destructuring operator.

var sensorInput = new { Latitude = 25, Longitude = 134 };
Log.Information("Processing {@SensorInput}", sensorInput);

as you can see to do destructuring you have to set @ before key name. This is missed in your sample code

logger.Debug("Employee details {Employee}", employee);
oleksa
  • 3,688
  • 1
  • 29
  • 54
0

@oleksa's answer worked for me and helped me realize what I needed to do in my case of trying to log some info from a controller using the Log.ForContext(...) approach. Here are a couple examples:

Option 1:

I prefer this approach since it keeps the view cleaner in the log aggregator (Seq in my case).

// Inside controller GET method

Employee employee = await myService.GetData();

// Need to set the `destructureObjects` flag to `true`
Log.ForContext<Employee>(Serilog.Events.LogEventLevel.Information, "Employee", employee, true)
   .Information("Employee Information");

Option 2:

// Inside controller GET method

Employee employee = await myService.GetData();

Log.Information("Employee Information {@Employee}", employee);

.NET 6 & Serilog 5.0

Mycah
  • 4,602
  • 5
  • 24
  • 32
-4

The logging framework is going to call ToString on the object passed to it. If you want the details logged, one option would be to override the ToString method to serialize the object (assumes reference to Newtonsoft.JSON library):

// in Person.cs
public override string ToString()
{
    return JsonConvert.SerializeObject(this);
}
Kyle Burns
  • 1,164
  • 7
  • 16
  • 1
    I thought the idea of serilog was to avoid the need for such explicit serialisation - it is a structured logging framework – Rob Bowman Oct 05 '17 at 11:01