首页 > 编程语言 >pinpoint-php-aop 内部原理

pinpoint-php-aop 内部原理

时间:2024-08-30 14:03:15浏览次数:10  
标签:__ function PHP pinpoint aop interceptor php

pinpoint-php-aop 是一个支持pinpoint-php agent 的库

  1. 自动注入PHP内置函数,比如redis,pdo,mysqli
  2. 自动注入用户类,比如 guzzlehttp, predis

怎样处理内置函数

内置函数解释:

    PHP comes standard with many functions and constructs. There are also functions that require specific 
    PHP extensions compiled in, otherwise fatal "undefined function" errors will appear. For example, to 
    use image functions such as imagecreatetruecolor(), PHP must be compiled with GD support. Or, to use 
    mysqli_connect(), PHP must be compiled with MySQLi support. There are many core functions that are 
    included in every version of PHP, such as the string and variable functions. A call to phpinfo() 
    or get_loaded_extensions() will show which extensions are loaded into PHP. Also note that many 
    extensions are enabled by default and that the PHP manual is split up by extension. ...

> https://www.php.net/manual/en/functions.internal.php#functions.internal
 

通过修改PHP内核中 CG(class_table)

Inspired by https://www.phpinternalsbook.com/php7/extensions_design/hooks.html#overwriting-an-internal-function

PHP内核中提供了全局的 class_table,用户可以可以用来替换原始的函数,然后达到包装该函数的目的:比如插入一些安全的插件代码。

步骤

  1. ext_pinpoint-php 提供内置函数替换功能
