2

我想通过扩展现有的 CI_Log 类将系统错误日志存储到数据库中。到目前为止,这就是我所做的

class MY_Logger extends CI_Log{
    public function __construct(){
        parent::__construct();
    }

    function write_log($level='error', $msg, $php_error = FALSE){

        $result = parent::write_log($level, $msg, $php_error);
        $ci =& get_instance();
        $ci->load->library('user_agent');
        if ($result == TRUE && strtoupper($level) == 'ERROR') {

            $gmtoffset = 60*60*5;
            $post = array(
                'log_type' => $level,
                'log_message' => $msg,
                'log_php_message' => $php_error,
                'log_ip_origin' => $this->input->ip_address(),
                'log_user_agent' => $this->agent->agent_string(),
                'log_date' => date("Y-m-d H:i:s",time() + $gmtoffset)
            );

            $ci->db->insert('system_log', $post);
        }

        return $result;
    }
}

我在 autoload.php 和 config.php 中配置了以下内容

$autoload['libraries'] = array('database', 'session', 'xmlrpc', 'user_agent');
$config['log_threshold'] = 1;

但是,当我对其进行测试时,它不会将错误存储到数据库中(尽管它会正确显示和写入日志)

谁能指出我在这里错过了什么?

ps:

更改了代码以扩展 CI_Exceptions 也无法正常工作:

class MY_Exceptions extends CI_Exceptions{
    function __construct(){
        parent::__construct();
    }

    function log_exception($severity, $message, $filepath, $line){

        //$result = parent::write_log($level, $msg, $php_error);
        $ci =& get_instance();
        //if ($result == TRUE && strtoupper($level) == 'ERROR') {

            $gmtoffset = 60*60*5;
            $post = array(
                'log_type' => $severity,
                'log_message' => $message,
                'log_php_message' => $line,
                'log_ip_origin' => $ci->input->ip_address(),
                'log_user_agent' => $ci->agent->agent_string(),
                'log_date' => date("Y-m-d H:i:s",time() + $gmtoffset)
            );

            $ci->db->insert('system_log', $post);
        //}
        parent::log_exception($severity, $message, $filepath, $line);
        //return $result;
    }
}
4

4 回答 4

0

问题的发生是因为在 CI_Controller 单例可用之前使用了 log_message() 函数 - 它利用了 Log 库。

您可能需要添加检查以查看 CI_Controller 类是否可用,如果可用,则使用 get_instance() 函数。然后,在使用 $CI 时,您必须首先确保它的设置正确(或者如果您不使用构造函数来分配 $CI,则只需在第一个检查的 if 语句中进行设置)。

您可能正在尝试记录控制器中发生的错误,这意味着届时数据库功能将可用。对于某些核心文件初始化时出现的早期调试消息,您将没有数据库日志记录。

于 2014-03-21T12:53:13.667 回答
0

我相信我前一阵子尝试过,并得出结论认为不应引用 MY_Log 中的 CI 实例,因为它尚不可用(或尚未始终构建)。

于 2013-08-08T13:10:01.807 回答
0

我在加载顺序方面遇到了类似的问题。我的目标是将 CI 日志重定向到 MonoLog,并将任何错误通过电子邮件发送给我。我想使用已经存在的库框架来加载 Monolog 和 SwiftMail,但这不可用。

我从 CI_Log 中的 get_config 加载了配置设置,但这仅包括来自 config.php 的值(而不是来自任何其他配置文件)。我使用 get_config 函数作为基础来创建另一个函数来加载其他配置文件。然后,这允许我加载我的电子邮件设置。然后我为 Monolog 和 Swiftmail 创建了新的加载器。它有点乱,但它有效。

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

include_once APPPATH . 'libraries/Swift_Mail/swift_required.php';
require_once APPPATH . 'libraries/common/ClassLoader.php';

use MyApp\Common\ClassLoader,
Monolog\Logger,
Monolog\Handler\RotatingFileHandler,
Monolog\Handler\SwiftMailerHandler,
 Psr\Log\LoggerInterface;

