Как сериализовать поля объекта с помощью NLog? - PullRequest
0 голосов
/ 08 апреля 2020

Я тестирую новое структурированное ведение журнала , но на самом деле не понимаю это правильно.

У меня есть это в моем 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);
        }

Вывод выглядит примерно так:

{"Operation": "OperationName", "PersonId": 1, "ComputerName": " MyComputername "," MachineName ":" MyMachinename "," Parameters ": {" LocationKeyList ": []," MyObjectIdList ": []," RolList ": []}}

Мне бы хотелось Параметры, чтобы получить сериализацию вместо просто showint [], чтобы я мог видеть все параметры работы службы. Параметр представляет собой сложный тип с dataContract (WCF).

Существует ли простой способ заставить параметры работать со структурными данными.

Повторные теги

Update1

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());

результат:

ientMachineName: \ "MyComputer \ "Имя_сервера: \" MyComputer \ "Параметр: [\" MyApp.ServiceContracts.GetEntityViewRequest \ "]", "Метка времени": "2020-04-08T23: 30: 59.7725147Z", "Продолжительность": "00:00: 00.0009930 "," Operation ":" GetReferenceData "," PersonId ": 1," ComputerName ":" SE-MyCom "," MachineName ":" SE-MyCom "," Parameters ": [" MyApp.ServiceContracts.GetEntityViewRequest "] }

{"time": "2020-04-09 01: 31: 00.3637", "level": "Info", "message": "2020-04-09 01:31:00 - Продолжительность : 00: 00: 00.5594936 Операция: \ "GetExternaAnrop \" PersonId: 1 ClientMachineName: \ "MyComputer \" Имя_сервера: \ "MyComputer \" Параметр: [{\ \ PlaceringKeyList \ ": [], \" ArbetsstalleIdList \ ": [ ], \ "RollList \": []}] ", TimeStamp": "2020-04-08T 23: 31: 00.363752Z "," Duration ":" 00: 00: 00.5594936 "," Operation ":" GetExternaAnrop "," PersonId ": 1," ComputerName ":" SE-MyCom "," MachineName ":" SE -MyCom "," Parameters ": [{" PlaceringKeyList ": []," ArbetsstalleIdList ": []," RollList ": []}]}

Update2

У меня есть метод обслуживания, который выглядит следующим образом:

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 имеют набор enum.

Вывод NLog выглядит следующим образом:

{"time": "2020-04-12 19: 27: 55.6690", "level" : "Info", "message": "2020-04-12 19:27:55 - Продолжительность: 00: 00: 00.0034730 Операция: \" GetReferenceData \ "PersonId: 1 ClientMachineName: \" MyComputer \ "Имя сервера: \" MyComputer \ "Param: [\" Orbit.ServiceContracts.GetEntityViewRequest \ "]", TimeStamp ":" 2020-04-12T17: 27: 55.6690745Z "," Duration ":" 00: 00: 00.0034730 "," Operation ": "GetReferenceData", "PersonId": 1, "ComputerName": "SE-MyCom", "MachineName": "SE-MyCom", "Parameters": ["Orbit.ServiceContracts.GetEntityViewRequest"]}

То есть, даже если класс не сложный, он все равно не печатает содержимое в NLog?

1 Ответ

0 голосов
/ 08 апреля 2020

Для JsonLayout есть важный параметр, который называется MaxRecursionLimit (по умолчанию = 0 до прибытия NLog v5):

https://github.com/nlog/nlog/wiki/JsonLayout

Так что вы можете сделать это :

<layout xsi:type="JsonLayout" includeAllProperties="true" maxRecursionLimit="10">
              <attribute name="time" layout="${longdate}" />
              <attribute name="level" layout="${level}"/>
              <attribute name="message" layout="${message}" />
</layout>

Возможно, вы захотите изменить свои параметры следующим образом:

if (args != null)
{
    text += "Params:{@Parameters} ";
    parameters.Add(args);
}

По умолчанию NLog не сериализует поля объекта, а только свойства объекта. Если поля обязательны для заполнения, вы можете настроить пользовательское отражение с помощью NLog 4.7:

LogManager.Setup().SetupSerialization(s =>
   s.RegisterObjectTransformation<GetEntityViewResponse>(obj => new {
      EntityViewKeys = obj.EntityViewKeys,
      MyList = obj.MyList,
   })
);

Или, если вы ленивый человек:

LogManager.Setup().SetupSerialization(s =>
   s.RegisterObjectTransformation<GetEntityViewRequest>(obj => 
       return Newtonsoft.Json.Linq.JToken.FromObject(obj) // Lazy and slow
   )
);
...