ELK

Как искать в Kibana уже написано (1, 2, 3, 4, 5, 6) но для себя еще коротко:

ОписаниеSQLKibanaНайдет строкуНе найдет строку
неточный поиск во всех поляхнет аналога"value1"- MY value1 bar- MY bar
неточный поиск по частинет аналога- field:"value1"
- field:/value1/
- MY value1 bar
- MY value1-bar
- MYvalue1 bar
- MYvalue1Bar
неточный поиск по полю слеваfield like '%value1'field: *value1- MYvalue1
- MYvalue1 bar
- MYvalue1-bar
- MYvalue1Bar
неточный поиск по полю,
более сложный способ это
использовать регулярку (о
ней смотрите ниже)
field like '%value1%'field: *value1*- MYvalue1
- MYvalue1 bar
- MYvalue1-bar
- MYvalue1Bar
- MY bar
поиск по двум значениям
(раньше работало,
в 7-ой версии нет)
field like '%value1%' OR
field like '%value2%'
field: "value1, value2" - MYvalue1
- MYvalue1 bar
точный поиск по полюfield like 'value1'field.keyword: "value1"- value1все остальное
поиск по диапазону: field >= 500
field BETWEEN 500 AND X
field: [500 TO *]
field: {500 TO *}
  
наличие поля или любой записиfield like '%'field: *все строки 

Поиск с точкой:

{
  "query": {
    "wildcard": {
      "request.keyword": "*.json*"
    }
  }
}

как видите, не смотря на то, что строки при индексировании обрабатываются анализатором (Analyzer), который разбирает строку на части, например www.google.com станет "www, google, com", в поле keyword хранит оригинал, по которому можно "грепать".

Поиск сразу по двум значениям (one OR two):

{
  "query": {
    "bool": {
      "should": [
        {
          "wildcard": {
            "request.keyword": "*.json*"
          }
        },
        {
          "wildcard": {
            "request.keyword": "*/api/*"
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

Поиск по регулярке:

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "regexp": {
      "user.id": {
        "value": "k.*y",
        "flags": "ALL",
        "case_insensitive": true,
        "max_determinized_states": 10000,
        "rewrite": "constant_score"
      }
    }
  }
}
'

* в версии 6.8 флаг невалидно указывать: "case_insensitive": true,

Отрицание ненужных уровней и ошибок:

ELK

Фильтр по файлу делается так:

ELK

Более сложные параметры поиска

Поиск по float >= 0.5

{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "request_time": {
              "gte": "0.5"
            }
          }
        }
      ]
    }
  }
}

Поиск по началу строки (префикс): 1 - 2 - 3

{
  "query": {
    "match_phrase_prefix": {
      "api_method": {
        "query": "seo"
      }
    }
  }
}

Визуализации

Количество записей в каждом лог-файле за последние 4 часа: 

ELK

Фильтр, который группирует по типу ошибок:

ELK

Визуализация по кол-ву запросов:

ELK

Http статусы

p.s. к сожалению с значением float, так не получится (Kibana будет показывать неправильные данные), попробуйте просто использовать перцентели.

Время запроса максимальное и среднее

Перцентиль

Еще несколько примеров

Построение графика по 5 наиболее запрашиваемым страницам на сайте (визуализация Visual Builder):

а индекс и параметры выборки указываются на вкладке Panel options:

Список наиболее часто запрашиваемых адресов (с информацией о кол-ве запросов, максимальному и среднему времени выполнения запроса, а так же по 95 и 97 перцентелям).

Дашборд

ELK

Чтобы добавить на дашборд список записей из которых построены графики, нужно при добавлении визуализации выбрать вкладку Saved Search (конечно предварительно нужно такой сохранить, а сохранятся он на странице Discover и минимально может состоять только из выбора индекса): 

Оповещения

Есть и нотификации, для этого компания Elasticsearch предлагает инструменты Watcher и Observability.

Требования к логированию

Логировать можно за большее кол-во дней (по возможности 2 недели, чтобы отслеживать тенденцию).

Как просматривать логи (фильтрация):
a) выбрал название сервиса ( project_name, если говорить о веб-приложении, то это http host )
б) выбрал source_name ( все или на выбор: https://www.php.net/manual/ru/function.php-sapi-name.php#refsect1-function.php-sapi-name-returnvalues )
* логи веб-сервиса должны использовать source_name возвращаемое пхп функцией php_sapi_name
в) выбрал уровень логирования (level_name)
* логи веб-сервиса должны использовать отличное значение от level_name используемое в приложении или виртуальной машине, например есть:
- access статики
- access пхп-фпм