class MY_Log extends CI_Log  {

/** @var \Swift_Mailer  */
private $mailer;

/** @var  $logger LoggerInterface */
protected  $logger;

private $cfg;

public function __construct()
{
    parent::__construct();
    $masterConfig = &get_config(); //This is a config array, not the CI Config object
    $emailConfig = $this->GetConfig('email');
    $this->cfg = array_merge($masterConfig, $emailConfig);

    $this->InitMailer();
    $this->InitLogger();
}

/**
 * There is no exposed CI way to load the email config file, so this allows us to load it.
 * The logic is based on the get_config function in CI.
 * @param $configName
 * @return null
 */
function GetConfig($configName)
{
    $config = null;

    // Is the config file in the environment folder?
    if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/'.$configName.'.php'))
    {
        $file_path = APPPATH.'config/config.php';
    }

    // Fetch the config file
    if ( ! file_exists($file_path))
    {
        exit('The configuration file does not exist.');
    }

    require($file_path);

    // Does the $config array exist in the file?
    if ( ! isset($config) OR ! is_array($config))
    {
        exit('Your config file does not appear to be formatted correctly.');
    }

    return $config;
}

/**
 * This mirrors the init in the SwiftMail Loader.  This is required b/c
 * libraries are not loaded at this point.
 */
protected function InitMailer()
{
    $transport = Swift_SmtpTransport::newInstance
        ($this->cfg['smtp_host'],
            $this->cfg['smtp_port']);

    $transport->setTimeout(20); //Amazon Internal Timeout of 5s, just giving a buffer

    if(array_key_exists('smtp_user',$this->cfg))
    {
        $transport->setUsername($this->cfg['smtp_user']);
    }

    if(array_key_exists('smtp_pass',$this->cfg))
    {
        $transport->setPassword($this->cfg['smtp_pass']);
    }

    if(array_key_exists('smtp_crypto',$this->cfg))
    {
        $transport->setEncryption($this->cfg['smtp_crypto']);
    }

    /** @var  $mailer Swift_Mailer*/
    $this->mailer = Swift_Mailer::newInstance($transport);
}

/**
 * Setup monolog.
 */
protected function InitLogger()
{
    $loader = new ClassLoader("Psr", APPPATH . 'libraries');
    $loader->register();

    $loader = new ClassLoader("Monolog", APPPATH . 'libraries');
    $loader->register();

    $logLevel = Logger::ERROR;

    /* CI Error levels
     *  |   0 = Disables logging, Error logging TURNED OFF
        |   1 = Error Messages (including PHP errors)
        |   2 = Debug Messages
        |   3 = Informational Messages
        |   4 = All Messages
     */

    switch($this->cfg['log_threshold'])
    {
        case 0:
            $logLevel = Logger::ERROR; //We still want errors.
            break;
        case 1:
            $logLevel = Logger::INFO;
            break;
        case 2:
            $logLevel = Logger::DEBUG;
            break;
        case 3:
            $logLevel = Logger::INFO;
            break;
        case 4:
            $logLevel = Logger::DEBUG;
            break;
    }

    /** @var  $message Swift_Message*/
    $message = Swift_Message::newInstance('MyApp Error - '.ENVIRONMENT)
        ->setFrom($this->cfg['FROM_ADDR'])
        ->setTo($this->cfg['ERROR_ADDR']);

    $swiftMailHandler = new SwiftMailerHandler($this->mailer, $message, Logger::ERROR);


    $this->logger = new Logger('myapp');
    $this->logger->pushHandler(new RotatingFileHandler(APPPATH.'logs/myapp.log', 0, $logLevel, true, 0666));
    $this->logger->pushHandler($swiftMailHandler);
}


public function write_log($level = 'error', $msg, $php_error = FALSE)
{
    parent::write_log($level, $msg, $php_error);

    if($level === 'error')
    {
        $this->logger->error($msg);
    }
    elseif($level === 'debug')
    {
        $this->logger->debug($msg);
    }
    else
    {
        $this->logger->info($msg);
    }
}

}

于 2015-05-13T02:14:46.030 回答
0

@Jeremy 在您的一条评论中,您提到您的记录器类存储在文件夹中。相反,它应该放在名为 MY_Log.php的核心文件夹下。有关更多详细信息,请参阅以下链接:

https://codeigniter.com/user_guide/general/core_classes.html#extending-core-class

唯一的问题是文件命名约定并将其放置在错误的文件夹中。至于你的代码,我已经测试过了,它可以正常工作。我知道这是一个老问题,但知道相同的解决方案,所以分享了它。

于 2019-11-09T08:21:24.513 回答