调支付接口时,如果请求、回调和状态变化都写进 system.log,定位一笔订单很痛苦。临时用 file_put_contents() 虽然快,但绕过日志级别、异常处理和轮转。比较稳的方式是给模块配置独立的 Monolog Handler,再把这个 Logger 只注入需要的类。

Handler只负责文件和最低日志级别

namespace Vendor\Payment\Logger;

use Magento\Framework\Logger\Handler\Base;
use Monolog\Level;

class Handler extends Base
{
    protected $loggerType = Level::Debug;
    protected $fileName = '/var/log/payment.log';
}

不同 Magento/Monolog 版本对 level 常量的类型要求可能不同。如果项目仍使用 Monolog 1/2,就按当前 Magento\Framework\Logger\Handler\Base 的属性定义使用 Logger::DEBUG。不要从网上复制一段代码后跳过编译检查。

用di.xml组装一个只带这个Handler的Logger

<virtualType name="VendorPaymentLogger" type="Magento\Framework\Logger\Monolog">
    <arguments>
        <argument name="name" xsi:type="string">payment</argument>
        <argument name="handlers" xsi:type="array">
            <item name="payment" xsi:type="object">Vendor\Payment\Logger\Handler</item>
        </argument>
    </arguments>
</virtualType>

<type name="Vendor\Payment\Model\GatewayClient">
    <arguments>
        <argument name="logger" xsi:type="object">VendorPaymentLogger</argument>
    </arguments>
</type>

业务类仍然依赖 Psr\Log\LoggerInterface,不用把自定义 Logger 类写死:

public function __construct(private LoggerInterface $logger) {}

$this->logger->info('payment request started', [
    'order_id' => $orderId,
    'request_id' => $requestId,
]);

日志能定位问题,但不能把敏感数据原样落盘

支付日志至少要过滤卡号、CVV、Authorization、Cookie、完整 access token 和客户密码。请求体最好建立白名单,只记录订单号、网关请求号、金额、币种、HTTP 状态和耗时。失败响应也不要整包输出,第三方接口有时会回显用户资料。

用一笔可控测试订单验证四件事

编译并清配置缓存后,检查 var/log/payment.log 是否由正确用户创建、正常请求是否写入、异常是否包含 correlation id、system.log 是否没有重复一份。最后配置 logrotate 或容器日志采集,避免高峰期把磁盘写满。独立日志的价值是快速串起一笔交易,而不是把所有对象 dump 得越多越好。