gggeek / polyfill-pinba
纯PHP实现的暴露于本地Pinba扩展的API
Requires
- php: ^5.3.0 || ^7.0 || ^8.0
Requires (Dev)
- ext-mysqli: *
- phpunit/phpunit: ^4.8 || ^5.7 || ^8.5.31
- phpunit/phpunit-selenium: *
- yoast/phpunit-polyfills: *
Provides
- ext-pinba: *
README
“PHP扩展Pinba”的纯PHP重新实现。
关于原始版本,请参阅http://pinba.org
要求
PHP 5.3或更高版本。
需要一个Pinba服务器来发送数据。已知的服务器包括http://pinba.org/和https://github.com/badoo/pinba2。这两个都可以作为Docker容器镜像试用。
安装
composer require gggeek/polyfill-pinba
然后在php.ini
中设置配置设置pinba.enabled
和pinba.server
,具体请参阅https://github.com/tony2001/pinba_engine/wiki/PHP-extension#INI_Directives
就这么多。
注意默认情况下,指标收集和发送到服务器是禁用的。除非您在PHP代码中添加了显式的pinba api调用,否则您必须通过ini设置启用它。
用法
请参阅https://github.com/tony2001/pinba_engine/wiki/PHP-extension中描述的API
一个简单的用法示例可以在doc/sample.php中找到。
要查看收集到的指标,请查看https://github.com/intaro/pinboard,https://github.com/pinba-server/pinba-server或https://github.com/ClickHouse-Ninja/Proton
原始API的扩展
Pinba::ini_set
如果您的设置中没有启用pinba php扩展(这很可能是情况,否则您就不会使用这个包),则无法从PHP代码中修改ini选项pinba.enabled
和pinba.server
的值。虽然可以在php.ini
中设置它们的值,但如果您想在运行时修改它们的值,您将不得不使用方法\PinbaPhp\Polyfill\pinba::ini_set($option, $value)
。您还应该使用相应的方法\PinbaPhp\Polyfill\pinba::ini_get($option)
来检查它。
ini选项pinba.inhibited
如果您想保留代码中用pinba_timer_add
,pinba_timer_stop
和类似调用进行仪器检测,但不再收集pinba数据,并且希望尽可能减少此包带来的开销,请在php.ini
中设置pinba.inhibited=1
。
在此场景中不建议使用pinba.enabled=0
或pinba.auto_flush=0
,因为尽管它们都禁用了数据发送,但它们并不能防止定时器的实际创建。
兼容性
我们努力实现与Pinba扩展1.1.2相同的API。
至于服务器端,该库已针对Pinba服务器和Pinba2进行兼容性测试。
不支持的功能(尚未支持)
- 定时器数据缺少
ru_utime
和ru_stime
成员。这也适用于添加到PinbaClient
实例的定时器
已知问题(无法/不会修复的问题)
- 时间报告精度不足:页面执行报告的时间会比使用PHP扩展所能测量的时间短得多。因此,我们建议不要将此包报告的时间视为绝对值,而是用它来检查宏观问题,例如一个页面运行10秒,或者比另一个页面多10倍。在演示文件 doc/sample.php 中,我们展示了如何尽可能精确地进行时间测量
- 对系统性能的影响:此实现(运行在您网站的每个页面上!)所使用的CPU时间和RAM也大于PHP扩展使用的资源。是否使用此包给服务器增加额外负载取决于您自己,尤其是对于高负载的生产服务器
- 当将错误数据传递给pinba php函数时,所引发的警告严重性为
E_USER_WARNING
,而不是E_WARNING
- 在
pinba_get_info
报告的数据和报告给Pinba服务器的数据中,doc_size
始终具有0值。可以通过使用PinbaClient
实例并调用setDocumentSize
来解决此问题 - 有关示例,请参阅doc/measure_body_size.php - 在报告给Pinba服务器的数据中,
memory_footprint
始终具有固定的0值或根本不报告。同样,使用PinbaClient
实例可以解决这个问题 - 但据我所知,没有PHP函数可以报告由PHP扩展完成的等效mallinfo
C调用的使用情况 - ini设置
pinba.resolve_interval
不受支持,并且可能永远不会支持 - 报告给Pina引擎的
schema
字段的默认值是空字符串,而不是未设置。这导致数据库表存储的值为''而不是NULL。同时,发送NULL值会使服务器端引擎重用上一个pinba数据包中的最后一个非空值,这似乎是一种错误的行为 pinba_reset
调用确实会删除所有现有的计时器,这与PHP扩展中相同函数的行为不同。同样,上游的行为感觉上是错误的
性能
这些结果表明,执行1000次函数调用循环的时间和内存开销,并使用单独的计时器对每次执行进行仪表化。
如您所见,引入的执行延迟非常小,小于1毫秒。内存开销与添加的计时器数量和每个计时器附加的标签数量成正比。
No timing: 0.00001 secs, 0 bytes used
Pinba-extension: 0.00072 secs, 280.640 bytes used
PHP-Pinba: 0.00062 secs, 412.920 bytes used
注意:奇怪的是,PHP扩展似乎平均比纯PHP实现要慢一些。简要查看扩展的C代码后,我怀疑这是因为它执行了太多的gettimeofday
调用...
如果您想保持使用大量pinba_timer_start
调用的代码进行仪表化,并尽可能减少使用扩展的开销(当然不再进行测量),您可以在php.ini中设置pinba.inhibited=1
。
设置了它之后,这是“计时”1000次函数调用执行时的开销
No timing: 0.00001 secs, 0 bytes used
PHPPinba timed: 0.00009 secs, 0 bytes used
(在Ubuntu Focal容器中执行测试,容器运行在Ubuntu Jammy VM中,分配了4个vCPU)
注意
包含来自Iván -DrSlump- Montes的Protobuf for PHP库的代码:https://github.com/drslump/Protobuf-PHP
存在其他实现相同想法的已知包,例如:https://github.com/vearutop/pinba-pure-php
常见问题解答
- 问题:我可以在使用 pinba php 扩展的同时运行 polyfill 吗?答案:是的,尽管我不明白你为什么要这样做。这样做时,除非你注意选择性地禁用 php 扩展或此捆绑包(例如,通过在代码中调用
Pinba::ini_set
),否则你将向 Pinba 服务器报告双倍的数据。
运行测试
运行库的测试套件建议的方式是通过提供的 Docker 容器和相应的 Docker Compose 配置。有一个方便的 shell 脚本可以简化 Docker 和 Docker Compose 的使用。
操作的全过程是
./tests/ci/vm.sh build
./tests/ci/vm.sh start
./tests/ci/vm.sh runtests
./tests/ci/vm.sh stop
# and, once you have finished all testing related work:
./tests/ci/vm.sh cleanup
默认情况下,测试使用基于 Ubuntu 20 Focal 的容器中的 php 7.4 运行。数据被发送到运行原始 Pinba 服务器容器的容器 - 它也可以配置为发送到运行 Pinba2 服务器容器的容器。
你可以在构建容器之前设置环境变量 PHP_VERSION
和 UBUNTU_VERSION
来更改使用的 PHP 和 Ubuntu 版本。
你可以在启动容器之前设置环境变量 PINBA_DB_SERVER=pinba2
、PINBA_SERVER=pinba2
和 PINBA_PORT=3002
,将测试套件的目标容器切换到运行 Pinba2 的容器。
测试技巧
-
要调试 php 和 Pinba 服务器之间的通信,你可以在
php
容器中使用 tcpdump。sudo tcpdump udp -w packets.cap
一旦捕获文件被保存,可以使用 Wireshark 等工具进行分析。为了提高 Wireshark 解码 protobuf 格式消息的能力,请根据 https://wiki.wireshark.org/Protobuf.md 中的说明设置其配置。描述 Pinba 所用消息的
.proto
文件可以在 https://github.com/badoo/pinba2/blob/master/proto/pinba.proto 找到。作为 Wireshark 不需要的替代方案,你也可以将
pinba_get_data()
调用的字符串结果保存到文件中,然后使用默认包含在测试容器中的protoc
工具对其进行解码。php myTestFile > test.rawmsg protoc --decode=Pinba.Request tests/pinba.proto < test.rawmsg
许可证
使用此软件受 许可证 文件中的条款约束。