Все виды логов должны реализовывать единый формат:

{
 "project_name": "wosy",
 "source_name": "cli",
 "level_name": "ERROR",
 "message": "phpErrorHandler error",
 "datetime": {
   "date": "2018-07-13 11:35:58.248318",
   "timezone_type": 3,
   "timezone": "Europe/Moscow"
 },
 Дополнительные данные, которые могут отсутсвовать:
 "http_request_id": "490d25d", -- часто используется для связывания запросов в микросервисах
 "channel": "time_balance", -- часто используется в монологе
 "context": { -- место в проекте, которое вызвало запись в лог
  "code": 123,
   "message": "Call to a member function verify_phone() on null",
   "file": "/var/www/builds/api2-9fd503b71cf911e6621af710e077e1bf88760935-20180710T102106/app/src/Customer/V1/VerifyResource.php",
   "line": 28,
   "trace": "any string"
 },
 "extra": { -- остальные данные, могут присутствовать в логах, но не обязаны индексироваться
   "http_method": "GET",
   "http_host": "test-api2.gemotest.ru",
   "url": "/customer/v2/verify?phone=79258277651",
   "referrer": null,
   "function": "MyFunction",
   "session": {
     "id": "fkajsldfkjalsdhfasldkfjaFHdksjlfsd",
     "user_id": 54546
   }
   "server_ip": "10.128.71.100",
   "remote_addr": "10.128.71.200",
 }
}

Важно: регламентировать глубину вложенности логов - обычно достаточно глубины равной трем (остальное обрезается).

Напомню, что обычно php-приложение состоит из:
- логи приложения (например monolog в формате json)
- логов php (ошибки в самом php)

Статьи по теме:

https://habr.com/ru/post/345968/

Вот в таком виде приходят логи из Haproxy:

{
  "_index": "logstash-haproxylog-2019.08.20",
  "_type": "doc",
  "_id": "mw4QrmwBHMig4HowlNn0",
  "_version": 1,
  "_score": null,
  "_source": {
    "source": "/var/log/haproxy/haproxy.log",
    "prospector": {
      "type": "log"
    },
    "time_queue": 0,
    "beconn": 0,
    "srvconn": 0,
    "syslog_server": "sl-app-13",
    "type": "haproxylog",
    "captured_response_cookie": "-",
    "frontend_name": "ft_web~",
    "offset": 1591510441,
    "@version": "1",
    "request_header_accept_language": "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7",
    "termination_state": "sH--",
    "server_name": "sl-sky-03",
    "time_backend_response": -1,
    "time_duration": 240000,
    "actconn": 693,
    "backend_name": "office2",
    "http_request": "/index.php?r=gemopay/Purchase/PaymentForm&model_id=51782369&module_type=lis&model_type=order",
    "syslog_timestamp": "Aug 20 11:06:56",
    "bytes_read": 195,
    "tags": [
      "beats_input_codec_plain_applied",
      "filter.grok.haproxy.log"
    ],
    "retries": 0,
    "srv_queue": 0,
    "http_status_code": 504,
    "request_header_user_agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36",
    "http_version": "1.1",
    "host": "sl-app-13",
    "request_header_referer": "https://office2.gemotest.ru/inputOrder/inputMain_test.php?oid=51782369",
    "client_port": 4956,
    "@timestamp": "2019-08-20T08:02:56.330Z",
    "client_ip": "87.117.56.253",
    "time_backend_connect": 0,
    "captured_request_cookie": "-",
    "feconn": 693,
    "backend_queue": 0,
    "http_verb": "GET",
    "time_request": 0,
    "beat": {
      "version": "6.2.3",
      "name": "sl-app-13",
      "hostname": "sl-app-13"
    },
    "request_header_host": "office2.gemotest.ru"
  },
  "fields": {
    "@timestamp": [
      "2019-08-20T08:02:56.330Z"
    ]
  },
  "highlight": {
    "request_header_host": [
      "office2.@kibana-highlighted-field@gemotest.ru@/kibana-highlighted-field@"
    ],
    "request_header_referer": [
      "https://office2.@kibana-highlighted-field@gemotest.ru@/kibana-highlighted-field@/inputOrder/inputMain_test.php?oid=51782369"
    ]
  },
  "sort": [
    1566288176330
  ]
}

