直接用PhalApi\DI()->tracer在图像处理各环节(缩放、加水印等)打唯一可读标记点,避免循环高频打点;日志需结构化记录原始/目标尺寸等参数,异步处理时须手动透传traceId或改用时间戳对齐日志。

如何用 PhalApi\DI()->tracer 记录图像处理关键节点耗时
直接在图像处理流程里打点,比事后查时间戳靠谱得多。PhalApi 的 tracer 不依赖外部 SDK,也不需要改 Nginx 或 PHP-FPM 配置,只要项目已接入 PhalApi 框架就能用。
- 在图像缩放前调用
$di->tracer->mark('image.resize.start'),缩放完成后调用$di->tracer->mark('image.resize.end') - 同理,对水印添加、格式转换、EXIF 清洗等步骤分别打点,标识要唯一且可读,避免用数字编号(如
'step_1') - 不要在循环内高频打点——比如逐像素操作时每 100 行打一次,否则
getStack()返回的数组会膨胀到几 MB,拖慢整个请求
getLastSql() 和 getSqls() 对图像处理日志没用,但别误用
图像处理本身不走数据库,getLastSql() 和 getSqls() 返回的永远是空或上一个接口遗留的 SQL。强行调用不仅无意义,还可能干扰后续 DB 操作的链路追踪上下文。
- 如果图像处理后要写入元数据(如保存缩略图路径到数据库),那才应在 DB 操作前后用
tracer打点,而不是在 GD/ImageMagick 调用处 - 混淆这点会导致你误以为某次耗时长是因为 SQL 慢,实际是
imagejpeg()在高压缩比下阻塞了 800ms - 验证方法:在图像处理函数开头加
var_dump($di->tracer->getSqls()); die;,看输出是否为空
日志中必须包含图像原始尺寸与目标尺寸
光记“缩图完成”没用,必须结构化记录输入输出参数,否则无法区分是大图压测还是小图批量处理导致的性能抖动。
- 用
error_log()或 Monolog 写日志时,至少包含:original_size、target_width、target_height、format(如jpg)、quality - 避免拼接字符串日志,例如
"resize 2000x1500 → 400x300",应输出 JSON 格式,方便后续用 Logstash 提取字段:{"op":"resize","src":"2000x1500","dst":"400x300","fmt":"jpg","q":85,"took_ms":327} - GD 库在处理超大 PNG 时可能触发内存溢出,但错误日志里只报
Allowed memory size exhausted,没尺寸信息就无法定位是哪类图片引发的——所以尺寸字段不是可选,是必填
异步处理图像时,tracer 的 span 会丢失
PhalApi 的 tracer 默认绑定当前请求生命周期,一旦 fork 子进程或投递到消息队列(如 Redis Queue、Beanstalkd),traceId 就断了。这不是 bug,是设计使然。
立即学习“PHP免费学习笔记(深入)”;
- 若用
exec('php image_worker.php ... &')异步处理,必须手动透传 traceId:exec("php image_worker.php --trace-id={$di->tracer->getTraceId()} ... &") - 子进程启动后,需重建 tracer 实例并注入该 ID:
$tracer = new \PhalApi\Tracer\Tracer(); $tracer->setTraceId($argv[2]); - 更稳妥的做法是放弃
tracer,改用独立日志文件 + 时间戳对齐:主进程写start_time到临时文件,子进程完成时读该时间并计算差值,再写入统一日志
target_width 字段,排查某次 OOM 就可能多花两小时。



















