Logstash и вложенный JSON из Monlog; Почему массивы конвертируются в строку JSON? - PullRequest
0 голосов
/ 30 августа 2018

Я использую PHP с Monolog. Я выводлю журналы в файл JSON и использую Gelf для Logstash, который затем отправляет журналы в ElasticSearch.

Проблема в том, что я пропускаю объект extra в Кибане, и поле tags интерпретируется как строка вместо вложенного объекта.

Есть идеи, как убедить Logstash / Kibana, чтобы внутреннее поле JSON анализировалось как поля / объекты, а не как строка JSON?

Вот так это выглядит в Кибане.

{
   "_index":"logstash-2018.08.30",
   "_type":"doc",
   "_id":"TtHbiWUBc7g5w1yM8X6f",
   "_version":1,
   "_score":null,
   "_source":{
      "ctxt_task":"taskName",
      "@version":"1",
      "http_method":"GET",
      "user_agent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0",
      "level":6,
      "message":"Finished task",
      "tags":"{\"hostname\":\"28571f0dc7e1\",\"region\":\"eu-west-1\",\"environment\":\"local\",\"processUniqueId\":\"5b87a4d843c20\"}",
      "url":"/assets/Logo.jpg",
      "ctxt_controller":"ControllerName",
      "memory_usage":"4 MB",
      "referrer":"https://local.project.net/account/login",
      "facility":"logger",
      "memory_peak_usage":"4 MB",
      "ctxt_timeElapsed":0.05187487602233887,
      "@timestamp":"2018-08-30T08:03:37.386Z",
      "ip":"172.18.0.1",
      "ctxt_start":1535616217.33417,
      "type":"gelf",
      "host":"18571f0dc7e9",
      "source_host":"172.18.0.8",
      "server":"local.project.net",
      "ctxt_end":1535616217.386045,
      "version":"1.0"
   },
   "fields":{
      "@timestamp":[
         "2018-08-30T08:03:37.386Z"
      ]
   },
   "sort":[
      1535616217386
   ]
}

Мой журнал выглядит так:

{
   "message":"Finished task",
   "context":{
      "controller":"ControllerName",
      "task":"taskName",
      "timeElapsed":0.02964186668395996,
      "start":1535614742.840069,
      "end":1535614742.869711,
      "content":""
   },
   "level":200,
   "level_name":"INFO",
   "channel":"logger",
   "datetime":{
      "date":"2018-08-30 08:39:02.869850",
      "timezone_type":3,
      "timezone":"Europe/London"
   },
   "extra":{
      "memory_usage":"14 MB",
      "memory_peak_usage":"14 MB",
      "tags":{
         "hostname":"28571f0dc7e1",
         "region":"eu-west-1",
         "environment":"local",
         "processUniqueId":"5b879f16be3f1"
      }
   }
}

Мой logstash conf:

input {
    tcp {
        port => 5000
    }
    gelf {
        port => 12201
        type => gelf
        codec => "json"
    }
}

output {
    elasticsearch {
        hosts => "172.17.0.1:9201"
    }
}

Мой монологический конфиг:

$gelfTransport = new \Gelf\Transport\UdpTransport(LOG_GELF_HOST, LOG_GELF_PORT);
            $gelfPublisher = new \Gelf\Publisher($gelfTransport);
            $gelfHandler = new \Monolog\Handler\GelfHandler($gelfPublisher, static::$logVerbosity);
            $gelfHandler->setFormatter(new \Monolog\Formatter\GelfMessageFormatter());

            // This is to prevent application from failing if `GelfHandler` fails for some reason
            $ignoreErrorHandlers = new \Monolog\Handler\WhatFailureGroupHandler([
                $gelfHandler
            ]);
            $logger->pushHandler($ignoreErrorHandlers);

EDIT: Пока что я обнаружил, что это вызвано GelfMessageFormatter преобразованием массивов в JSON:

$val = is_scalar($val) || null === $val ? $val : $this->toJson($val);

Когда netcat используется вместе с вложенным JSON, например ::1010*

echo -n '{
"field": 1,
"nestedField1": {"nf1": 1.1, "nf2": 1.2, "2nestedfield":{"2nf1":1.11, "2nf2":1.12}}
}' | gzip -c | nc -u -w1 bomcheck-logstash 12201

тогда данные в Кибане выглядят нормально

1 Ответ

0 голосов
/ 30 августа 2018

Похоже, GELF не поддерживает вложенные структуры данных из коробки. Я решил использовать собственный плагин Logstash UDP:

input {
    udp {
        port => 12514
        codec => "json"
    }

}

вместе с Monolog LogstashFormatter

$connectionString = sprintf("udp://%s:%s", LOG_UDP_LOGSTASH_HOST, LOG_UDP_LOGSTASH_PORT);
$handler = new \Monolog\Handler\SocketHandler($connectionString);
$handler->setFormatter(new \Monolog\Formatter\LogstashFormatter('project', null, null, 'ctxt_', \Monolog\Formatter\LogstashFormatter::V1));
$logger->pushHandler($handler);

Вложенные данные правильно отображаются в Кибане.

...