в debian, monitoring, nginx

Пишем свой плагин для munin — nginx request time

Munin nginx_request_time
Давайте разберемся с созданием плагина для munin, который в красивой и понятной форме даст нам представление о времени обработки запросов nginx’ом.

Итак, на графике нам нужно видеть количество запросов (в процентах от общего числа), время обработки которых:

  • дольше 1 секунды;
  • от 100 милисекунд до 1 секунды;
  • от 50 до 100 милисекунд;
  • менее 50 милисекунд;

Почему именно плагин для munin? Во-первых, это просто и понятно — можно написать плагин, потратив минимум времени на чтение документации. Во-вторых, получение данных от всех плагинов сервером munin происходит каждые 5 минут (по умолчанию). В-третьих, ротация логов nginx’а происходит также каждые 5 минут (в моем случае).

Алгоритм действий следующий:

  • открываем на редактирование конфиг /etc/nginx/nginx.conf:
nano /etc/nginx/nginx.conf
  • в секции http находим строку log_format и добавляем в нее параметр $request_time:
log_format  main  '$remote_addr $remote_user [$time_local] "$request" $status $request_time $bytes_sent '
                          '"$http_referer" "$http_user_agent"';

Примечание. $request_time — время обработки запроса в секундах с точностью до миллисекунд; время, прошедшее с момента чтения первых байт от клиента до момента записи в лог после отправки последних байт клиенту.

  • перечитываем конфигурацию nginx’а:
nginx -s reload

После этих действий /var/log/nginx/access.log должен выгдядеть примерно так:

...
31.43.5.37 - [20/Feb/2014:10:54:04 +0200] "GET /_data/search_categories.php?search=%D0%BD HTTP/1.1" 200 0.016 311 "-" "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16"
...

Примечание. Именно значение 0.016 в примере из лога — то, с чем мы будем работать дальше

Далее непосредственно написание плагина для munin:

  • переходим в каталог /etc/munin/plugins:
cd /etc/munin/plugins
  • создаем файл nginx_request_time:
nano nginx_request_time
  • вставляем следующий код:
#!/usr/bin/php
<?php
if ($argv[1] == 'config')
{
  echo "graph_category nginx
  graph_title Nginx request time
  graph_vlabel %
  graph_scale no
  graph_args --base 1000 -r --lower-limit 0 --upper-limit 100
  t0.label less 50ms
  t0.draw AREA
  t0.type GAUGE
  t0.min 0
  t1.label less 100ms
  t1.draw STACK
  t1.type GAUGE
  t1.min 0
  t2.label less 1s
  t2.draw STACK
  t2.type GAUGE
  t2.min 0
  t3.label more 1s
  t3.draw STACK
  t3.type GAUGE
  t3.min 0
  ";
}
else
{
  $result    = `grep '\" 200 ' /var/log/nginx/access.log.0 | awk '{print $9;}'`;
  $resultArray = explode("\n", $result);
  $return    = array(0, 0, 0, 0);
  if (count($resultArray))
  {
    foreach ($resultArray as $one)
    {
      if ($one < 0.05)
      {
        $return[0] ++;
      }
      elseif ($one < 0.1)
      {
        $return[1] ++;
      }
      elseif ($one < 1)
      {
        $return[2] ++;
      }
      else
      {
        $return[3] ++;
      }
    }
  }
  $all_request = array_sum($return);
  foreach ($return as $key => $one)
  {
    $value = round(($one / $all_request * 100), 4);
    echo 't'.$key.'.value '.$value."\n";
  }
}
  • меняем права доступа для nginx_request_time:
chmod 755 nginx_request_time
  • переходим в каталог /etc/munin/plugin-conf.d:
cd /etc/munin/plugin-conf.d
  • в файле munin-node находим (или создаем) секцию nginx*, где в качестве пользователя укажем root:
...
[nginx*]
user root
...
  • перезапускаем демон munin-node:
/etc/init.d/munin-node restart

Через некоторое время вы сможете увидеть результаты проделанной работы в виде графика:

nginx request time

График с примером работы плагина nginx request time

Добавить комментарий

  1. Евгений подскажите, если на сервере несколько доменов и у каждого домена свой лог, как правильно использовать этот плагин?
    Т.е. плагин использовать только для конкретного домена, или можно как-то сложить логи всех доменов?
    PS. Я понимаю, что это только пример, но все же.

    • В своем примере я рассматривал только один домен, если вам нужно логи нескольких доменов объединить и выводить суммарную информацию — попробуйте покрутить строку
      $result = `grep '\" 200 ' /var/log/nginx/access.log.0 | awk '{print $9;}'`;

      • А если доменов десятки, то наверное лучше через массив сделать.
        Я к сожалению не силен в программировании.
        Кстати, у меня этот пример почему-то так и не заработал, не создается .rrd файл.
        В лог информация пишется в том же формате, что и в примере, единственное только путь к логу другой, и я его конечно заменил на свой.
        А так, подключаю сторонние плагины и все работает, так что минимальный опыт подключения у меня есть.
        Даже не знаю в чем может быть причина.