*/
class StatisticService extends WORKERMAN\Core\SocketWorker
{
/**
* 判断包是否都到达
* @see Worker::dealInput()
*/
public function dealInput($recv_str)
{
return \WORKERMAN\Protocols\SimpleHttp::input($recv_str);
}
/**
* 处理业务逻辑 查询log 查询统计信息
* @see Worker::dealProcess()
*/
public function dealProcess($recv_str)
{
\WORKERMAN\Protocols\SimpleHttp::decode($recv_str);
$module = isset($_GET['module']) ? trim($_GET['module']) : '';
$interface = isset($_GET['interface']) ? trim($_GET['interface']) : '';
$start_time = isset($_GET['start_time']) ? trim($_GET['start_time']) : '';
$end_time = isset($_GET['end_time']) ? trim($_GET['end_time']) : '';
if(0 === strpos($_SERVER['REQUEST_URI'], '/graph'))
{
if(!extension_loaded('gd'))
{
return $this->sendToClient("not suport gd\n");
}
$type_map = array('request','time');
$type = isset($_GET['type']) && in_array($_GET['type'], $type_map) ? $_GET['type'] : 'request';
$this->displayGraph($module, $interface, $type, $start_time);
}
// 日志
elseif(0 === strpos($_SERVER['REQUEST_URI'], '/log'))
{
$right_str = '';
$code = isset($_GET['code']) ? $_GET['code'] : '';
$msg = isset($_GET['msg']) ? $_GET['msg'] : '';
$pointer = isset($_GET['pointer']) ? $_GET['pointer'] : '';
$count = isset($_GET['count']) ? $_GET['count'] : 100;
$log_data = $this->getStasticLog($module, $interface , $start_time , $end_time, $code, $msg , $pointer, $count);
if($log_data['pointer'] == 0)
{
return $this->display($log_data['data']);
}
else
{
$_GET['pointer'] = $log_data['pointer'];
unset($_GET['end_time']);
$next_page_url = http_build_query($_GET);
$log_data['data'] .= "
下一页";
return $this->display(nl2br($log_data['data']));
}
}
// 统计
else
{
// 首页
if(empty($module))
{
return $this->home();
}
else
{
if($interface)
{
return $this->displayInterface($module, $interface, $start_time, $end_time);
}
else
{
return $this->display();
}
}
}
return $this->display();
}
/**
* 统计主页
* @return void
*/
protected function home()
{
$data = '';
$address = '127.0.0.1:10101';
$sock = stream_socket_client($address);
if(!$sock)
{
return $this->display();
}
fwrite($sock, 'status');
$read_fds = array($sock);
$write_fds = $except_fds = array();
$time_start = time();
while(1)
{
$ret = @stream_select($read_fds, $write_fds, $except_fds, 1);
if(!$ret)
{
if(time() - $time_start >= 1)
{
break;
}
continue;
}
foreach($read_fds as $fd)
{
if($ret_str = fread($fd, 8192))
{
$data .= $ret_str;
}
else
{
break;
}
}
if(time() - $time_start >= 1)
{
break;
}
}
$data = ''.$data.'
';
return $this->display($data);
}
/**
* 接口统计信息
* @param string $module
* @param string $interface
* @param int $start_time
* @param int $end_time
* @return void
*/
protected function displayInterface($module ,$interface, $start_time, $end_time)
{
$data = $this->getStatistic($module, $interface, $start_time, $end_time);
$suport_gd = extension_loaded('gd');
$right_str = '
模块:'.$module.' 接口:'.$interface.'
'.($suport_gd ? '
' : '未安装gd库,图形无法展示') .'
请求量
'.($suport_gd ? '
' : '未安装gd库,图形无法展示') .'
延迟单位:秒
';
$right_str .= '';
$date_array = $this->getAvailableStDate($module, $interface);
$current_key = strtotime(date('Y-m-d', $start_time ? $start_time : time()));
if(!isset($date_array[$current_key]))
{
$date_array[$current_key] = date('Y-m-d', $current_key);
}
unset($_GET['start_time']);
$st_url = http_build_query($_GET);
$date_array_chunk = array_chunk($date_array, 7, true);
if($date_array_chunk)
{
foreach($date_array_chunk as $date_array)
{
foreach($date_array as $time_stamp => $date)
{
$right_str .= ($current_key == $time_stamp) ? (''.$date.' ') : (''.$date.' ');
}
$right_str .= "
";
}
}
$right_str .='
';
$right_str .='
| 时间 | 调用总数 | 平均耗时 | 成功调用总数 | 成功平均耗时 | 失败调用总数 | 失败平均耗时 | 成功率 |
';
if($data)
{
foreach($data as $item)
{
$right_str .= "| {$item['time']} | {$item['total_count']} | {$item['total_avg_time']} | {$item['suc_count']} | {$item['suc_avg_time']} | ".($item['fail_count']>0?("{$item['fail_count']}"):$item['fail_count'])." | {$item['fail_avg_time']} | ".($item['precent']<=98?''.$item['precent'].'%' : $item['precent'].'%')." |
\n";
}
}
$right_str .= '
';
return $this->display($right_str);
}
/**
* 展示曲线图
* @param string $module
* @param string $interface
* @param string $type
* @param integer $start_time
* @return void
*/
protected function displayGraph($module ,$interface, $type = 'request', $start_time = '')
{
$data = $this->getStatistic($module, $interface, $start_time);
\WORKERMAN\Protocols\SimpleHttp::header("Content-type: image/jpeg");
$gg=new buildGraph();
$d2 = $d3 = array();
$time_point = $start_time ? strtotime(date('Y-m-d',$start_time)) : strtotime(date('Y-m-d'));
switch($type)
{
case 'time':
for($i=0;$i<288;$i++)
{
$time_point +=300;
$d2[$time_point] = isset($data[$time_point]['total_avg_time']) ? $data[$time_point]['total_avg_time'] : 0;
$d3[$time_point] = isset($data[$time_point]['fail_avg_time']) ? $data[$time_point]['fail_avg_time'] : 0;
}
break;
default:
for($i=0;$i<288;$i++)
{
$time_point +=300;
$d2[$time_point] = isset($data[$time_point]['total_count']) ? $data[$time_point]['total_count'] : 0;
$d3[$time_point] = isset($data[$time_point]['fail_count']) ? $data[$time_point]['fail_count'] : 0;
}
}
$d2 = array_values($d2);
$d3 = array_values($d3);
$gg->addData($d2);
$gg->addData($d3);
$gg->setColors("088A08,b40404");
ob_start();
// 生成曲线图
$gg->build("line",0); // 参数0表示显示所有曲线,1为显示第一条,依次类推
return $this->sendToClient(\WORKERMAN\Protocols\SimpleHttp::encode(ob_get_clean()));
}
/**
* 获取模块
* @return array
*/
public function getModules()
{
$st_dir = WORKERMAN_LOG_DIR . 'statistic/st/';
return glob($st_dir."/*");
}
/**
* 渲染页面
* @param string $data
* @return bool
*/
protected function display($data=null)
{
$left_detail = '';
$html_left = '';
$current_module = empty($_GET['module']) ? '' : $_GET['module'];
if($current_module)
{
$st_dir = WORKERMAN_LOG_DIR . 'statistic/st/'.$current_module.'/';
$all_interface = array();
foreach(glob($st_dir."*") as $file)
{
if(is_dir($file))
{
continue;
}
$tmp = explode("|", basename($file));
$interface = trim($tmp[0]);
if(isset($all_interface[$interface]))
{
continue;
}
$all_interface[$interface] = $interface;
$left_detail .= '- '.$interface.'
';
}
}
$modules_name_array = $this->getModules();
if($modules_name_array)
{
foreach($modules_name_array as $module_file)
{
$tmp = explode("/", $module_file);
$module = end($tmp);
$html_left .= '- '.$module.'
';
if($module == $current_module)
{
$html_left .= $left_detail;
}
}
}
$display_str = <<
WORKERMAN监控