在phpmyadmin中使用pinpoint

> from https://github.com/pinpoint-apm/pinpoint-c-agent/wiki/%E5%9C%A8phpmyadmin%E4%B8%AD%E4%BD%BF%E7%94%A8pinpoint

怎样在phpmyadmin 中使用pinpoint-c-agent

为什么我们要发布这篇文章 ?

分享一些监控PHP项目的经验

您能从里面获取到啥 ?

  1. 怎样使用pinpoint监控PHP项目,比如phpmyadmin
  2. 怎样自定义插件

开始

安装pinpoint php 客户端

安装phpmyadmin 项目 https://www.phpmyadmin.net/

  1. 安装 pinpoint_php 扩展

    1. pecl install pinpoint_php or curl -sL https://github.com/pinpoint-apm/pinpoint-c-agent/releases/latest/download/install_pinpoint_php.sh | sh

      假如安装失败了,请在issue上面共享你的环境信息给我们。

    2. 如果是 windows 直接下载 pinpoint.dll https://pecl.php.net/package/pinpoint_php 
      • 如果不能访问 pecl.php.net, 试着从GitHub release 页面下载. 
  2. 不要忘了在php.ini 启用 pinpoint_php

    detail setting https://github.com/pinpoint-apm/pinpoint-c-agent/blob/dev/DOC/PHP/Readme.md#steps

    [pinpoint_php]
    extension=pinpoint_php.so
    pinpoint_php.CollectorHost=tcp:collector-agent-host:10000
    pinpoint_php.DebugReport=true
    ...
     
  3. 加入 pinpoint-php-aop 依赖

    composer require -w pinpoint-apm/pinpoint-php-aop

  4. 恭喜你,这是最后一步了。在项目里面的入口文件,启用pinpoint。

    • phpmyadmin:
      <?php
      // www/html/index.php
      ...
      require AUTOLOAD_FILE;
      
      class MyAdminRequestPlugin extends Pinpoint\Plugins\DefaultRequestPlugin
      {
          public function __construct()
          {
              $blackUri = ['/favicon.ico'];
              // if uri in blackUri, skips it 
              if (!in_array($_SERVER['REQUEST_URI'], $blackUri)) {
                  parent::__construct();
              }
          }
          public function __destruct()
          {
              // do nothing
          }
      }
      define('APPLICATION_NAME', 'cd.dev.test.php'); // your application name
      define('APPLICATION_ID', 'cd.dev.phpmyadmin');  // your application id
      define('PP_REQ_PLUGINS', MyAdminRequestPlugin::class);
      require_once __DIR__ . '/vendor/pinpoint-apm/pinpoint-php-aop/auto_pinpointed.php';
      
      ...
       

到此为止,客户端已经安装成功了。

安装 collector-agent(pinpoint 协议的代理模块)

打开你的phpmyadmin 页面,你可能在日志里面看到如下错误 

这就是由于collector-agent 没有安装

什么是collector-agent: https://github.com/pinpoint-apm/pinpoint-c-agent/tree/dev/DOC/collector-agent

在你安装collector-agent 之前,请保证pinpoint 已经安装成功了

安装 pinpoint

By docker-compose

https://github.com/pinpoint-apm/pinpoint-docker

安装 collector-agent

docker run -itd -p 10000:10000 --env-file ./env.list ghcr.io/pinpoint-apm/pinpoint-c-agent/collector-agent:latest

## env.list dev-pinpoint 就是pinpoint collector 的地址
PP_COLLECTOR_AGENT_SPAN_IP=dev-pinpoint
PP_COLLECTOR_AGENT_SPAN_PORT=9993
PP_COLLECTOR_AGENT_AGENT_IP=dev-pinpoint
PP_COLLECTOR_AGENT_AGENT_PORT=9991
PP_COLLECTOR_AGENT_STAT_IP=dev-pinpoint
PP_COLLECTOR_AGENT_STAT_PORT=9992
...
 

详细文档: https://github.com/pinpoint-apm/pinpoint-c-agent/blob/dev/DOC/collector-agent/readme.md

检查PHP项目的请求是否在pinpoint-web 上显示

服务调用图

调用栈图

怎样自定义插件

我跳过了一个重要的部分,pinpoint 入口文件。我在这里专门介绍它。

什么是入口文件 ? 就是下面的代码块

require_once __DIR__ . '/vendor/autoload.php'; // !!! must insert right behind system/framework autoload

define('APPLICATION_NAME', 'cd.dev.test.php'); // your application name
define('APPLICATION_ID', 'cd.dev.phpmyadmin');  // your application id
define('PP_REQ_PLUGINS', \Pinpoint\Plugins\DefaultRequestPlugin::class); //
require_once __DIR__ . '/vendor/pinpoint-apm/pinpoint-php-aop/auto_pinpointed.php';
 

这个变量用来配置一些特殊的需求

  1. 忽略页面
    public function __construct()
    {
        $blackUri = ['/favicon.ico']; // 这里忽略的页面
        // if uri in blackUri, skips it 
        if (!in_array($_SERVER['REQUEST_URI'], $blackUri)) {
            parent::__construct();
        }
    }
 

完整的例子参考 : https://github.com/pinpoint-apm/pinpoint-c-agent/blob/dev/testapps/php_phpmyadmin/index.php#L38-L44

  1. 添加拦截自己定义的类或者其他内置函数

    1. 内置函数
      • 在监控函数被调用前,加载插件
      • 插件代码模板
      pinpoint_join_cut(
          "built-in-function/method",$on_before_callback,$on_end_callback,$on_exception_callback
      )
       

      这里也有很多例子,请参考 https://github.com/pinpoint-apm/pinpoint-php-aop/blob/dev/lib/Pinpoint/Plugins/SysV2/

    2. 用户自定义类 (支持通过类加载器加载的类 load by auto_loader)
      • 继承 \Pinpoint\Plugins\DefaultRequestPlugin 并重写 joinedClassSet
      • 注册 AspectClassHandle 类
          public function joinedClassSet(): array
          {
              // don't forget passing the parent AspectClassHandle
              $cls = parent::joinedClassSet();
              $classHandler = new Pinpoint\Common\AspectClassHandle(\User\ABC::class);
              $classHandler->addJoinPoint('foo_method', \Pinpoint\Plugins\Common\CommonPlugin::class);
              $cls[] = $classHandler; //完成注册
              return $cls;
          }
       

      这里也有很多例子,请参考 https://github.com/pinpoint-apm/pinpoint-php-aop/blob/dev/lib/Pinpoint/Plugins/Yii2PerRequestPlugins.php,https://github.com/pinpoint-apm/pinpoint-php-aop/blob/dev/lib/Pinpoint/Plugins/DefaultRequestPlugin.php