前言
由于公司JAVA部门接入了pinpoint , 所以也要求PHP也提出了相同的要求 ,于是 ...
Pinpoint功能强大,这里就不多赘述了,直接进入正题:
Pinpoint本身是CS结构,服务端可以参考其他文章.服务端会启动一个collector的服务,用来收集其他客户端发送过来的数据.而我们要做的是搭建客户端.客户端的实现原理如下:
- 官方提供了php-c-agent扩展,我们可以通过扩展中的Api将追踪的结果写入/tmp/collector-agent.sock(可修改) , PHP的任务就完成了
- 同时官方提供了一个用python开发的agent,启动agent后会将/tmp/collector-agent.sock中的内容上报给collector
安装步骤
- 官方提供PHP的扩展 GIT: https://github.com/naver/pinpoint-c-agent/releases
- 检出代码 git clone https://github.com/naver/pinpoint-c-agent.git
- 阅读README.md – 这里提供了完整的安装和启动过程
- 编译PHP扩展
编译php扩展
cd pinpoint-c-agent/PHP/pinpoint_php_ext
#常规的编译php扩展方法,phpize如果不是全局的请手动指定路径
phpize
./configure
make
make install
#编辑php.ini文件 >
extension=pinpoint_php.so
# must be unix:(unix sock address) 必须是unix套接字地址
pinpoint_php.CollectorHost=unix:/tmp/collector-agent.sock
pinpoint_php.SendSpanTimeOutMs=0 # 0 is recommanded
# request should be captured duing 1 second. < 0 means no limited
pinpoint_php.TraceLimit=-1
pinpoint_php.DebugReport=true #开启debug,在命令行执行php时会报告pinpoint的上报信息
- 启动agent;
cd pinpoint-c-agent/collector-agent/
yum install python3 #如果没装python3 需要先安装
python3 -m venv env
source env/bin/activate
pip3 install -r requirements.txt
export COLLECTOR_CONFIG=/full path of collector.conf/
./init_python_env.sh
python run.py
修改配置文件
conf/collector.conf >
# collectorhost and specific port
AgentID=your_id #当前服务器的ID,每台机器不同
ApplicationName=your_name #程序名(pinpoint会按照程序名分组显示,同一个网站应该起相同的程序名)
#这里有个坑, 以下是2种不同的配置方式,官方没有给说明,我猜是2中不同的连接方式.如果一种配置连不通可以换另一种.
#方式1
CollectorSpanIp=collectorHost #pinpoint collector的地址
CollectorSpanPort=9996 #默认9996 参考pinpoint的配置,以下同
CollectorStatIp=collectorHost
CollectorStatPort=9995
CollectorTcpIp=collectorHost
CollectorTcpPort=9994
#方式2 grpc 我一开始就用的grpc一直不通,换成方式1一下就搞定了.. -_- !
collector.grpc.agent.ip=collectorHost #collector的地址
collector.grpc.agent.port=9991
collector.grpc.stat.ip=collectorHost
collector.grpc.stat.port=9992
collector.grpc.span.ip=collectorHost
collector.grpc.span.port=9993
# your web server (nginx&apache) port
Web_Port=80 #你web服务的端口
# debug in dev
Log_Level=ERROR #错误级别,开发时可以写DEBUG,会提供能多有用的信息
# make sure LOG_DIR is exist
LOG_DIR=/your log dir/ #错误日志地址,如果目录不可写会直接报错
[Agent]
# the same as below "pinpoint_php.CollectorHost"
Address=/tmp/collector-agent.sock #这里需要和php.ini配置的一样
启动脚本
export COLLECTOR_CONFIG=/full path of collector.conf/
./init_python_env.sh
python run.py #持久运行需要使用nohup 或 &
调试: 可以用tail -f 日志文件的方式查看上报的情况
PHP的接入
Pinpoint扩展提供了基础的trace方法,数据是需要我们手动上报的
- API
/**
* start trace,if callstack is empty, creat a span. Otherwise, create a span event
* start方法类似ob_start是可以嵌套的块,在pinpoint中查看时也是一样.
*/
function pinpoint_start_trace(){
}
/**
* pop a trace.
* 类似ob_end 关闭一个块
* @return current stacksize
*/
function pinpoint_end_trace(){
}
/**
* 添加一个线索(记录一个key=>value) 却别于 pinpoint_add_clues 他的第一个参数是string
* 允许的值都是预置的,不支持自定义:
* EXP异常 uri client server stp 操作类型 name统计的块类型 sid 块id , tid跟踪id , appname 程序名, appid 程序id
*
* insert key,value into current span/spanevent
* @param string $key
* @param string $value
*/
function pinpoint_add_clue(string $key, string $value){
}
/**
* insert key,value into current span/spanevent annotation
* @param int $key
* @param string $value
*/
function pinpoint_add_clues(int $key, string $value){
}
/**
* create a process unique id 创建一个pinpoint的唯一id,用户创建tid
* @return int
*/
function pinpoint_unique_id(){
}
/**
* if $timestamp is given, use $timestamp. Or use time()
* @param int $timestamp
*/
function pinpoint_tracelimit(int $timestamp=null){
}
/**
* 丢弃当前trace
*Drop current span. Will not send to collector-agent
*/
function pinpoint_drop_trace(){
}
/**
* Get appName 获取配置文件中的app_name
*/
function pinpoint_app_name(){
}
/**
*Get appID 获取配置文件中设置的appid
*/
function pinpoint_app_id(){
}
/**
* @return collector-agent starttime
*/
function pinpoint_start_time(){
}
- API的使用
官方提供了AOP库 ,通过AOP的方式实现了追踪, 参见 PHP/Readme.md 官方库据说效率很不错 , 但是会编译现有的库,对现有的项目不友好,也会给开发增加麻烦 , 所以我决定自己通过API来嵌入pinpoint. (推荐大家还是先尝试使用官方库)
<?php
namespace common\components;
use yii\base\Component;
use yii\caching\DummyCache;
use Yii;
/**
* Pinpoing Agent植入Yii框架.
* 侦测页面访问,接口调用等功能
*
* Class Pinpoint
* @package common\components
*/
class Pinpoint extends Component
{
public static $counter = 0;//计数器
/**
* 字段声明
*/
const T_PHP_ARGS = -1;
const T_PHP_RETURN = 14;
const T_PROXY_HTTP_HEADER = 300;
const T_SQL_ID = 20;
const T_SQL = 21;
const T_SQL_METADATA = 22;
const T_SQL_PARAM = 23;
const T_SQL_BINDVALUE = 24;
const T_STRING_ID = 30;
const T_HTTP_URL = 40;
const T_HTTP_PARAM = 41;
const T_HTTP_PARAM_ENTITY = 42;
const T_HTTP_COOKIE = 45;
const T_HTTP_STATUS_CODE = 46;
const T_HTTP_INTERNAL_DISPLAY = 48;
const T_HTTP_IO = 49;
const T_MESSAGE_QUEUE_URI = 100;
//DB类型定义 2*** 数据库 , 8*** 缓存,消息队列 , 9*** rpc调用
//以下内容没有文档,都是一个个试出来的...妥善保存
const T_PHP_METHOD = "1501";
const T_PHP = "1500";
const T_MYSQL = "2101";
const T_MSSQL_SERVER = "2200";
const T_ORACLE = "2300";
const T_CUBRID = "2400";
const T_POSTGRESQL = "2500";
const T_CASSANDRA = "2600";
const T_MONGODB = "2651";//mongodb 2650也是mongodb,但是无法汇总.所以使用2651
const T_REDIS = "8200";
const T_REDIS_REDISSON = "8203";
const T_REDIS_REDISSON_INTERNAL = "8204";
const T_RABBITMQ = "8300";
const T_ACTIVEMQ = "8310";
const T_ARCUS = "8100";
const T_MEMCACHED = "8050";
const T_PINPOINT_PHP_REMOTE = 9700;
const T_NGINX_PROXY = "Pinpoint-ProxyNginx";
const T_APACHE_PROXY = "HTTP_PINPOINT_PROXYAPACHE";
const T_SAMPLED = "Pinpoint-Sampled";
/**
* @var array 统计次数限制.超过次数忽略
*/
public $limit = [
'redis' => 3,
'mysql' => 10
];
/**
* 开关.如果系统没有pinpoint扩展,改为关闭
* @var bool
*/
public $isEnable = true;
/**
* @var 记录的APPid
*/
public $appid;
/**
* @var 记录的项目名
*/
public $appname;
public $tid = null;
public $sid = null;
public $psid = null;
public $pname = null;
public $ptype = null;
public $ah = null;
private $curNextSpanId ='';
private $isLimit =false;
private $start = false;
private $end = false;
public function init()
{
if (Yii::$app->request->isAjax) {
// $this->isEnable = false;
}
//如果系统没有安装pinpoint扩展,关闭本功能
if ($this-