不能直接用 error_log() 记 ai 接口请求,因其默认写入 php 错误日志、无上下文、难过滤;应封装统一函数并记录结构化字段,用 monolog 配 rotatingfilehandler 和 jsonformatter,禁用 display_errors 等高危配置。

为什么不能直接用 error_log() 记 AI 接口请求
因为 error_log() 默认写入 PHP 错误日志,不带上下文(如请求 ID、耗时、响应体),也难过滤。AI 接口调用失败时,你看到的可能只是 PHP Warning: curl_exec(): ...,根本不知道是模型返回了 429 Too Many Requests 还是 JSON 解析失败。
实操建议:
- 所有 AI 请求必须封装在统一函数(如
call_ai_api())中,日志逻辑内聚,避免散落各处 - 日志至少包含:
timestamp、request_id(用uniqid()或random_bytes(8)生成)、model、prompt_truncated(布尔值,提示过长时标记)、http_status、response_time_ms、error_type(如"curl_timeout"/"json_decode_failed"/"ai_rejected") - 不要记录完整
response_body(含敏感 prompt 或 token),用mb_substr($body, 0, 512)截断,或只记录strlen($body)和json_last_error_msg()
用 Monolog 写结构化日志但避开常见配置坑
Monolog 是事实标准,但默认 StreamHandler 在高并发下容易丢日志(PHP-FPM worker 复用导致文件句柄冲突),且 JSON 格式若没配 JsonFormatter,查起来反人类。
实操建议:
- 用
RotatingFileHandler替代StreamHandler,设置$maxFiles = 30防止磁盘打满 - 务必加
JsonFormatter,并设$formatter->includeStacktraces(false)(AI 日志不需要堆栈) - 关键字段用
extra传,别塞进 message 字符串:$logger->info('AI call completed', ['model' => 'gpt-4o', 'latency' => 1247, 'tokens_in' => 321]) - 避免在
__destruct()或异常处理器里写 AI 日志——可能已超时或内存不足,导致二次崩溃
如何快速定位“明明返回 200 却没拿到结果”的问题
AI 接口常返回 HTTP 200,但 body 是错误 JSON(如 Cloudflare 拦截页、OpenAI 的 {"error": {"message": "Rate limit..."}}),或字段名拼错(choices[0].message.content vs choices[0].delta.content)。
实操建议:
- 在解析前加校验:
if (!isset($data['choices'][0]['message']['content']) && !isset($data['choices'][0]['delta']['content'])) { throw new RuntimeException('Unexpected AI response structure'); } - 把原始
$http_response_header和$http_response_code一并记进日志,比只看curl_getinfo($ch, CURLINFO_HTTP_CODE)更准(后者可能被重定向覆盖) - 对 streaming 响应(SSE),用
fgets()逐行读取时,记录每行长度和是否以data:开头,防止粘包或空行中断
生产环境必须关掉的三件事
不是功能要不要,而是关不关直接影响稳定性与合规性。
- 关掉
display_errors = On—— 一旦call_ai_api()抛出未捕获异常,HTML 页面会暴露 API Key 或 prompt 内容 - 关掉日志中的
$_SERVER['HTTP_AUTHORIZATION']和$_SERVER['PHP_AUTH_USER']—— OpenID 或自建鉴权头可能含 token - 关掉
log_errors_max_len的默认值(1024)——AI 返回的 error message 可能超长,截断后看不出是"context_length_exceeded"还是"invalid_request_error"
最易被忽略的是:日志文件权限。PHP 进程用户(如 www-data)写入的日志,如果被运维用 root 手动 cat 或 tail -f 查看,可能触发 SELinux 或 auditd 告警;应统一用 logrotate + create 640 www-data adm 管理。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