Из mono.log :

{
  "_index": "logstash-%{[type]}-2019.08.21",
  "_type": "doc",
  "_id": "E2Q5s2wBHMig4Howd7LG",
  "_version": 1,
  "_score": null,
  "_source": {
    "@timestamp": "2019-08-21T08:09:35.789Z",
    "source": "/var/log/php-app/mono.log",
    "prospector": {
      "type": "log"
    },
    "beat": {
      "version": "6.4.3",
      "name": "sl-sky-02",
      "hostname": "sl-sky-02"
    },
    "host": {
      "name": "sl-sky-02"
    },
    "offset": 42778529,
    "tags": [
      "beats_input_codec_plain_applied",
      "_grokparsefailure"
    ],
    "@version": "1",
    "message": "{\"message\":\"Sending message\",\"context\":{\"classMethod\":\"Gs\\\\Gemopay\\\\Handler\\\\Handler::request\",\"requestId\":0},\"level\":300,\"level_name\":\"WARNING\",\"channel\":\"gemopay\",\"datetime\":{\"date\":\"2019-08-21 11:09:35.740972\",\"timezone_type\":3,\"timezone\":\"Europe/Moscow\"},\"extra\":{\"session\":{\"id\":\"4diuompce3bv26eilknn0d6bur\",\"user_id\":4000746},\"trace\":\"#11 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/src/Gemopay/Handler/Handler.php(310): Monolog\\\\Logger->warning('Sending message', Array)\\n#10 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/src/Gemopay/Handler/FiscalPrinterHandler.php(50): Gs\\\\Gemopay\\\\Handler\\\\Handler->request('Status', Array, 15)\\n#9 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/src/Gemopay/Service/Payment/FiscalPrinterStatusFactory.php(38): Gs\\\\Gemopay\\\\Handler\\\\FiscalPrinterHandler->Status()\\n#8 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/src/Gemopay/Service/Payment/PaymentService.php(211): Gs\\\\Gemopay\\\\Service\\\\Payment\\\\FiscalPrinterStatusFactory->create('0617740006060912')\\n#7 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/www/protected/modules/gemopay/controllers/PurchaseController.php(33): Gs\\\\Gemopay\\\\Service\\\\Payment\\\\PaymentService->initByGemopay('0617740006060912', 4000746, '50091', '50091_ЛОКАЛМЕДСЕРВИС_Московская область_Балашиха_янтарный_2', 'lis', '51785947', 'order', 8)\\n#6 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/vendor/yiisoft/yii/framework/web/CController.php(306): PurchaseController->beforeAction(CInlineAction)\\n#5 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/vendor/yiisoft/yii/framework/web/CController.php(286): CController->runAction(CInlineAction)\\n#4 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/vendor/yiisoft/yii/framework/web/CController.php(265): CController->runActionWithFilters(CInlineAction, Array)\\n#3 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/vendor/yiisoft/yii/framework/web/CWebApplication.php(282): CController->run('PaymentForm')\\n#2 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/vendor/yiisoft/yii/framework/web/CWebApplication.php(141): CWebApplication->runController('gemopay/Purchase/PaymentForm')\\n#1 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/vendor/yiisoft/yii/framework/base/CApplication.php(185): CWebApplication->processRequest()\\n#0 /var/www/builds/gemosystem-daa29b362d0c3b65faed5b075d4ef9ae1f774f3f-20190814T155407/www/index.php(17): CApplication->run()\\n\",\"url\":\"/index.php?r=gemopay/Purchase/PaymentForm&model_id=51785947&module_type=lis&model_type=order\",\"ip\":\"185.13.112.232\",\"http_method\":\"GET\",\"server\":\"office.gemotest.ru\",\"referrer\":\"https://office.gemotest.ru/inputOrder/inputMain_test.php?oid=51785947\",\"uid\":\"2b753f0\"}}",
    "input": {
      "type": "log"
    }
  },
  "fields": {
    "@timestamp": [
      "2019-08-21T08:09:35.789Z"
    ]
  },
  "highlight": {
    "source.keyword": [
      "@kibana-highlighted-field@/var/log/php-app/mono.log@/kibana-highlighted-field@"
    ]
  },
  "sort": [
    1566374975789
  ]
}

Elasticsearch as a Time Series Data Store : 1 - 2


12.12.2010 10:02