<?php
/**
* php-fpm 慢日志解析监控报警
* User: liuzimu1995
* Date: 2021/4/7
* Time: 22:15
*/
// 处理参数
$fpmLogPath = getParam('-path', $argv);
// 处理本分钟的内容
if (empty($fpmLogPath)) {
echo "请指定日志文件地址 example : -path=/home/worker/data/php/logs/php-fpm.log";
exit;
}
// 分割日志tail -n 5000 /home/worker/data/php/logs/php-fpm.log | grep '$time' > /runtime/phpslow.log
// 这里处理两分钟前的,怕日志延迟写入
$time = date('d-M-Y H:i', strtotime('-2minute'));
$path = '/runtime/phpslow.log';
echo "tail -n 5000 /home/worker/data/php/logs/php-fpm.log | grep '{$time}' > {$path}";
shell_exec("tail -n 5000 /home/worker/data/php/logs/php-fpm.log | grep '{$time}' > {$path}");
if (!is_file($path)) {
echo "文件地址不存在";
exit;
}
define("OUT_PATH", './phpslowlog/');
if (!is_dir(OUT_PATH)) {
mkdir(OUT_PATH, 0777);
}
// 一行行读取文件,将一次的结果写入到今天的输出配置中
$file = fopen($path, 'r');
if (!$file) {
echo "文件地址不存在";
exit;
}
$todayConfigName = OUT_PATH . 'out_' . date('Y-m-d') . '.php';
if (is_file($todayConfigName)) {
$toDayConfig = require_once $todayConfigName;
} else {
$toDayConfig = [];
}
$isSend = false;
while (!feof($file)) {
while (($buffer = fgets($file, 4096)) !== false) {
//处理buffer
$data = [];
if (strpos($buffer, 'seems busy') !== false) {
// echo $buffer . PHP_EOL;
// 解析php-fpm需要调优提示
$toDayConfig['fpmbusy'] = empty($toDayConfig['fpmbusy']) ? 1 : $toDayConfig['fpmbusy'] + 1;
} else {
// 解析慢接口
$data = [];
preg_match_all('/(?<=\()[^\)]+/', $buffer, $data);
if (empty($data[0])) {
continue;
}
list($route, $time) = $data[0];
preg_match('/(?<= )[^\"]+/', $route, $routeRet);
if (empty($routeRet[0])) {
continue;
}
$routeRet = parse_url($routeRet[0]);
if (empty($routeRet['query'])) {
continue;
}
$routeRet = explode('&', $routeRet['query']);
if (empty($routeRet[0])) {
continue;
}
$toDayConfig[$routeRet[0]]['count'] = empty($toDayConfig[$routeRet[0]]['count']) ? 1 : $toDayConfig[$routeRet[0]]['count'] + 1;
if ($toDayConfig[$routeRet[0]]['count'] % 120 == 0) {
// 每一千次发送提醒到我们的群
$isSend = true;
}
// 放入时长
$toDayConfig[$routeRet[0]]['time'] = $time;
}
}
}
fclose($file);
// 覆盖今日配置文件
file_put_contents($todayConfigName, "<?php
return " . var_export($toDayConfig, true) . ";");
// 实现发送到企业微信
if (true === $isSend) {
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$ip = '本地测试';
} else {
$ip = shell_exec("/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}' | grep -v 172.*.0.1");
}
$sendData[9999999999] = '<font color="warning">警告:</font>服务器{' . $ip . '}php慢日志告警TOP20,请及时处理~';
foreach ($toDayConfig as $key => $value) {
if ('fpmbusy' == $key) {
// 调优提示
$sendData[9999999998] = "*调优提示出现{$value}次,请查看是否需要调优fpm~*";
} else {
$sendData[$value['count']] = "> {$key},出现{$value['count']}次,时间{$value['time']}";
}
}
uksort($sendData, function ($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? 1 : -1;
});
$sendData = array_values($sendData);
$sendData = array_slice($sendData, 0, 20);
$param = [
'msgtype' => 'markdown',
'markdown' => [
'content' => implode(PHP_EOL, $sendData)
]
];
$context = stream_context_create(['http' => ['method' => 'POST', 'header' => "Content-Type: application/json\r\n", 'content' => $sendData = json_encode($param)]]);
//$ret = file_get_contents('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=', false, $context);
echo $ret;
}
/**
* 获取参数
* @param $key
* @param array $argv
* @return string
*/
function getParam($findKey, array $argv)
{
foreach ($argv as $value) {
$values = explode('=', $value);
list($key, $val) = $values;
if ($key == $findKey) {
return $val;
}
}
return '';
}
本文链接:
http://zimu.devorz.com/archives/5/