Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serilog Destructure.ByTransforming<Interface>() not working

Tags:

c#

serilog

I would like Serilog to destructure any class that implement an interface (so I don't have to manually include them all.) The following doesn't seem to work:

public interface ITest { }

public class Test : ITest { }

public class Program
{
    public static int Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .Destructure.ByTransforming<ITest>(i => new { str = "Blah" })
            .CreateLogger();

        Log.Logger.Debug("We have issues with {@test}", new Test());
    }
}

Instead of getting {str="Blah"} as I do with a class destructure, I get {} Is there a trick to getting the destructuring to trigger for all that implement the interface?

like image 917
Cory-G Avatar asked May 04 '18 21:05

Cory-G


1 Answers

I found one way to do it. I couldn't find any documentation or examples online, but I flailed and figured out how to use a Destructuring Policy. Simply create a class that inherits from IDestructuringPolicy and implement the TryDestructure method. As parameters of TryDestructure, you will get the value to be destructured, a factory object that you can use to construct the result, and the last param is an out param of the result. The function should return true if the destructuring was a success and false otherwise.

I created a destructuring policy that checks the type of the incoming object. If it matches the interface type that I want, I destructure it like normal and return true.

Here is an example of one I created:

 public class ResponseDestructuringPolicy : IDestructuringPolicy
 {
   public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
   {
     if (value is IResponse response)
     {
       result = propertyValueFactory.CreatePropertyValue( new {response.Message} );
       return true;
     }

     result = null;
     return false;
   }
}

You then hook it to the logger when creating it like so:

 Log.Logger = new LoggerConfiguration()
     .Destructure.With(new ResponseDestructuringPolicy())
     .CreateLogger();

The Destructure.With() function can take as many polices as you want. It looks like Serilog checks for registered type destructures then it will run through each policy and run the TryDestructure functions on each until it gets true. If no true is received, it will go on to destructure the default way.

like image 190
Cory-G Avatar answered Oct 15 '22 00:10

Cory-G