在 mod_php 中,您可以使用该apache_note()
函数在 Apache 访问日志中记录变量:
<?php
apache_note('SCRIPT_TIME', '1234');
?>
使用 Apache 配置:
LogFormat "%h %l %u %t [%D/%{SCRIPT_TIME}n] \"%r\" %>s %b" inc_info
...
CustomLog /path/to/access_log inc_info
但该apache_note()
功能在 PHP-FPM 中不可用。
同样,您不能使用apache_setenv()
或setenv()
设置环境变量(通过 记录%{SCRIPT_TIME}e
)。
一种可能性是设置 Apache 可以使用“%{SCRIPT_TIME}i”记录的标头,但您需要小心不要让敏感信息发送到客户端(例如,了解登录脚本的准确处理时间可能是一种安全措施问题)。但更重要的是,如果内容已经发送到客户端,它就不起作用,因为您不能再发送标头(根据下面的完整示例)。
或者,PHP 可以编写它自己的日志文件,但这会重复很多 Apache 日志已经做的事情,有可能错过日志条目(例如,如果脚本有错误),并且将在 Apache 用户下创建权限(而不是以 root 身份写入)。
只是为了更详细,这是我用来记录脚本处理时间的代码:
<?php
define('SCRIPT_START', microtime(true));
function log_shutdown() {
if (!defined('SCRIPT_END')) {
define('SCRIPT_END', number_format(round((microtime(true) - SCRIPT_START), 4), 4));
}
if (function_exists('apache_note')) {
apache_note('SCRIPT_TIME', SCRIPT_END);
}
}
register_shutdown_function('log_shutdown');
?>
从时间的角度来看,虽然 Apache 确实提供了“%D”来记录“服务请求所花费的时间”,但这在很大程度上取决于用户的互联网连接。
这与我尝试使用以下配置在我的服务器上启用 HTTP/2 有关:
Protocols h2 http/1.1
<FilesMatch \.php$>
CGIPassAuth on
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
SetHandler "proxy:fcgi://127.0.0.1:9001"
</FilesMatch>
同样相关的是Nginx 版本
如果您只记录处理时间并使用 nginx,则来自@MichaelHampton 的建议可以通过记录
$upstream_response_time
变量来起作用。但我想继续使用 Apache,并存储额外的详细信息(用户 ID、处理某些任务的时间等)......
我的解决方案是创建一个单独的日志文件,PHP 可以随时写入该文件(即使在标头已发送之后),我将为每个请求创建一个唯一的(ish)参考代码(这样两个日志可以是加入)。
首先,让您的 PHP 脚本生成参考代码,并将其作为标头发送:
Apache 可以记录该参考代码(更多信息):
然后你可以添加一个类似的
register_shutdown_function()
东西:由于懒惰的原因,我正在重复访问日志中的信息(例如,grep 单个日志文件)。