Logging errors with CodeIgniter

Logging errors which occur within your CodeIgniter application doesn't have to be limited to looking at the PHP or Apache logs; you can enable CodeIgniter to handle and log errors and other behaviors and events at certain points in your code using CodeIgniter's logging functionality. This facility can be particularly useful (if you set it up correctly) to track a user's journey and progress through the system and should something go wrong with whatever they're doing, you can look in the logs and trace what they did and when, and get a better idea of what (if at all) went wrong and hopefully think about how to prevent it from occurring again.

In this recipe, we're going to look at using the logging functionality within CodeIgniter and to track if something goes wrong with an operation.

Getting ready

We'll need to set the log reporting level in the config file so that CodeIgniter knows which level of logging messages to report on. The log's folder should also have write access, so perform the following steps:

  1. Open the /path/to/codeigniter/application/config/config.php file and find the following line:
    $config['log_threshold'] = 0;

    You can change the value of the log_threshold config array element to one of the five states, as shown in the following table:

    State

    Usage

    Description

    0

    -

    CodeIgniter will not log anything.

    1

    log_message('error', 'Some Text')

    CodeIgniter will log error messages.

    2

    log_message('debug', 'Some Text')

    CodeIgniter will log debugging messages.

    3

    log_message('info', 'Some Text'),

    CodeIgniter will log information messages.

    4

    All of the above

    CodeIgniter will log everything.

    For our recipe, I have set the value to 4 as I want to log any error messages or information messages that CodeIgniter might generate for me.

  2. Look for the line:
    $config['log_path'] = '/path/to/log/folder/';.

    Ensure that /path/to/log/folder/ is set correctly in $config[' log_path'] and that the folder specified has write permissions (otherwise, CodeIgniter cannot write a log file to that folder).

How to do it...

We're going to use (as it was convenient) the Using CodeIgniter caching recipe, mentioned earlier in this chapter, and alter it in such a way as to apply CodeIgniter logging. In this recipe, we've changed its name to cache_log.php (to keep it separate from rss_cache.php). So, if you haven't already done so (don't forget to change the name, highlighted in the following code):

  1. Create the /path/to/codeigniter/application/controllers/cache_log.php file and add the following code to it (the changes are highlighted):
    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'),
    
    class Cache_log extends CI_Controller {
      function __construct() {
        parent::__construct();
        $this->load->helper('url'),
        $this->load->helper('xml'),
        $this->load->driver('cache', array('adapter' => 'apc'));
      }
    
      public function index() {
        $raw_feed = '<?xml version="1.0" encoding="ISO-8859-1" ?>
        <rss version="2.0">
        <channel>
          <title>RSS Feed</title>
            <link>http://www.domain.com</link>
            <description>General Description</description>
          <item>
            <title>RSS Item 1 Title</title>
            <link>http://www.domain1.com/link1</link>
            <description>Description of First Item</description>
          </item>
          <item>
            <title>RSS Item 2 Title</title>
            <link>http://www.domain2.com/link2</link>
            <description>Description of Second Item</description>
          </item>
          <item>
            <title>RSS Item 3 Title</title>
            <link>http://www.domain3.com/link3</link>
            <description>Description of Third Item</description>
          </item>
        </channel>
        </rss>';
    
        $feed = new SimpleXmlElement($raw_feed);
    
        if (!$feed) {
          log_message('error', 'Unable to instantiate SimpleXmlElement.'),
        } else {
          log_message('info', 'SimpleXmlElement was instantiated correctly.'),
        }
    
        if (!$cached_feed = $this->cache->get('rss')) {
          foreach ($feed->channel->item as $item) {
            $cached_feed .= $item->title . '<br />' .$item->description . '<br /><br />';
          }
    
            $this->cache->save('rss', $cached_feed, 7);
            log_message('info', 'Cache item saved.'),
        }
    
        echo $this->cache->get('rss'),
        
      }
    
      public function clear_cache() {
        if (!$this->cache->clean()) {
          log_message('error', 'Unable to clear Cache.'),
        } else {
          log_message('info', 'Cache cleared.'),
        }
    
        redirect('rss_cache'),
      }
    }
    ?>

    If all goes well you shouldn't have any errors, but you should have some DEBUG data in the config file. When you open that file you should see something similar to:

    <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed'), ?>
    
    DEBUG - 2013-09-24 19:46:11 --> Config Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Hooks Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Utf8 Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> UTF-8 Support Enabled
    DEBUG - 2013-09-24 19:46:11 --> URI Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Router Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Output Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Security Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Input Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> XSS Filtering completed
    DEBUG - 2013-09-24 19:46:11 --> XSS Filtering completed
    DEBUG - 2013-09-24 19:46:11 --> XSS Filtering completed
    DEBUG - 2013-09-24 19:46:11 --> CRSF cookie Set
    DEBUG - 2013-09-24 19:46:11 --> Global POST and COOKIE data sanitized
    DEBUG - 2013-09-24 19:46:11 --> Language Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Loader Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Database Driver Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Session Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Helper loaded: string_helper
    DEBUG - 2013-09-24 19:46:11 --> Encrypt Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Session routines successfully run
    DEBUG - 2013-09-24 19:46:11 --> XML-RPC Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Controller Class Initialized
    DEBUG - 2013-09-24 19:46:11 --> Helper loaded: url_helper
    DEBUG - 2013-09-24 19:46:11 --> Helper loaded: xml_helper
    INFO  - 2013-09-24 19:46:11 --> SimpleXmlElement was instantiated correctly.
    INFO  - 2013-09-24 19:46:11 --> Cache item saved.
    DEBUG - 2013-09-24 19:46:11 --> Final output sent to browser
    DEBUG - 2013-09-24 19:46:11 --> Total execution time: 0.0280

    You can see the info items we set in the code written in the log; I've highlighted them so that they stand out.

How it works...

You can see that we have added some conditional statements on various stages of the controller's execution, checking for the return value of certain CodeIgniter functions (the changes are highlighted in the previous code). Depending on that returned value (either TRUE or FALSE), we will write to the logs using the CodeIgniter log_message() function, but let's take a closer look at those messages and when each of them is triggered.

First off, we'll try to instantiate a new SimpleXmlElement() object. If we get a returned object, an info message is written to the log (SimpleXmlElement() was instantiated correctly). If there was an error, we write an error message to the log (unable to instantiate SimpleXmlElement()); take a look at the following code snippet:

$feed = new SimpleXmlElement($raw_feed);

if (!$feed) {
  log_message('error', 'Unable to instantiate SimpleXmlElement.'),
} else {
  log_message('info', 'SimpleXmlElement was instantiated correctly.'),
}

You can see that we're using CodeIgniter's logging functionality to write messages to the log file, and define those messages as either errors or info; this can be helpful in debugging the user's journey as you'll know what is a genuine error, and what is information entered by you to help you in the logs.

Logging style

I find it useful to write my log messages like the following code snippet:

 log_message('info', ' **** ' . __LINE__ . ' – This is a message.'),

In the preceding code snippet, we're defining the message as info, but we begin the message with four asterisks (****). This'll make the message stand out in the logs as we're viewing them, next comes the __LINE__ argument (to let you know where in the script it was triggered), followed by the actual message--here it is the unimaginative--' - This is a message.'

You may wish to add __FILE__, __CLASS__, or __FUNCTION__ for greater accuracy, depending on your needs.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.97.157