2016-10-20 7 views
1

Я тестирую Serilog и имею некоторые названия полей проблем.Имена полей Serilog для свойств, не используемых в шаблоне сообщений

Я хочу добавить запись журнала с одним полем, включенным в шаблон сообщения, и другими полями, которые просто хранятся в журнале для запроса.

Я хотел бы сделать что-то простое, как это:

logger.Debug("Recalculation performed for operation {OperationId}", 
       operationId, operationTypeId, otherId, anotherId); 

Но это приводит к именам полей не было дано понятные имена, потому что они не находятся в шаблоне сообщения:

{ 
    "@timestamp":"2016-10-20T16:57:02.0623798+01:00", 
    "level":"Debug", 
    "messageTemplate":"Recalculation performed for operation {OperationId}", 
    "fields":{ 
     "OperationId":1024, 
     "__1":16, 
     "__2":32, 
     "__3":256, 
     "SourceContext":"SerilogTest.Worker" 
    } 
} 

I знаю, что я могу поместить все поля в класс и использовать метод ForContext для их включения в запись в журнале:

internal class OperationData 
{ 
    public int OperationId { get; set; } 

    public int OperationTypeId { get; set; } 

    public int OtherId { get; set; } 

    public int AnotherId { get; set; } 
} 

var operationData = new OperationData 
       { 
        OperationId = 1024, 
        OperationTypeId = 16, 
        OtherId = 32, 
        AnotherId = 256 
       }; 

var operationLogger = logger.ForContext("OperationData", 
         operationData, destructureObjects: true); 
operationLogger.Debug("Recalculation performed for operation {OperationId}", 
         operationData.OperationId); 

Этот вид получает меня результат я ищу:

{ 
    "@timestamp":"2016-10-20T18:00:35.4956991+01:00", 
    "level":"Debug", 
    "messageTemplate":"Recalculation performed for operation {OperationId}", 
    "fields":{ 
     "OperationId":1024, 
     "OperationData":{ 
     "_typeTag":"RecalulationResult", 
     "OperationId":1024, 
     "OperationTypeId":16, 
     "OtherId":32, 
     "AnotherId":256 
     }, 
     "SourceContext":"SerilogTest.Worker" 
    } 
} 

НО, похоже, много усилий, чтобы пройти только, чтобы иметь дружественные имена полей. Я должен создать новый экземпляр журнала, иметь тип, чтобы включить все соответствующие поля для сообщения журнала, а затем сделать журнал. Есть ли более простой способ присвоения имен этим полям?

ответ

2

Анонимные типы добиться того, что у вас есть выше с гораздо меньшим количеством кода:

logger 
    .ForContext("Operation", new {operationTypeId, otherId, anotherId}, true) 
    .Debug("Recalculation performed for operation {OperationId}", operationId); 

или, альтернативно, в том числе все, что в случае:

logger.Debug("Recalculation performed for operation {@Operation}", new { 
     Id = operationId, TypeId = operationTypeId, OtherId = otherId, 
     AnotherId = anotherId 
    }); 

Если вы найдете там много сообщений в которые вы хотите включить в одни и те же свойства, вам может быть лучше отталкивать их на LogContext:

using (LogContext.PushProperty("OperationId", operationId)) 
{ 
    logger.Debug("Recalculation performed"); 

    // ...etc... 

    logger.Debug("Something else"); 
} 

В этом случае оба события будут связаны с ними OperationId. Вы можете переместить несколько свойств в контекст журнала. Просто не забудьте добавить Enrich.FromLogContext() к своим LoggerConfiguration, чтобы использовать этот стиль.

+0

Я предположил, что анонимные типы не будут работать, поскольку Serilog должен использовать отражение, а отражение не хорошо работает с анонимными типами. Я попробую. –

+0

@GlenThomas Reflection работает с анонимными типами. Какие конкретные проблемы существуют? – user2864740

+0

@ user2864740 У меня были проблемы в прошлом с использованием таких библиотек, как Dapper с анонимными типами. Возможно, это была более ранняя версия .NET Framework, но я уверен, что метаданные свойств типа недоступны или уменьшены, когда тип анонимный. –