Lurgle.Logging v1.2.2 - Destructure and mask structured properties!
Table of Contents
Update
After the original post, I tackled another item I'd been meaning to look at - being able to configure proxy settings for the Serilog Seq sink. Lurgle.Logging v1.2.3 now includes additional optional configurations for the Seq sink's proxy. This is particularly useful for console apps like Seq Reporter, to ensure they don't attempt to use your proxy config when logging to Seq.
You can configure the new settings in your app.config (as per below) or via the LoggingConfig()
constructor with Logging.SetConfig()
!
<!-- Optional Seq proxy settings -->
<add key="LogSeqUseProxy" value="false" />
<add key="LogSeqProxyServer" value ="" />
<add key="LogSeqBypassProxyOnLocal" value = "false" />
<add key="LogSeqProxyBypass" value = "" />
<add key="LogSeqProxyUser" value = "" />
<add key="LogSeqProxyPassword" value = "" />
Original post on the destructure and masking goodies below!
Lurgle Contemplation
It seems like such a long time ago since I first released Lurgle.Logging, but in fact it was only last month! In the original post I said:
This implementation does not currently destructure properties, but it's an enhancement to contemplate for future updates.
Well, I contemplated it, and here it is.
The purpose of destructuring is to ensure that on object passed which contains structured data - such as a class with its own properties - is reflected in your logging. If you pass a class to the log without destructuring, Serilog will return a ToString()
representation of the class type. If you destructure - you'll get the properties within that class.
The original logging class that became Lurgle.Logging didn't really account for destructuring since it wasn't needed for the implementation. When I created Lurgle, I was conscious that it was needed, but I parked it until now.
Destructured Lurgles, and a bonus - updating common properties!
It was, overall, quite simple to add the functionality. I needed to amend the AddProperty()
methods to include a bool (destructure
), and then it was just a matter of ensuring that the flag was passed on to Serilog, and that masking was also handled accordingly.
I inserted the new flag before the optional correlationId
, which means that the various static AddProperty()
methods have changed in implementation; for example:
public static ILevel AddProperty(string name, object value,
string correlationId = null,
bool showMethod = false,
[CallerMemberName] string methodName = null, [CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
is now:
public static ILevel AddProperty(string name, object value, bool destructure = false,
string correlationId = null,
bool showMethod = false,
[CallerMemberName] string methodName = null, [CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
and similarly, the fluent AddProperty()
methods have changed to implementations like;
public IAddProperty AddProperty(string name, object value, bool destructure = false)
I usually try to avoid breaking changes, but the static AddProperty methods are only a recent addition, and it's a relatively minor change.
This functionality also applies to common properties - properties that are persisted through all log events until cleared. As a bonus - while adding the destructure flag to AddCommonProperty()
, I also made it possible to update common properties that already exist. So the AddCommonProperty()
methods have changed to implementations like:
public static void AddCommonProperty(string name, object value, bool destructure = false, bool update = false)
The adddition of the update
flag means that if you already have a common property set, but need to update it for some reason, you can do so without having to clear the common properties and start again.
Masking destructured Lurgles
So one of the key benefits to destructuring is that we can apply masking to the destructured properties. There's an excellent implementation in the Masking.Serilog code, which was mostly workable but needed a little adjustment to avoid overlap with the Lurgle masking implementation.
I have therefore adapted the code to suit the Lurgle masking policy and configuration, and made it into an integrated destructurer, as shown by part of the LoggerConfiguration()
:
return config
.Destructure.WithMaskProperties()
The masking is controlled by your configuration for the LogMaskPolicy
; if my config is set to a masking policy, or if (as in my LurgleTest app) I were to enable masking using one of;
Logging.SetConfig(new LoggingConfig(Logging.Config, logMaskPolicy: MaskPolicy.MaskWithString));
Logging.SetConfig(new LoggingConfig(Logging.Config, logWriteInit: true, logMaskPolicy: MaskPolicy.MaskLettersAndNumbers));
Whether masking with a string, or masking letters or numbers - the result will be that any property within the LogMaskProperties
config that match within the destructured data will be masked.
In the above screenshot, the log message shows the deconstructed "Test" property that was passed to Serilog, and the Mechagodzilla
property that has been enabled for masking is correctly masked as per the LogMaskPolicy.MaskLettersAndNumbers
settings.
Lurgle it now!
As usual, you can update Lurgle.Logging via Nuget, or use the oh-so-fancy links:
Comments