If I have the following class
public class Customer
{
public string Name;
}
and then have the following log command in Serilog
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
var item = new Customer();
item.Name = "John";
Serilog.Log.Information("Customer {@item}", item);
The log just displays in Seq as
Customer {}
If I change the Name field to a property it works but I would prefer not to do that at this stage. Is there any way around it?
To do this just for the one type (recommended), you can use:
.Destructure.ByTransforming<Customer>(c => new { c.Name })
If you want to include public fields for all types, or those matching some kind of condition, you can plug in a policy to do it:
class IncludePublicFieldsPolicy : IDestructuringPolicy
{
public bool TryDestructure(
object value,
ILogEventPropertyValueFactory propertyValueFactory,
out LogEventPropertyValue result)
{
if (!(value is SomeBaseType))
{
result = null;
return false;
}
var fieldsWithValues = value.GetType().GetTypeInfo().DeclaredFields
.Where(f => f.IsPublic)
.Select(f => new LogEventProperty(f.Name,
propertyValueFactory.CreatePropertyValue(f.GetValue(value))));
result = new StructureValue(fieldsWithValues);
return true;
}
}
The example scopes this down to look at objects derived from SomeBaseType
only.
You can plug it in with:
.Destructure.With<IncludePublicFieldsPolicy>()
(I think it's likely to require some tweaking, but should be a good starting point.)