TransferStatistics v2 使用webman開發(fā)的一個應用監(jiān)控系統,用于查看應用調用記錄、請求量、調用耗時、調用分析等。
系統使用
HTTP
接收上報數據;使用Redis
進行數據匯總統計;使用MySql
存儲統計數據和上報信息
PHP版本不低于7.2,并安裝 Redis 拓展
創(chuàng)建項目
composer create-project hsk99/transfer-statistics
1、下載 或 git clone https://github.com/hsk99/transfer-statistics
2、執(zhí)行命令 composer install
database/transfer.sql
1、修改文件 config/redis.php
設置 Redis
2、修改文件 config/server.php
設置 HTTP
3、修改目錄 config/plugin/webman/redis-queue/
設置 RedisQueue 相關信息
4、修改文件 config/thinkorm.php
設置 MySql 相關信息
執(zhí)行命令 php start.php start
瀏覽器訪問 http://ip地址:8788
默認賬號:admin
默認密碼:admin888
相關信息可在 系統管理--系統設置
中進行設置
webman 使用 webman-statistic 插件
其他框架使用,TP6中間件示例
<?php
declare(strict_types=1);
namespace app\middleware;
class Transfer
{
/**
* 處理請求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
$startTime = microtime(true); // 開始時間
$project = 'tp6'; // 應用名
$ip = '127.0.0.1'; // 請求IP
$transfer = 'test'; // 調用入口
$response = $next($request);
$finishTime = microtime(true); // 結束時間
$costTime = $finishTime - $startTime; // 運行時長
$code = mt_rand(2, 5) * 100; // 狀態(tài)碼
$success = $code < 400; // 是否成功
// 詳細信息,自定義設置
$details = [
'time' => date('Y-m-d H:i:s.', (int)$startTime) . substr((string)$startTime, 11), // 請求時間(包含毫秒時間)
'run_time' => $costTime, // 運行時長
// .....
];
// 執(zhí)行上報
try {
// 數據打包 多條 換行 隔開
$data = json_encode([
'time' => date('Y-m-d H:i:s.', (int)$startTime) . substr((string)$startTime, 11),
'project' => $project,
'ip' => $ip,
'transfer' => $transfer,
'costTime' => $costTime,
'success' => $success ? 1 : 0,
'code' => $code,
'details' => json_encode($details, 320),
], 320) . "\n";
$client = new \GuzzleHttp\Client(['verify' => false]);
$client->post(
// 上報地址
'http://127.0.0.1:8788/report/statistic/transfer',
[
'headers' => [
// 上報認證,不設置默認為當前年份的md5值
'authorization' => md5(date('Y'))
],
'form_params' => [
// 上報數據
'transfer' => $data
],
]
);
} catch (\Throwable $th) {
//throw $th;
}
return $response;
}
}
v2.0.3 - 2022-07-24
1、新增 Elasticsearch全局搜索并高亮展示
2、新增 調用記錄同步至Elasticsearch
3、新增 MySql數據同步至Elasticsearch,可多進程處理
4、新增 db搜索并關鍵字高亮展示
5、新增 調用記錄列表數據篩選、刷新、導出等操作
6、新增 應用管理 可刪除并清空應用數據
7、優(yōu)化 數據緩存,進程關閉時存儲其緩存數據
8、優(yōu)化 頁面展示
v2.1.1 - 2022-08-31
1、去除 redis-queue
2、重構 上報數據處理方式
3、優(yōu)化 統計數據同步MySql邏輯
4、重構 調用記錄存儲MySql、Elasticsearch
v1 版本介紹:https://hsk99.com.cn/blog/4
我寫了一篇使用實例 大家可以參考看看
TransferStatistics使用實例:應用和SQL監(jiān)控系統workerman
https://my.oschina.net/owenzhang24/blog/5522317
ErrorException: Undefined array key 0 in /path/vendor/workerman/workerman/Protocols/Http/Response.php:396
Stack trace:
#0 /path/vendor/workerman/workerman/Protocols/Http/Response.php(396): {closure}(2, 'Undefined array...', '/Users/ziyoren/...', 396)
#1 /path/vendor/workerman/workerman/Protocols/Http.php(254): Workerman\Protocols\Http\Response->__toString()
#2 /path/vendor/workerman/workerman/Connection/TcpConnection.php(321): Workerman\Protocols\Http::encode(Object(Webman\Http\Response), Object(Workerman\Connection\TcpConnection))
#3 /path/vendor/workerman/webman-framework/src/App.php(396): Workerman\Connection\TcpConnection->send(Object(Webman\Http\Response))
#4 /path/vendor/workerman/webman-framework/src/App.php(166): Webman\App::send(Object(Workerman\Connection\TcpConnection), Object(Webman\Http\Response), Object(support\Request))
#5 /path/vendor/workerman/workerman/Connection/TcpConnection.php(638): Webman\App->onMessage(Object(Workerman\Connection\TcpConnection), Object(support\Request))
#6 /path/vendor/workerman/workerman/Events/Select.php(295): Workerman\Connection\TcpConnection->baseRead(Resource id #210)
#7 /path/vendor/workerman/workerman/Worker.php(2431): Workerman\Events\Select->loop()
#8 /path/vendor/workerman/workerman/Worker.php(1555): Workerman\Worker->run()
#9 /path/vendor/workerman/workerman/Worker.php(1397): Workerman\Worker::forkOneWorkerForLinux(Object(Workerman\Worker))
#10 /path/vendor/workerman/workerman/Worker.php(1371): Workerman\Worker::forkWorkersForLinux()
#11 /path/vendor/workerman/workerman/Worker.php(549): Workerman\Worker::forkWorkers()
#12 /path/start.php(108): Workerman\Worker::runAll()
#13 {main}
worker[wechatpay:52968] exit with status 64000
只要加上中間件,就報錯。不知道為什么?請問如何排查?
<?php
namespace app\middleware;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
use app\services\StatisticClient; //客戶端類放在這里
class Statistic implements MiddlewareInterface
{
public function process(Request $request, callable $next) : Response
{
$ip = $request->getRealIp();
$controller = $request->controller;
$action = $request->action;
$transfer = $controller . '::' . $action;
// 開始計時
$unique = StatisticClient::tick('project', $ip, $transfer); //只要調用到這里就會報錯
$response = $next($request);
$code = $response->getStatusCode();
$success = $code < 400;
$details = [
'ip' => $ip ?? '', // 請求客戶端IP
'url' => $request->fullUrl() ?? '', // 請求URL
'method' => $request->method() ?? '', // 請求方法
'request_param' => $request->all() ?? [], // 請求參數
'request_header' => $request->header() ?? [], // 請求頭
'cookie' => $request->cookie() ?? [], // 請求cookie
'session' => $request->session()->all() ?? [], // 請求session
'response_code' => $response->getStatusCode() ?? '', // 響應碼
'response_header' => $response->getHeaders() ?? [], // 響應頭
'response_body' => $success ?: (string)$response->rawBody(), // 響應數據(發(fā)生異常)
];
// 數據上報
StatisticClient::report($unique, 'project', $ip, $transfer, $success, $code, json_encode($details, 320));
return $response;
}
}
原因:PHP8報錯了,導致后面的程序無法按預期的運行。
StatisticClient類的tick方法,第一個參數給了默認值,函數的參數帶有默認值時,如果不再參數最后,PHP8會提示deprecated。
public static function tick(string $project = '', string $ip, string $transfer = ''): string
{
$unique = uniqid();
self::$timeMap[md5($project . $ip . $transfer . $unique)] = microtime(true);
return $unique;
}
將上面的代碼改一下
public static function tick(string $project, string $ip, string $transfer = ''): string
{
$unique = uniqid();
self::$timeMap[md5($project . $ip . $transfer . $unique)] = microtime(true);
return $unique;
}
注意:其他幾個方法也要修改。
代碼還是要規(guī)范啊!?。。?/p>
在mac上有權限問題?
php start.php start時提示PHP Warning: mkdir(): Read-only file system in /path/to/my/projects/transfer-statistics/start.php on line 36
php 8.1.9 運行報錯
[2022-09-02 11:02:57] Worker?ync.statistics.to.mysql
ErrorException: Implicit conversion from float 1662087777.472007 to int loses precision in /root/transfer-statistics/support/hsk99/bootstrap/ThinkOrmLog.php:29
Stack trace:
#0 [internal function]: {closure}()
#1 /root/transfer-statistics/support/hsk99/bootstrap/ThinkOrmLog.php(29): date()
#2 /root/transfer-statistics/vendor/topthink/think-orm/src/db/Connection.php(264): support\hsk99\bootstrap\ThinkOrmLog::support\hsk99\bootstrap\{closure}()
#3 /root/transfer-statistics/vendor/topthink/think-orm/src/db/PDOConnection.php(776): think\db\Connection->trigger()
#4 /root/transfer-statistics/vendor/topthink/think-orm/src/db/connector/Mysql.php(66): think\db\PDOConnection->getPDOStatement()
#5 /root/transfer-statistics/vendor/topthink/think-orm/src/db/PDOConnection.php(422): think\db\connector\Mysql->getFields()
#6 /root/transfer-statistics/vendor/topthink/think-orm/src/db/PDOConnection.php(362): think\db\PDOConnection->getTableFieldsInfo()
#7 /root/transfer-statistics/vendor/topthink/think-orm/src/db/PDOConnection.php(409): think\db\PDOConnection->getSchemaInfo()
#8 /root/transfer-statistics/vendor/topthink/think-orm/src/db/PDOConnection.php(459): think\db\PDOConnection->getTableInfo()
#9 /root/transfer-statistics/vendor/topthink/think-orm/src/db/Query.php(291): think\db\PDOConnection->getPk()
#10 /root/transfer-statistics/vendor/topthink/think-orm/src/db/concern/WhereQuery.php(442): think\db\Query->getPk()
#11 /root/transfer-statistics/vendor/topthink/think-orm/src/db/concern/WhereQuery.php(422): think\db\BaseQuery->whereEq()
#12 /root/transfer-statistics/vendor/topthink/think-orm/src/db/concern/WhereQuery.php(386): think\db\BaseQuery->parseWhereItem()
#13 /root/transfer-statistics/vendor/topthink/think-orm/src/db/concern/WhereQuery.php(41): think\db\BaseQuery->parseWhereExp()
#14 /root/transfer-statistics/app/common/service/SyncStatisticsToMySql.php(49): think\db\BaseQuery->where()
#15 /root/transfer-statistics/process/SyncStatisticsToMySql.php(18): app\common\service\SyncStatisticsToMySql::run()
#16 /root/transfer-statistics/vendor/workerman/workerman/Events/Select.php(238): process\SyncStatisticsToMySql->process\{closure}()
#17 /root/transfer-statistics/vendor/workerman/workerman/Events/Select.php(299): Workerman\Events\Select->tick()
#18 /root/transfer-statistics/vendor/workerman/workerman/Worker.php(2463): Workerman\Events\Select->loop()
#19 /root/transfer-statistics/vendor/workerman/workerman/Worker.php(1574): Workerman\Worker->run()
#20 /root/transfer-statistics/vendor/workerman/workerman/Worker.php(1416): Workerman\Worker::forkOneWorkerForLinux()
#21 /root/transfer-statistics/vendor/workerman/workerman/Worker.php(1390): Workerman\Worker::forkWorkersForLinux()
#22 /root/transfer-statistics/vendor/workerman/workerman/Worker.php(557): Workerman\Worker::forkWorkers()
#23 /root/transfer-statistics/start.php(117): Workerman\Worker::runAll()
centos7.9 php 8.1.10報錯
"require": {
"php": ">=7.2",
"workerman/webman-framework": "^1.5.0",
"monolog/monolog": "^2.0",
"tinywan/exception-handler": "^1.1",
"webman/think-orm": "^1.0",
"psr/container": "^2.0",
"illuminate/redis": "^10.5",
"symfony/cache": "^6.2",
"webman/console": "^1.2",
"google/apiclient": "^2.13",
"topthink/think-log": "^2.0",
"workerman/crontab": "^1.0",
"kreait/firebase-php": "^7.2",
"zjkal/time-helper": "^1.1",
"tinywan/validate": "^0.0.6",
"ext-openssl": "*",
"yzh52521/webman-lock": "^1.0",
"vlucas/phpdotenv": "^5.5",
"ext-pdo": "*",
"hsk99/webman-statistic": "^2.0"
},
ErrorException: strtolower(): Passing null to parameter #1 ($string) of type string is deprecated in D:\Web\webman-test\config\plugin\hsk99\statistic\route.php:28
Stack trace:
#0 [internal function]: support\App::{closure}(8192, 'strtolower(): P...', 'D:\\Web\\webman-t...', 28)
#1 D:\Web\webman-test\config\plugin\hsk99\statistic\route.php(28): strtolower(NULL)
#2 D:\Web\webman-test\vendor\workerman\webman-framework\src\App.php(159): Webman\Route::{closure}(Object(support\Request))
#3 D:\Web\webman-test\vendor\workerman\workerman\Connection\TcpConnection.php(646): Webman\App->onMessage(Object(Workerman\Connection\TcpConnection), Object(support\Request))
#4 D:\Web\webman-test\vendor\workerman\workerman\Events\Select.php(311): Workerman\Connection\TcpConnection->baseRead(Resource id #373)
#5 D:\Web\webman-test\vendor\workerman\workerman\Worker.php(1479): Workerman\Events\Select->loop()
#6 D:\Web\webman-test\vendor\workerman\workerman\Worker.php(1399): Workerman\Worker::forkWorkersForWindows()
#7 D:\Web\webman-test\vendor\workerman\workerman\Worker.php(560): Workerman\Worker::forkWorkers()
#8 D:\Web\webman-test\vendor\workerman\webman-framework\src\support\App.php(131): Workerman\Worker::runAll()
#9 D:\Web\webman-test\start.php(4): support\App::run()
#10 {main}
大贊!