PHP内核函数研究之error_log[原创]
作者 斯人 | 发布于 2012 年 6 月 19 日
PHP PHP内核

PHP有一个很强大的日志处理函数:error_log,

我们可以用它来记录我们程序中出现的错误,比如SQL错误等。

通过 PHP手册,我们可以知道,该函数可以向服务器、文件或远程目标发送一个错误日志。

它接受四个参数:
error 必需。要记录的错误消息。
type 可选。规定错误记录的类型。
可能的记录类型:
0 – 默认。根据在 php.ini 文件中的 error_log 配置,错误被发送到服务器日志系统或文件。
1 – 错误被发送到 destination 参数中的地址。只有该类型使用 headers 参数。
2 – 通过 PHP debugging 连接来发送错误。该选项只在 PHP 3 中可用。
3 – 错误发送到文件目标字符串。
destination 可选。规定向何处发送错误消息。该参数的值依赖于 “type” 参数的值。
headers 可选。只在 “type” 为 1 时使用。
规定附加的头部,比如 From, Cc 以及 Bcc。由 CRLF (\r\n) 分隔。
注释:在发送电子邮件时,必须包含 From 头部。可以在 php.ini 文件中或者通过此参数设置。

error_log函数支持四种方式记录错误日志
1.到默认的文件
type为0.
根据在 php.ini 文件中的 error_log 配置,错误被发送到服务器日志系统或文件。
2.邮件
type 为1.

error_log("this is a test string",1,"imsiren@163.com","From:imsiren@163.com");

很简单,它可以向某个邮箱发送邮件,第三个参数是收件人,第四个是发送人的邮箱
3
通过 PHP debugging 连接来发送错误。该选项只在 PHP 3 中可用。
我从来没用过
4.发送到文件
type=3

error_log("this is a test string",3,"/home/admin/log/error_log");

这种 方式,是我们经常用到的,将我们指定的错误内容写入到某一个文件。
==============================================================================
下面看看PHP是如何实现的error_log
在ext/tandard/basic_functions.c文件中:

PHP_FUNCTION(error_log)
{
        char *message, *opt = NULL, *headers = NULL;
        int message_len, opt_len = 0, headers_len = 0;
        int opt_err = 0, argc = ZEND_NUM_ARGS();
        long erropt = 0;

        if (zend_parse_parameters(argc TSRMLS_CC, "s|lss", &message, &message_len, &erropt, &opt, &opt_len, &headers, &headers_len) == FAILURE) {
                return;
        }

        if (argc > 1) {
                opt_err = erropt;
        }

        if (opt_err == 3 && opt) {
                if (strlen(opt) != opt_len) {
                        RETURN_FALSE;
                }
        }

        if (_php_error_log_ex(opt_err, message, message_len, opt, headers TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
        }

        RETURN_TRUE;
}

这个没什么说的,检测传入过来的参数,然后调用_php_error_log_ex函数。
看看它的定义

PHPAPI int _php_error_log_ex(int opt_err, char *message, int message_len, char *opt, char *headers TSRMLS_DC) /* {{{ */
{
        php_stream *stream = NULL;

        switch (opt_err)
        {
                case 1:         /*send an email */
                        if (!php_mail(opt, "PHP error_log message", message, headers, NULL TSRMLS_CC)) {
                                return FAILURE;
                        }
                        break;

                case 2:         /*send to an address */
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "TCP/IP option not available!");
                        return FAILURE;
                        break;

                case 3:         /*save to a file */
                        stream = php_stream_open_wrapper(opt, "a", IGNORE_URL_WIN | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
                        if (!stream) {
                                return FAILURE;
                        }
                        php_stream_write(stream, message, message_len);
                        php_stream_close(stream);
                        break;

                case 4: /* send to SAPI */
                        if (sapi_module.log_message) {
                                sapi_module.log_message(message);
                        } else {
                                return FAILURE;
                        }
                        break;

                default:
                        php_log_err(message TSRMLS_CC);
                        break;
        }
        return SUCCESS;
}

case 1:php_mail函数会根据我们php.ini里面sendmail_path的配置来发送邮件;
case 2:这个就不说了,我从来没用过
case 3:通过IO函数写入到文件中。
case 4:这个可以通过sapi接口记录我们的日志内容
default: 根据 error_log的配置,将日志写到该文件中。。

原文出处:http://www.imsiren.com/archives/617