AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 962004
Accepted
Craig Francis
Craig Francis
Asked: 2019-04-09 03:01:18 +0800 CST2019-04-09 03:01:18 +0800 CST 2019-04-09 03:01:18 +0800 CST

从 PHP-FPM 将自定义变量添加到 Apache 访问日志

  • 772

在 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 版本

apache-2.4
  • 1 1 个回答
  • 1367 Views

1 个回答

  • Voted
  1. Best Answer
    Craig Francis
    2019-12-25T03:14:34+08:002019-12-25T03:14:34+08:00

    如果您只记录处理时间并使用 nginx,则来自@MichaelHampton 的建议可以通过记录$upstream_response_time变量来起作用。

    但我想继续使用 Apache,并存储额外的详细信息(用户 ID、处理某些任务的时间等)......

    我的解决方案是创建一个单独的日志文件,PHP 可以随时写入该文件(即使在标头已发送之后),我将为每个请求创建一个唯一的(ish)参考代码(这样两个日志可以是加入)。

    首先,让您的 PHP 脚本生成参考代码,并将其作为标头发送:

    <?php 
    
    // A more compact uniqid - which uses hex encoding, and a full UNIX timestamp
    
    $start = microtime(true);
    $sec = floor($start);
    $usec = round(($start - $sec) * 1000000); // Only accurate to 6 decimal places.
    
    $sec -= strtotime('-' . date('w', $sec) . ' days, 00:00:00', $sec); // Time since Sunday 00:00, max value = 604800 (60*60*24*7)
    
    $code = '';
    foreach([$sec, $usec, rand(100000, 999999)] as $code_part) {
        $a = dechex($code_part); // decbin returns a string
        $a = hex2bin(((strlen($a) % 2) == 0 ? '' : '0') . $a);
        $a = base64_encode_rfc4648($a);
        $code .= str_pad($a, 4, '.', STR_PAD_LEFT); // 4 characters max = 999999 -> "0f423f" (hex) -> "D0I/" (base64)
    }
    
    define('REQUEST_START', $start);
    define('REQUEST_CODE', $code);
    
    header('X-Request-Code: ' . $code); // For Apache
    
    ?>
    

    Apache 可以记录该参考代码(更多信息):

    Header always note "X-Request-Code" "Request-Code"
    Header always unset "X-Request-Code"
    
    LogFormat "%h %l %u [%{%Y-%m-%d %H:%M:%S}t] [%{Request-Code}n] \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" inc_ref
    
    CustomLog /path/to/access_log inc_ref
    

    然后你可以添加一个类似的register_shutdown_function()东西:

    <?php 
    
    $log_values = [
            date('Y-m-d H:i:s'),
            REQUEST_CODE,
            $user_id,
            $_SERVER['REMOTE_ADDR'],
            $_SERVER['REQUEST_METHOD'],
            $_SERVER['REQUEST_URI'],
            http_response_code(),
            round((microtime(true) - REQUEST_START), 4),
        ];
    
    if (($fp = fopen($log_file, 'a')) !== false) {
        fputcsv($fp, $log_values);
        fclose($fp);
    }
    
    ?>
    

    由于懒惰的原因,我正在重复访问日志中的信息(例如,grep 单个日志文件)。

    • 0

相关问题

  • Apache2 - SSL 不工作

  • Apache <VirtualHost> 标签,如果客户端的 IP = x 则不重定向... 怎么做?

  • 我无法启用我的网站?[关闭]

  • SELinux 阻止 Apache 写入文件

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve