I'm trying to log model passed to controller by doing something like this:
_log
.ForContext("Id", "XXXXXX-XXXX-XXXX-XXXXXXXXX")
.ForContext("Email", email)
.ForContext("UserId", userId)
.ForContext("Parameters", parameters)
.ForContext("Errors", errors.ToArray())
.ForContext("ActionArguments", actionArguments)
.Information(message);
where actionArguments
is of type IDictionary<string, object> actionArguments
. This is interpreted like
{
someProperty: "Some.Namespace.Dtos.Something.MyTypeDto"
}
and I really wish someProperty
to be expanded to what complex type represents. Is it possible? How to do it?
By default, Serilog will serialize objects with types it does not understand (including your own custom types) by just calling ToString()
to get a simple representation. The default implementation of ToString()
for an object just returns the full name of the type, which is why the type name of your DTO is showing up in the log context.
What you're after is called 'destructuring' in Serilog. In the documentation, this is defined as:
Destructuring is the process of taking a complex .NET object and converting it into a structure, which may later be represented as say, a JSON object or XML blob
There's an optional argument destructureObjects
that you can provide to the ILogger.ForContext
method that tells Serilog to try and pull out additional information from the object:
.ForContext("ActionArguments", actionArguments, destructureObjects: true)
By default it will destructure recursively using reflection, effectively walking down all of the object's properties and any properties of those properties, etc. until it finds a type that it knows how to format.
Just be careful that you're not logging any sensitive information by using this approach; Serilog will do its best to include every value it finds.