Pull to refresh

Просмотр запросов к веб серверу apache в реальном времени

Reading time 4 min
Views 20K
Нагрузка на сервер является важным звеном администрирования веб сервера, отслеживание запросов помогает быстро искать ошибочные запросы и устранять их раньше чем они вернуться к вам со статистикой вебмастера. По умолчанию в конфигурационном файле веб сервера апаче закоментрировано определение хоста в dns что в свою очередь еще больше усложняет понимание того, что приходит на сайте. Упростить все это удалось написанием скрипта отображающего все запросы к веб серверу в режиме реального времени. Сохраняя несколько сотен запросов удалось посчитать время загрузки. Это процент от реально прошедшего времени суммы времени потраченных на вывод ресурсов. Удобный вывод времени затраченного на выполнение каждой страницы сайта стал незаменим в поиске слабых мест. Небольшой массив со списком шаблонов поисковых систем позволил выделить их отдельным цветом в ленте запросов.

Запускается вывод с использованием консоли линукс пробросом по ssh вывода из логов. Плюсом стала минимальная нагрузка при этом на сервер, так как все вычисления происходят на локальной странице. Помогает в подсчетах небольшой php скрипт на вход которого поступает вывод данных из /var/log/apache2/access.log который в свое время подсвечивает важные части лога яркой подсветкой.

К сожалению стандартных уровней логирования подходящих под мои условия я не нашел, В моем случае важным параметром было имя хоста куда приходит запрос, но параметр %V который отвечает за вывод полного имени хоста в стандартных настройках отсутствовал. Пришлось дописать нужные параметры к common

LogFormat "%h %V %l %u %t \"%r\" %>s %O %D" common

Важно видеть в подобной ленте ботов, эту задачу помогла решить установка вывода в лог ДНС имени клиента. Эта настройка также выключена по умолчанию в конфигурационном файле.

HostnameLookups On

Сам скрипт представляет из себя небольшой php файл который разбирает все входящие на него данные по частям и подсвечивает обрабатывает важное для дальнейшего вывода. Выглядит это следующим образом. В целях безопасности все локальные хосты и адреса в видео заменены. Дополнительно возможно будет удобно внести в список интересных адресов важные для вас страницы. Скрипт подсветит эти адреса в ленте запросов. На видео во втором параметром выводится среднее количество запросов в секунду, третьим время затраченное на выдачу ресурсов с учетом последних тысячи запросов.



Ну и сам скрипт который отображает данный вывод.

/usr/local/bin/log.php

<?php

$colors = array(
	"200"=>"[0;32m", "404"=>"[1;31m", "410"=>"[0;31m", "403"=>"[0;91m", "301"=>"[1;33m", "302"=>"[1;36m", "304"=>"[1;36m",
); # Цвета статусов
$bots = array("localhost", "googlebot", "yandex", "spider", "ahrefs", "mail.ru", "bot"); # Шаблон имен ботов, отображается более темным

$url = ["login", "admin"]; # Интересующие адреса будут подсвечиваться в ленте

require "/home/mpak2/www/idna_convert.class.inc";
$idna = new idna_convert();
$in = fopen('php://stdin', 'r');
$tm = []; $t = microtime(true); $nn = 0; $microtime = microtime(true);
while($str = fgets($in)){
	if(!$ar = explode(" ", $str)){ print_r("Ошибка формирования массива элементов");
	}elseif(!$n = number_format($nt = (100*(count($tm)-1)+($nn%100))/(microtime(true)-$t), 2)){ print_r("Ошибка форматирования времени генерации ресурса");
	}elseif(!($percent = number_format((array_sum(array_column($tm, 'msec'))/1e6)/(microtime(true)-$t)*100, 2)) & false){ print_r("Ошибка вычисления процента загрузки");
	}elseif(!$mtime = $ar[11]/1e6){ print_r("Ошибка вычисления время обработки ресурса");
	}elseif(!$mtm = (($_tm = number_format($mtime, 3)) > 1 ? "\e[1;31m{$_tm}\e[0m" : $_tm)){ print_r("Ошибка форматирования микровремени");
	}elseif(!$uri = urldecode($ar[7])){ mpre("Ошибка адрес не определен");
	}elseif(!$uri = (array_filter(array_map(function($u) use($uri){ return strpos($uri, $u); }, $url)) ? "\e[1;37m". urldecode($ar[7]). "\e[0m" : urldecode($ar[7]))){ print_r("Локальный адрес не установлен");
#	}elseif(!$uri = "/какой-то/адрес"){ mpre("Замена адреса");
	}elseif(!$status = (array_key_exists($ar[9], $colors) ? "\e{$colors[$ar[9]]}{$ar[9]}\e[0m" : $ar[9])){ print_r("Ошибка раскрашивания статуса");
	}elseif(!$host = "\e[1;34m". $idna->decode($ar[1]). "\e[0m"){ print_r("Ошибка определения хоста запроса");
#	}elseif(!$host = "хабра-хабр.рф"){ print_r("Замена имени хоста на звездочки");
	}elseif(!$bot = ((array_filter(array_map(function($b) use($ar){ return (strpos($ar[0], $b) !== false ? $b : false); }, $bots))) ? "\e[1;35m{$ar[0]}\e[0m" : "\e[1;32m{$ar[0]}\e[0m")){ print_r("Ошибка определения бота");
	}elseif(!$size = number_format($ar[10]/1024, 2). "КБ"){ print_r("Ошибка определения размера запроса");
	}else{// print_r($ar);
		if(($nn++ % 100) == 0){
			array_unshift($tm, ['msec'=>0, 'microtime'=>microtime(true)]);
			if(count($tm) > 10){
				$t = array_pop($tm)['microtime'];
			}
		} if(!($nn % 1000) && ($cmd = "echo '". strtr($n, ['.'=>' ']). "' | festival --tts --language russian &")){
			passthru($cmd);
		} $tm[0]['msec'] += $ar[10];

		passthru("echo '{$nn} {$n} {$percent}% {$mtm}c {$status} http://{$host}{$uri} ({$bot}) {$size}'");
	}
};

Запускается командой: ssh root@хабра-хабр.рф 'tail -f /var/log/apache2/access.log' | php -f /usr/local/bin/log.php
Tags:
Hubs:
+4
Comments 27
Comments Comments 27

Articles