apache默认不记录单个文件上传大小和耗时,但可通过自定义日志格式(%i和%d)、合理配置limitrequestbody、php脚本补充记录及排查代理干扰来实现可观测性。

Apache 本身不直接记录单个文件上传的大小和耗时,它默认只记录整个请求的响应状态、时间戳、客户端 IP 和请求行等基础信息。但你可以通过组合日志格式定制 + 模块启用 + 后端配合的方式,间接实现对上传行为的可观测性。
1. 自定义日志格式,捕获请求体大小和处理时间
Apache 的 %I(输入字节数)和 %D(响应耗时,微秒)是关键字段:
- %I 表示从客户端接收到的原始字节数(含 HTTP 头+请求体),对 POST/PUT 上传请求来说,这个值接近实际上传数据量(不含 TCP/IP 开销)
- %D 是 Apache 完成请求处理所用的总微秒数,可反映上传+脚本执行整体耗时
在 apache2.conf 或虚拟主机配置中添加:
<ifmodule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %I %D" uploadlog
CustomLog ${APACHE_LOG_DIR}/upload.log uploadlog
</ifmodule>
重启 Apache 后,/var/log/apache2/upload.log 中每行末尾会多出两个数字:上传总字节数(%I)和总耗时微秒(%D)。例如:
192.168.1.100 - - [18/Jun/2026:02:35:12 +0000] "POST /upload.php HTTP/1.1" 200 124 "-" "curl/7.81.0" 52430120 12485000→ 表示上传了约 52.4 MB 数据,整个请求耗时约 12.5 秒。
2. 确保 LimitRequestBody 不过早截断,避免日志失真
如果 LimitRequestBody 设置过小,大上传会在进入 PHP 前就被 Apache 拒绝(返回 413),此时 %I 可能只记录到截断点,%D 极短,无法反映真实上传尝试。建议:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 将 LimitRequestBody 设为略大于你期望的最大上传值(如设为 60MB 对应 50MB 业务需求)
- 确保该值 ≥ PHP 的 post_max_size,否则上传可能被 PHP 截断而 Apache 日志仍显示完整 %I(因请求体已全部接收)
3. 结合 PHP 脚本补充细粒度信息
Apache 日志无法区分“上传了什么文件”或“PHP 是否真正接收成功”。需在 PHP 上传逻辑中主动记录:
- 用 $_SERVER['CONTENT_LENGTH'] 获取原始请求体长度(与 %I 接近)
- 用 microtime(true) 在脚本开头和 move_uploaded_file() 后打点,计算 PHP 层处理耗时
- 记录 $_FILES['xxx']['size'](PHP 解析后的文件大小)和 $_FILES['xxx']['error']
例如在 upload.php 开头加:
$start = microtime(true);
error_log("UPLOAD START: CONTENT_LENGTH={$_SERVER['CONTENT_LENGTH']} | FILES=".json_encode($_FILES), 3, "/var/log/apache2/php-upload.log");
结尾加:
$end = microtime(true);
error_log("UPLOAD DONE: size={$_FILES['file']['size']} | time=".round($end-$start,3)."s | error={$_FILES['file']['error']}", 3, "/var/log/apache2/php-upload.log");
4. 注意代理层干扰(Nginx 反代场景)
若前端有 Nginx,Apache 日志中的 %I 是 Nginx 转发过来的数据量,可能已被 Nginx 截断。此时必须同时检查:
- Nginx 的 client_max_body_size 是否足够
- Nginx access_log 中的 $body_bytes_sent 和 $request_time 字段
- 用 curl -I 看响应头 Server 字段,确认请求是否真的到达了 Apache
不复杂但容易忽略









