Last week I read an interesting post about logging your messages into a Mongo database (I must admite that I didn’t know what a Mongo DB was until that day). This made me think about an experiment, and this is it.
The experiment
According to the post intro and the post title, you don’t need to be a genius to guess what the experiment is about. Yes, as you should probably notice, this is about developing a logger which update a twitter account with the symfony log messages. The twitter account is @fTwittyLogger (wich is the nickname I gave it).
sfLogger class
First off, some theory. Every logger you develop must inherit from the abstract class sfLogger. As clients of this code we are only concerned about implementing the sfLogger::doLog($message, $priority) method which takes two arguments, the message to log and the priority of this message, which can be one of the next constants: EMERG, ALERT, CRIT, ERR, WARNING, NOTICE, INFO and DEBUG.
The methods sfLogger:initialize() and sfLogger::shutdown() are executed at the begining and the end of the process, and may be useful to set some variables, close database connections, etc.
Our logger, fTwittyLogger
// lib/fTwittyLogger.class.php <?php class fTwittyLogger extends sfLogger { protected $format = '[%priority%] %message%'; public function initialize(sfEventDispatcher $dispatcher, $options = array()) { parent::initialize($dispatcher, $options); if (!$this->hasOption('user')) { throw new sfInitializationException(sprintf('You must provide the twitter username account')); } if (!$this->hasOption('pass')) { throw new sfInitializationException(sprintf('You must provide the twitter password account')); } $this->user = $this->getOption('user'); $this->pass = $this->getOption('pass'); return true; } protected function doLog($message, $priority) { $this->tweet(strtr($this->format, array( '%message%' => $message, '%priority%' => $this->getPriority($priority)) )); } protected function getPriority($priority) { return sfLogger::getPriorityName($priority); } public function hasOption($option) { return array_key_exists($option, $this->options); } private function tweet($message) { $context = stream_context_create(array( 'http' => array( 'method' => 'POST', 'header' => sprintf("Authorization: Basic %s\r\n", base64_encode($this->user.':'.$this->pass)). "Content-type: application/x-www-form-urlencoded\r\n", 'content' => http_build_query(array('status' => $message)), 'timeout' => 5, ), )); $ret = file_get_contents('http://twitter.com/statuses/update.xml', false, $context); return false !== $ret; } }
From top to bottom:
initialize()check there is an username and password for the Twitter accountdoLog()twits the message.tweet()method is a copy of this post
Using fTwittyLogger, modifying factories.yml
The last thing to do is to notify symfony that we are no longer using the default logger and we want to use our new one:
// app/config/factories.yml
prod:
logger:
class: fTwittyLogger
param:
loggers: ~
user: fTwittyLogger
pass: symfony
NOTE: As you can see, the password is there. It's not a slip. I did it so you don't have to create "zombie" accounts just in case you want to give it a try.
... this is nonsense
Before someone attack me without mercy, I would like to say I am aware about how useless and unpractical this is. Twitter just let you write 140 characters and the data is public domain, but this post is about learning something new rather than something practical. Hope you enjoy it!