Мы стремимся к лучшей централизации, структурированию и поиску в наших журналах с использованием стека ELK. В настоящее время мы регистрируемся в таблице базы данных, и у нас есть EventLog
POCO, который захватывает поля, необходимые для заполнения этих строк. Нашей первой попыткой получить эти данные в Elasticsearch было простое ведение журнала событий через Serilog следующим образом:
EventLog eventLog = ...;
log.ForContext("EventLog", eventLog, true).Write(eventLog.EventMessage);
В результате получается документ типа «logevent» Serilog с «полем», которое содержит нашу пользовательскую структуру и дает нам большую часть того, что мы хотим:
{
"_index": "logstash-2019.03.14",
"_type": "logevent",
"_id": "p_amfGkBaphWeJXGjjSW",
"_version": 1,
"_score": null,
"_source": {
"@timestamp": "2019-03-14T09:41:21.6924251-05:00",
"level": "Information",
"messageTemplate": "blah",
"message": "blah",
"fields": {
"EventLog": {
"_typeTag": "EventLog",
"EventMessage": "blah",
"EventId": 3112,
...
Kibana позволяет нам выполнять специальный поиск наших журналов по полям в нашей пользовательской структуре, и мы уже достаточно счастливы.
Теперь мы хотим программно выполнить поиск в наших журналах, и мы ищем NEST для этого, но мы не можем точно определить правильные заклинания. ElasticClient.Search<T>
кажется нам тем, что нам нужно, мы не уверены, что нужно T
, и как NEST интерпретирует критерии поиска или возвращенные данные.
Что мы пробовали:
client.Search<EventLog>(); // returns zero results
client.Search<Serilog.Events.LogEvent>(); // throws: Error converting string to Serilog.Events.MessageTemplate
client.Search<EventLog>(s => s.Type("logevent")); // returns results!, but the EventLog objects are all empty (properties all have default values)
Единственный звонок, который, кажется, приближает нас к чему-либо, это:
client.Search<Object>(s => s.Type("logevent")); // returns the raw JSON source of each log entry
Итак, мы чувствуем, что упускаем что-то простое и фундаментальное здесь. Все документы NEST основаны на типе Project
, который индексируется непосредственно в Elasticsearch, но что нам нужно сделать, чтобы иметь возможность извлекать и запрашивать наши пользовательские структуры, которые мы добавляем в журнал, используя ForContext
? * Serilog? 1022 *
ОБНОВЛЕНИЕ: Похоже, нам может понадобиться создать отдельный набор POCO, которые повторяют структуру события Serilog, например:
private class DummyFields
{
public EventLog EventLog { get; set; }
}
private class Dummy
{
public DummyFields Fields { get; set; }
}
Запросы на Dummy
в NEST действительно дают нам доступ к нашей внутренней структуре, но, похоже, должен быть лучший способ сделать это ...
ОБНОВЛЕНИЕ 2:
Мы в порядке с реализацией POCO только для сопоставления ответов на запросы, но теперь кажется, что есть другая проблема с сопоставлением полей внутри нашей вложенной структуры:
client.Search<Dummy>(s => s
.AllTypes()
.Query(q => q
.Match(t => t
.Field(f => f.Message).Query("blah"); // returns some results
client.Search<Dummy>(s => s
.AllTypes()
.Query(q => q
.Match(t => t
.Field(f => f.Fields.EventLog.EventMessage).Query("blah"); // returns zero results
Почему второй запрос не "видит" наше вложенное сообщение о событии?
ОБНОВЛЕНИЕ 3:
Любопытно, что это также работает:
client.Search<Dummy>(s => s
.AllTypes()
.Query(q => q
.Match(t => t
.Field(f => new Field("fields.EventLog.EventMessage")).Query("blah");
Так что похоже, что NEST просто не соответствует типобезопасной версии вложенного поля. Очевидно, мы бы предпочли не полагаться на магические нити здесь ...
ОБНОВЛЕНИЕ 4:
Я включил ведение журнала запросов в ES и увидел, что между запросами литералов и выражений есть разница в регистре. Литеральный запрос (со свойствами PascalCased) рассматривается ES как Pascal и находит документы, в то время как безопасное от типа выражение преобразуется в camelCase ("fields.eventLog.eventMessage") и ничего не соответствует. Конечно же, если я сделаю запрос с буквенным путем поля camelCased, я тоже ничего не получу.
Как мне сказать NEST, чтобы использовать правильную чувствительность к регистру?