// https://github.com/pinpoint-apm/pinpoint-c-agent/blob/9c544f139665dde3a9cee2a244a9c3be2f32bff9/src/PHP/pinpoint_php.cpp#L887
zend_function *func = (zend_function *)zend_hash_str_find_ptr(
      CG(function_table), ZSTR_VAL(name), ZSTR_LEN(name));
  if (func != NULL &&
      func->internal_function.handler == pinpoint_interceptor_handler_entry) {
    pp_trace("function `%s` interceptor already added", ZSTR_VAL(name));
  } else if (func != NULL) {
    pp_interceptor_v_t *interceptor =
        make_interceptor(name, before, end, exception, func);
    // insert into hash
    if (!zend_hash_add_ptr(PPG(interceptors), name, interceptor)) {
      free_interceptor(interceptor);
      pp_trace("added interceptor on `function`: %s failed. reason: already "
               "exist ",
               ZSTR_VAL(name));
      return;
    }
    func->internal_function.handler = pinpoint_interceptor_handler_entry;
    pp_trace("added interceptor on `function`: %s success", ZSTR_VAL(name));
 
  1. 基于第一步的功能,在插入点添加pinpoint的业务逻辑插件
// https://github.com/pinpoint-apm/pinpoint-php-aop/blob/5994253869d516c38d528a8ef784a5c1c18b20f3/lib/Pinpoint/Plugins/SysV2/_curl/curl.php#L78
pinpoint_join_cut(
    ["curl_close"],
    function ($ch) use (&$ch_res) {
        unset($ch_res[(int) $ch]);
        pinpoint_start_trace();
        pinpoint_add_clue(PP_INTERCEPTOR_NAME, "curl_close");
        pinpoint_add_clue(PP_SERVER_TYPE, PP_PHP_METHOD);
    },
    function ($ret) {
        pinpoint_end_trace();
    },
    function ($e) {
    }
);
 
  1. 根据需要,启用插件
// https://github.com/pinpoint-apm/pinpoint-php-aop/blob/5994253869d516c38d528a8ef784a5c1c18b20f3/lib/Pinpoint/Plugins/PinpointPerRequestPlugins.php#L126C12-L126C58
if(sampled){
    require_once __DIR__ . "/SysV2/__init__.php";
}else{
    require_once __DIR__ . "/SysV2/_curl/__init__.php";
}
 

怎样处理用户定义的类

在此之前,你需要了解类加载器

By registering autoloaders, PHP is given a last chance to load the class or interface before it fails with an error.
> https://www.php.net/manual/en/language.oop5.autoload.php 
 

对于PHP,当用户通过 use 等来加载类或者函数的时候,内核会检查这个类是否已经被加载。如果没有,它就会调用auto_loader去调用对应的文件。pinpoint-php-aop 也就是在这个时候开始拦截类的。

  1. 当PHP的类加载器初始完成后,pinpoint-php-aop 的类加载器会拦截所有的加载的类和函数。当发现一个需要被拦截的类被加载的时候,它会把这个类指向一个添加了pinpoint插件的类。

  2. 当pinpoint 加载器发现这个文件没有被pinpoint的插件拦截,它就会生成一个添加了pinpoint插件的类,然后注册到类加载器里面。更重要的是,这些类会被缓存到cache_dir中,当后续的请求到来的时候,这些类文件会被重新使用。这样的好处是,可以节约很多请求时间。

ast_loader

可能有些晕

标签:__,function,PHP,pinpoint,aop,interceptor,php
From: https://www.cnblogs.com/eeliu/p/18388648

相关文章

  • thinkphp5跨域问题
    首先我想到的是在配置文件中加跨域header("Access-Control-Allow-Origin:*");header('Access-Control-Allow-Methods:*');header('Access-Control-Allow-Headers:x-requested-with,content-type,token');header('Access-Control-Allow-Credentials',......
  • 逆向工程、Spring框架IOC、AOP学习
    系列文章目录第一章基础知识、数据类型学习第二章万年历项目第三章代码逻辑训练习题第四章方法、数组学习第五章图书管理系统项目第六章面向对象编程:封装、继承、多态学习第七章封装继承多态习题第八章常用类、包装类、异常处理机制学习第九章集合学习第......
  • 主动元数据和 DataOps 体系建设有什么关系?
    首先,主动元数据是相对静态元数据而言,它是一种动态、智能化的元数据管理技术,能够将传统静态元数据的被动等待变为实时在线、主动触发,推动数据探查、开发、测试、部署、运维和监控等数据治理工作高效运转,为数据的治理开发决策提供智能化支持。Gartner将主动元数据定义为“是对所有可......
  • Php:Call to a member function fetch_all() on bool in ... #0 {main} thrown in ...
    一、软件版本  软件版本:phpstudy_proV8.2.9;二、错误描述  在编写完连接数据库,执行相关的操作的代码之后,在浏览器运行时报如下错误:Fatalerror:UncaughtError:Calltoamemberfunctionfetch_all()onboolinD:\phpstudy_pro\WWW\test2.cc\contact.php:77St......
  • 第44天:WEB攻防-PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式
    #PHP-MYSQL-SQL操作-增删改查1、功能:数据查询查询:SELECT*FROMnewswhereid=$id2、功能:新增用户,添加新闻等增加:INSERTINTOnews(字段名)VALUES(数据)3、功能:删除用户,删除新闻等删除:DELETEFROMnewsWHEREid=$id4、功能:修改用户,修改文章等修改:UPDATEnewsSETid=......
  • ThinkPHP之入门讲解
    目录1ThinkPHP1.1框架1.1.1目录讲解1.1.1.15.x1.1.1.26.0以上1.1.2配置文件1.1.2.15.x1.1.2.26.0以上1.1.3函数文件1.1.3.15.x1.1.3.16.0以上1.2控制器1.2.1控制器的后缀1.2.2框架中的命名空间1.2.3url访问1.2.4调试模式1.2.4.15.x1.2.4.26.0以上1.3创建模块1.......
  • PHP8面向对象快速入门三 类的继承 类方法属性重写和final关键字 parent调用父类的方法
    在PHP中,类的继承(继承)是一种机制,允许一个类继承另一个类的属性和方法,从而实现代码的重用和扩展。继承可以帮助你创建一个基于现有类的新类,保留原有类的特性并增加或修改其功能。classAnimal{public$name='dongwu';protected$age=1;private......
  • 基于PHP+Vue的卷烟营销统计分析系统
    ......
  • 第42天:WEB攻防-PHP应用&MYSQL架构&SQL注入&跨库查询&文件读写&权限操作 - 快捷方式
    接受的参数值未进行过滤直接带入SQL查询 MYSQL注入:(目的获取当前web权限)1、判断常见四个信息(系统,用户,数据库名,版本)2、根据四个信息去选择方案root用户:先测试读写,后测试获取数据非root用户:直接测试获取数据  #PHP-MYSQL-SQL常规查询获取相关数据:1、数据库版本-看是否......
  • php 把文件加入到现有的zip压缩包中
    //指定要添加的文件和已有的压缩包名称$fileToAdd=public_path().'pdffile/file1.txt';//要添加的文件$zipFileName=public_path().'pdfzip/archive.zip';//已有的压缩包名称//创建一个新的ZIP档案对象$zip=newZipArchive();......