问题描述
我正在测试新的结构化日志但是并不能真正做到这一点.
Im testing out the new structured logging but do not really get it right.
我的nlog.config中有这个文件:
I have this in my nlog.config :
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log">
<layout xsi:type="JsonLayout" includeAllProperties="true">${longdate}|${level}|${logger}|${message}</layout>
</target>
<logger name="CommunicationLogger" minlevel="Info" writeto="f"></logger>
我的日志代码如下:
public void LogCommunication(string operation, List<object> args)
{
var parameters = new List<object>();
var text = "Operation:{Operation} ";
parameters.Add(operation);
text += "PersonId:{PersonId} ";
parameters.Add(SharedContext.GetMyUserContext().CurrentPersonId);
text += "ClientMachineName:{ComputerName} ";
parameters.Add(SharedContext.GetMyUserContext().ClientMachineName);
text += "Servername:{MachineName} ";
parameters.Add(Environment.MachineName);
if (args != null)
{
foreach(var param in args)
{
text += "Param:{@Parameters} ";
parameters.Add(param);
}
}
_log.LogCommunication(text, parameters.ToArray());
}
public void LogCommunication(string message, params object[] args)
{
_comLogger.Log(LogLevel.Info, message, args);
}
输出看起来像这样:
我希望参数也可以序列化,而不只是showint [],这样我就可以看到服务操作的所有参数.该参数是带有dataContract(WCF)的复杂类型.
I would like the Parameters to also get serialize instead of just showint [] so I can see all the parameters of the service operation. The parameter is a complex type with dataContract(WCF).
是否有一种简单的方法来获取用于结构数据的参数.
Is there a simple way to get the parameters to work with structural data.
Retagards
Retagards
Update1
nlog.config
nlog.config
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log">
<layout xsi:type="JsonLayout" includeAllProperties="true" maxRecursionLimit="10">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level}"/>
<attribute name="message" layout="${message}" />
</layout>
</target>
设置数据的代码
var parameters = new List<object>();
var text = "{TimeStamp} - ";
parameters.Add(DateTime.Now);
text += "Duration:{Duration} ";
parameters.Add(Timestamp);
text += "Operation:{Operation} ";
parameters.Add(operation);
text += "PersonId:{PersonId} ";
parameters.Add(SharedContext.GetMyUserContext().CurrentPersonId);
text += "ClientMachineName:{ComputerName} ";
parameters.Add(SharedContext.GetMyUserContext().ClientMachineName);
text += "Servername:{MachineName} ";
parameters.Add(Environment.MachineName);
if (args != null && args.Count() > 0)
{
text += "Param:{@Parameters} ";
parameters.Add(args);
}
_log.LogCommunication(text, parameters.ToArray());
结果:
{时间":"2020-04-09 01:31:00.3637",级别":信息",消息": "2020-04-09 01:31:00-持续时间:00:00:00.5594936 操作:\"GetExternaAnrop \" PersonId:1 ClientMachineName:\"MyComputer \"服务器名称:\"MyComputer \" 参数:[{\"PlaceringKeyList \":[],\"ArbetsstalleIdList \":[], \"RollList \":[]}]," TimeStamp:" 2020-04-08T23:31:00.363752Z, "Duration":"00:00:00.5594936","Operation":"GetExternaAnrop", "PersonId":1,"ComputerName":"SE-MyCom","MachineName": "SE-MyCom",参数":[{"PlaceringKeyList":[], "ArbetsstalleIdList":[],"RollList":[]}]}
{ "time": "2020-04-09 01:31:00.3637", "level": "Info", "message": "2020-04-09 01:31:00 - Duration:00:00:00.5594936 Operation:\"GetExternaAnrop\" PersonId:1 ClientMachineName:\"MyComputer\" Servername:\"MyComputer\" Param:[{\"PlaceringKeyList\":[], \"ArbetsstalleIdList\":[], \"RollList\":[]}] ", "TimeStamp": "2020-04-08T23:31:00.363752Z", "Duration": "00:00:00.5594936", "Operation": "GetExternaAnrop", "PersonId": 1, "ComputerName": "SE-MyCom", "MachineName": "SE-MyCom", "Parameters": [{"PlaceringKeyList":[], "ArbetsstalleIdList":[], "RollList":[]}] }
Update2
我有一个如下所示的服务方法:
I have a service method that looks like this :
GetEntityViewResponse GetReferenceData(GetEntityViewRequest request);
请求类如下:
[DataContract]
public class GetEntityViewRequest
{
public GetEntityViewRequest(params EntityViewKey[] Keys)
{
EntityViewKeys.AddRange(Keys);
}
public GetEntityViewRequest(params int[] EgnaKodtyper)
{
MyList.AddRange(EgnaKodtyper);
}
public GetEntityViewRequest()
{
}
[DataMember]
public List<EntityViewKey> EntityViewKeys = new List<EntityViewKey>();
[DataMember]
public List<int> MyList= new List<int>();
}
运行代码(发送请求)时,我可以在服务端的messageInspector中看到我已获取数据. EntityViewKeys有一个枚举集.
When running the code(sending the request) I can see in my messageInspector on the serviceside that I got data. The EntityViewKeys have a enum set.
NLog输出看起来像这样:
The NLog output looks like this :
因此,即使该类并不复杂,它仍不会在NLog中打印内容?
So even if the class is not complex it is still not printing the content in NLog?
推荐答案
JsonLayout有一个重要参数称为MaxRecursionLimit
(默认值= 0,直到NLog v5到达):
There is an important parameter for JsonLayout called MaxRecursionLimit
(Default = 0 until NLog v5 arrives):
https://github.com/nlog/nlog/wiki/JsonLayout
因此您可以执行以下操作:
So you can do this:
<layout xsi:type="JsonLayout" includeAllProperties="true" maxRecursionLimit="10">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level}"/>
<attribute name="message" layout="${message}" />
</layout>
也许您想将参数更改为此:
Maybe you want to change your parameters into this:
if (args != null)
{
text += "Params:{@Parameters} ";
parameters.Add(args);
}
默认情况下,NLog不会序列化对象字段,而只会序列化对象属性.如果必须填写字段,则可以使用NLog 4.7设置安装程序自定义反射:
NLog will by default not serialize object-fields, but only object-properties. If fields are a must, then you can setup setup custom reflection with NLog 4.7:
LogManager.Setup().SetupSerialization(s =>
s.RegisterObjectTransformation<GetEntityViewResponse>(obj => new {
EntityViewKeys = obj.EntityViewKeys,
MyList = obj.MyList,
})
);
或者,如果您是一个懒惰的人:
Or if you are a lazy person:
LogManager.Setup().SetupSerialization(s =>
s.RegisterObjectTransformation<GetEntityViewRequest>(obj =>
return Newtonsoft.Json.Linq.JToken.FromObject(obj) // Lazy and slow
)
);
这篇关于如何使用NLog序列化对象字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!