php源代码中的日志模块在哪里?

php源代码中的日志模块在哪里?,php,Php,这是关于php源代码的,而不是php语言本身 我有php的源代码,我想启用一些额外的日志记录。这样做的目的是在需要有人在日志调用中编写代码时记录某些操作。例如,每当有人对数据库进行调用时,都要记录该调用,并将一些连接详细信息发送给记录器。我知道我可以使用mysqli_get_client_stats来获取其中的一些细节,但这需要我编写每个php脚本来获取这些值并打印/发送到记录器,但我更愿意扩展这样的调用,以便为我自动记录这些信息 我应该在源代码中寻找什么来执行此操作?我假设我可以找到我想要自动

这是关于php源代码的,而不是php语言本身

我有php的源代码,我想启用一些额外的日志记录。这样做的目的是在需要有人在日志调用中编写代码时记录某些操作。例如,每当有人对数据库进行调用时,都要记录该调用,并将一些连接详细信息发送给记录器。我知道我可以使用mysqli_get_client_stats来获取其中的一些细节,但这需要我编写每个php脚本来获取这些值并打印/发送到记录器,但我更愿意扩展这样的调用,以便为我自动记录这些信息


我应该在源代码中寻找什么来执行此操作?我假设我可以找到我想要自动启用日志记录的必要函数,但是我还没有弄清楚我将调用什么来记录我想要记录的任何内容。

我不知道你需要编辑PHP源代码来完成这项工作。通过扩展
mysqli
并编写自己的日志例程(每次运行
query()
时都会运行),您可以轻松做到这一点


然后像平常一样调用此连接器。

一种比干预源代码更简单的方法是猴子补丁,使用并重新定义所需的功能

润吉 例如,您可以将旧的
whatever()
函数定义为
old\u whatever()
,并定义一个新的
whatever()
包装函数,该函数记录并调用
old\u whatever()
。要在整个应用程序中执行此操作,可以使用

范例

注意:默认情况下,只能删除、重命名或删除用户空间函数 被改进的。要覆盖内部函数,必须启用
php.ini中的
runkit.internal\u覆盖设置

由于需要在每个脚本上都执行此操作,因此需要在所有脚本中包含上述代码

通常情况下,只将其包含在基本级别,需要脚本或入口点(例如,
index.php
)才能首先执行,并且只执行一次。如果有很多入口点,可以使用
auto\u prepend
。然后真正要做的是创建一个包装器脚本

<?php
    require_once($_SERVER['DOCUMENT_ROOT'] . '/path/to/mysqli_rewriting.php');
?>
注意:monkeypatcher文件必须位于php包含路径中的一个目录中;如果后者是空的,则需要添加一个“/patches”文件夹,然后将monkeypatcher文件放在其中。另见

来源 如果您想修改PHP源代码,我认为最好的办法是利用
syslog
功能。您发现的PHP错误函数将中断处理和/或向错误处理程序发送输出,因此,如果您这样做,您还必须在所有脚本中提供/修改错误处理程序。这会让你重新开始

另一方面,syslog工具确实需要syslog功能,这通常捆绑在Unix平台和。。。在Windows操作系统上不太可靠(事实上,我不了解Windows 7+和Server 2008+的最新版本;它们现在可能正在工作)

如果您决定使用syslog,只需选择一个适当的日志级别发送到您选择的文件。将
syslogd
配置为接收这些消息并将其发送到您想要的任何地方

然后添加
main/php.h
(例如,在第306行附近)

main/main.c
的某处,例如在
php\u verror
之后:

/* {{{ logprintf
*/
int logprintf(const char *format, ...) {
    va_list args;
    char *buffer = NULL;
    int size;
    va_start(args, format);
    size = vspprintf(&buffer, 0, format, args);
    #ifdef HAVE_SYSLOG_H
    /* LOG_LOCAL3 is reserved for local use */
    php_syslog(LOG_LOCAL3, "%s", buffer);
    #endif
    efree(buffer);
    va_end(args);
    return size;
}
/* }}} */
此时,您可以使用与
printf()
相同的语法从PHP代码中的任何位置直接与syslog“对话”

