Notice: I no longer maintain this site regularly. While some content is still relevant, most of it will be migrated to my company site soon. To see what I'm up to go to focuslabllc.com.


Logging Actions in your ExpressionEngine Add-ons

9 comments

Written on March 1st, 2010 by Erik Reagan

Logging Actions in your ExpressionEngine Add-ons

I've recently given some thought to a piece of EE that I have never had a great need for. Control Panel logging. Out of the box, ExpressionEngine logs certain actions that are performed in the CP saving the Site ID, Member, IP Address of that member, date/time and the action performed. This can be very useful when trying to figure out when something happened and who may have done it. It can also help see how many people might be logging in under the same account from various locations (IPs). This is all great but quite limited considering the number of actions for which this occurs.

Developers: Throughout this article the word "action" is not referring to the exp_actions table which is used in tandem with Modules. It is simply referring to "an act that is performed" in the Control Panel.

General Notice: This article was written with a focus on EE 1.6.x. The code for EE2 is slightly different and there is a single sample code block at the bottom of the article.

What is logged?

Without extending ExpressionEngine at all, the following actions are logged:

  • A member logs in
  • A member logs out
  • A SuperAdmin logs in as another member
  • Member group settings are changed
  • A new member profile is created
  • A member profile field is deleted
  • A member's email address is updated
  • A member's username/password is updated
  • A weblog/channel's preferences are updated
  • A weblog/channel gets deleted
  • A category field gets deleted
  • A category group is created, updated or deleted
  • A status group is created, updated or deleted
  • A field group is created, updated or deleted
  • A custom field is deleted
  • An upload preference is deleted

As you see from the list above, the primary function of the Control Panel Log is to record more administrative actions to the log. That's a useful thing to have if you need to track down who may have performed an administrative action. However, what if you need to know who last saved a certain weblog/channel entry or who posted the last entry? What about logging actions on your custom Extensions or Modules? This is certainly doable with some simple code so let's take a look now.

Logging your own actions

In order to log actions you first need to load the Logger class in ExpressionEngine. This class is located in system/cp/cp.log.php and contains functions for logging and clearing three logs: the CP log (what we are talking about), the Search Term log and the Throttle log. Today we are just looking at a single function, log_action(). The function only takes a single parameter and will only be executed on a logged in member. This isn't something that should necessarily be used in your templates (though it is technically possible).

The rest of the article will be in the context of your add-on so open up an extension or module you've written or just test this out in a template for the time being. I advise you only to this in a test environment until your comfortable and always backup your database when trying something new.

To load the class we will first double check to make sure the class doesn't already exist (always good practice) then use PHP's require() function followed by creating a new log object. That looks like this:

<?php

if( ! class_exists('Logger') )
{
   
// PATH_CP is the system path to your cp class files and EXT is
   // the file extension. Both are constants set by EE
   
require PATH_CP 'cp.log' EXT;
}

// I tend to use all caps to stay consistent with EE's approach to
// naming objects 
$LOG = new Logger;

?> 

Now that we have the Logger class loaded into our add-on we just need to log an action. This part is as easy as it gets. As I mentioned earlier, the log_item() function only takes one parameter which is either the string message or an array of messages that you send it. Just to do a quick test let's throw a random string in there.

<?php

if( ! class_exists('Logger') )
{
   
// PATH_CP is the system path to your cp class files and EXT
   // is the file extension. Both are constants set by EE
   
require PATH_CP 'cp.log' EXT;
}

// I tend to use all caps to stay consistent with EE's approach to
// naming objects 
$LOG = new Logger;

// Log a test string
$LOG->log_action("Testing new CP log item");

?> 

Our results

Loading the extension/module you're testing this with will execute the logging so now go view your CP Log located under Admin → Utilities → View Control Panel Log. You should now see the new item logged like in the image below. See, that wasn't so hard was it?

Logged item screenshot

You can turn your message string into an array and produce multiple lines of text if you'd like. Consider the following example:

<?php

