I have struggle for weeks to get NLog to log my communication data including unspecific(DataContracts) parameters to file in a format that are ELK-stack compatible. It need to be configured in runtime and its preferred if the output parameters can be limited like MAX chars or depth.
NLog have a built-in JSON serializer but it will only read properties without defaults, fields will be ignored as you can see here. It would be a big job to adapt my data model and I do not really think its the right way to go, NLog should not affect how the data model should look like.
There is a couple of ways to add a custom JSON serializer :
I could use SetupSerialization on each class(Datacontract) like this :
LogManager.Setup().SetupSerialization(s => s.RegisterObjectTransformation<GetEntityViewRequest>(obj => return Newtonsoft.Json.Linq.JToken.FromObject(obj) ) );
Because I want to log all communication data the entire data model will have to be registered, its huge job and not effective.
I could use a custom IValueFormatter but it can´t be added to just my communication NLog instance, it have to be added in globally to all loggers like this :
NLog.Config.ConfigurationItemFactory.Default.ValueFormatter = new NLogValueFormatter();
So the IValueFormatter needs to filter so it is only manipulate data from the communication logger. I probably need to wrap my data in a class with a flag that tells IValueFormatter where the data come from, It do however not feel like a optimal solution.
There are also problems to actually get NLog to put out the data that the ValueFormatter filter as you can see here. The ValueFormatter do still run but its the regular NLog JSON data that will end up in the file.
What I need from NLog is this :
- Transform all communication data including parameters from object to string formatted so ELK stack read it.
- Serialization depth or string MAX length on parameters to avoid data overflow
- Configurable from NLog.config in runtime(as NLog is)
- Affect only a specific NLogger instance
My data come in through a IParameterInspector, it is compiled into a special CallInformation class that also holds the parameters(type object). The parameters can be vary complex with several layers. The entire CallInforamtion object is sent to NLog like this :
_comLogger.Log(LogLevel.Info, "ComLogger : {@callInfo}", callInfo);
The Nlog.config looks like this right now :
<logger name="CommunicationLogger" minlevel="Trace" writeto="communicationFileLog"></logger>
<target xsi:type="File"
name="communicationFileLog"
fileName="${basedir}/logs/${shortdate}.log"
maxArchiveDays="5"
maxArchiveFiles="10">
<layout xsi:type="JsonLayout" includeAllProperties="true" maxRecursionLimit="1">
</layout>
</target>
What am I missing? Is there another log library that might support my needs better?