Prototype C++ Extension

When functions are invoked in this class, we have a business requirement to log that fact. In order to do that, we add a call to the logger at the beginning of the function.

class RequiresLogging
{

	public function secretAction()
	{
		Logger::log( "notice", "Secret action performed by user " . $_SESSION['user'] );
		// perform secret action...
	}

}

This doesn't seem like much work, but of course there will not be just one ation performed by this class. Also, the calls to the logger are littered everywhere. Because we all like abstraction so much, enabling via attributes will provide a simplistic and very maintainable solution.

In order to make this work, the extension has one main function add_function_hook(). The function works a lot like an Aspect Oriented technique, whereby a function call is intercepted and redirected to a function specified by the developer. The difference is that the function is only intercepted if it has a particular attribute in its comments. Essentially, every time a function is called, the extension:

  1. Checks for any attributes
  2. Searches for any function hooks that have been added for those attributes
  3. Invokes those functions
  4. Returns control back to the destination function

So to implement the above code in an attribute oriented manner, we will need to:

  1. Define an attribute which declares that a function needs to be logged
  2. Create a function which will get invoked every time the log attribute is present
  3. Add a function hook so that every time the log attribute is found, the log function is invoked
class RequiresLogging
{

	/**
	 * @log notice "Secret action performed by user [user]
	 */
	public function secretAction()
	{
		// perform secret action...
	}

}

function performLog( $message )
{
	$parts = split( " ", $message, 2 );
	$level = $parts[0];
	$message = $parts[1];
	Logger::log( $level, $message );
}

add_function_hook( "log", "performLog" );

$object = new RequiresLogging();
$object->secretAction();

The amount of boiler plate code is no different from, say, a custom error handler in PHP, yet once done, logging becomes extermely simple. I have also played around with other parameters to add_function_hook, especially one which prevents the original destination function (secretAction in our example) from being executed if the registered hook function returns false after analysing the attributes. This would allow for low level permissioning of functions, at the Zend engine level.