如果需要,您可以使用
#define
来包含发生日志调用的文件名和行,并将其包含在输出中

如果您想记录查询(顺便说一句:注意记录密码和敏感信息…),您可以找到将查询传递到服务器的所有位置,例如

ext/pdo_mysql/mysql_statement.c (line 332)

+++ /* Add logging */
+++ logprintf("running MySQL query: '%s'", stmt->active_query_string);

if (mysql_real_query(H->server, stmt->active_query_string,
    stmt->active_query_stringlen) != 0) {
    pdo_mysql_error_stmt(stmt);
    PDO_DBG_RETURN(0);
}
缺点


请记住,API有许多入口点,甚至来自PHP(准备语句、直接查询、模拟准备查询等)。你需要把它们都记录下来。如果您只想记录MySQL查询(上面的方法允许记录任何您想要的内容),那么让MySQL记录它接收到的查询会让您感觉更好。您可以记录所有的查询,甚至只记录那些比给定时间慢的查询。

您从哪里了解到这种功能的存在?如果我必须开始查找,我会在
Zend/
目录中查找处理函数调用的代码。比如可能
zend_API.c
。另外,xdebug钩住了每个函数调用,所以看看它们是如何实现的可能会有所帮助。例如,您可以调用error_log,这将向php日志发送一条消息。因此,必须有一些内部日志功能才能使此调用正常工作。我想知道这个功能在源代码中的位置以及如何使用它。。因此,如果您启用了xdebug跟踪,然后对输出进行grep处理,您可能会得到您想要的信息吗?如果不是。。。你具体想记录什么?我真的在寻找一种方法来修改php源代码(c代码)来记录事件。它看起来像是
sapi/fpm/fpm/fpm_conf.c
保存了错误日志的函数。我可以简单地在另一个函数中调用该函数吗?或者我应该使用更低的函数吗?这会起作用,但如果我有大量现有脚本,我就必须返回并修改所有这些脚本。事实上,有没有办法创建一个类来像这样扩展查询,让现有脚本使用这个扩展而不是原来的扩展?我的第一个想法是,我必须
包含包含该类的文件,对吗?我偏爱自己
php_value auto_prepend_file "monkeypatcher.php"
#ifdef HAVE_SYSLOG_H
int logprintf(const char *format, ...);
#endif

/* PHPAPI void php_error(int type, const char *format, ...); */
PHPAPI void php_error_docref0(const char *docref TSRMLS_DC, int type, const char *format, ...)
    PHP_ATTRIBUTE_FORMAT(printf, PHP_ATTR_FMT_OFFSET + 3, PHP_ATTR_FMT_OFFSET + 4);
PHPAPI void php_error_docref1(const char *docref TSRMLS_DC, const char *param1, int type, const char *format, ...)
/* {{{ logprintf
*/
int logprintf(const char *format, ...) {
    va_list args;
    char *buffer = NULL;
    int size;
    va_start(args, format);
    size = vspprintf(&buffer, 0, format, args);
    #ifdef HAVE_SYSLOG_H
    /* LOG_LOCAL3 is reserved for local use */
    php_syslog(LOG_LOCAL3, "%s", buffer);
    #endif
    efree(buffer);
    va_end(args);
    return size;
}
/* }}} */
ext/pdo_mysql/mysql_statement.c (line 332)

+++ /* Add logging */
+++ logprintf("running MySQL query: '%s'", stmt->active_query_string);

if (mysql_real_query(H->server, stmt->active_query_string,
    stmt->active_query_stringlen) != 0) {
    pdo_mysql_error_stmt(stmt);
    PDO_DBG_RETURN(0);
}