if( ! class_exists('Logger') )
{
   
// PATH_CP is the system path to your cp class files and EXT
   // is the file extension. Both are constants set by EE
   
require PATH_CP 'cp.log' EXT;
}

// I tend to use all caps to stay consistent with EE's approach to
// naming objects 
$LOG = new Logger;

// Log a test array producing multiple lines of text
$LOG->log_action(array("This is line 1 of my message","This is line 2 of my message"));

?> 
Logged item screenshot 2

That would produce a logged item like the one seen in the picture to the right. You can create as many lines as you want/need using an array instead of a string. This can be particularly helpful if you want a message that is more than just a few words long which includes more specifics of an action.

So how can I use this?

I'm glad you asked! You can use this just about anywhere you might need inside of your Module or Extension. Let's take my Redirect Helper Lite module and use it as an example. If a user has permission to use that module they can create, modify and delete redirect rules for their website. Say I want to add a log record every time a redirect rule is created, modified or deleted. I simply add something like this to each method performing those specific actions:

<?php

// I'm excluding any additional code that would be in or around my method

// Log record of user updating the redirect entry using a variable
// available within my method
$LOG->log_action("Redirect Helper Lite: '".$fields['redirect_name']."' was modified");

?> 

This will record the name of the redirect entry (based on the form results, not relevant to our topic). Reloading our Log should show the new action as seen in the image below.

Logged item from Redirect Helper Lite screenshot

EE2 Sample Code

Here is a sample of how you would approach this in your EE2 add-ons. It's even easier than the 1.x version due to the way libraries are loaded in CI/EE2. (Thanks to Wes for pointing that out in the comments.)

<?php

$this
->EE->load->library('logger');
// Log a test string
$this->EE->logger->log_action("Testing new CP log item");

?> 

Go forth, Big Brother

As you can see, you can log actions provided it is either your custom module or you tap into an existing Hook in the system. It's pretty powerful but there's no need to go crazy. With this knowledge combined with an understanding of the available hooks in the system, you can extend the usefulness of the Control Panel Log.

Enjoy!

Comments

Awesome work, I was just about to write this same functionality myself. :)

Nathan Pitman on Mar 18th, 2010 at 10:07 am

This kicks ass. Thanks.

Rob Sanchez on Mar 30th, 2010 at 4:48 pm

Have you done this for any EE2 addons yet?

Wes Baker on Oct 29th, 2010 at 2:08 pm

Wes,

I hadn’t tested it until your comment. I opened EE2 up and checked things out. It looks like the class isn’t loaded already so we have very similar code. I’ve updated the blog post with the new EE2 sample code so take a look at the bottom of the post.

Thanks for checking in!

Erik Reagan on Oct 30th, 2010 at 4:46 pm

Erik, I also tinkered around with it yesterday, and this worked for me as well:

$this->EE->load->library('logger');
$this->EE->logger->log_action("Testing new CP log item"); 

Wes Baker on Oct 31st, 2010 at 11:07 am

Wes,

Thanks for posting that code. I was fresh out of a 1.x custom module when I updated the post and my mind was not in CI/EE2 mode. Your code is the “correct” and advised way of loading the library and I’ve actually updated the post to reflect that.

Thanks!

Erik Reagan on Nov 2nd, 2010 at 5:40 am

Is there any way to capture activity on the public facing side of the site? I would like to integrate this on the front end of the site.

djheru on Nov 4th, 2010 at 2:14 pm

Technically you could use the code above to still log front-end actions. You’d just use PHP in your templates. However, the Control Panel log is best left to Control Panel actions. You could certainly create a custom Module that logged actions as users interacted with your site. Is that what you’re thinking?

Erik Reagan on Nov 4th, 2010 at 2:16 pm

Yes, I have a custom module that extends Freeform and passes the form post on to a 3rd party API. I am getting an intermittent problem, and I would like to see what is happening within a moderately complicated conditional embed.

djheru on Nov 4th, 2010 at 2:46 pm

Your Words of Wisdom

Commenting is not available in this section entry.