En todo desarrollo se hacen necesarias herramientas que permitan hacer un seguimiento del código. Hoy voy a mostrar cómo mostrar logs desde PHP directamente a una consola en Firefox. ¡Di adiós a los “echos” y a los “var_dump”!

En primer lugar, debemos tener instalada la extensión Firebug. Por si no lo conocéis, es uno de los plugins más instalados de Firefox y nos es útil para numerosas tareas:

  • Inspeccionar el árbol DOM y HTML.
  • Modificar CSS al vuelo.
  • Monitorizar actividades en la red (¿Qué hace que tarde tanto en cargar mi página?)
  • Depurar código JavaScript.
  • Consola JavaScript
  • Y mucho más (En serio).

Una vez instalado Firebug, toca instalar otra nueva extensión. Se trata de FirePHP. Para que funcione, es necesario tener en Firebug activadas las pestañas de Red y de Consola. De momento está siendo fácil, ¿verdad? Pues ya no nos queda nada :)

Ahora que tenemos el cliente listo, sólo nos queda activarlo en el servidor. Al ser un sistema muy popular, la mayoría de los frameworks traen integradas de serie las bibliotecas necesarias, pero también se pueden usar las bibliotecas nativas si nuestro proyecto no utiliza ningún framework.

En este mini howto voy a mostrar cómo hacerlo funcionar con Zend Framework (Ver casos de uso con la biblioteca genérica).

FirePHP en Zend Framework

Lo primero es inicializar el sistema de logs en el fichero bootstrap:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{

   ...

   protected function _initLogging()
   {
      $this->bootstrap('frontController');
      $logger = new Zend_Log();

      $writer = 'production' == $this->getEnvironment() ?
         new Zend_Log_Writer_Stream(APPLICATION_PATH .
            '/../data/logs/app.log') :
         new Zend_Log_Writer_Firebug();

      $logger->addWriter($writer);

      if ('production' == $this->getEnvironment()) {
         $filter = new Zend_Log_Filter_Priority( Zend_Log::CRIT);
         $logger->addFilter($filter);
      }

      $this->_logger = $logger;
      Zend_Registry::set('log', $logger);
   }
   ...
}

Veamos paso a paso lo que hemos hecho:

  1. Nos aseguramos de que el frontController está inicializado.
  2. Creamos una nueva instancia de la clase Zend_Log.
  3. Por seguridad, si estamos en un entorno de producción, el registro de logs se volcará en el fichero data/logs/app.log. En caso contrario, se mostrará mediante Firebug. Existen muchas más clases que heredan de Zend_Log_Writer_Abstract, como por ejemplo para mandar por correo electrónico, o almacenar en base de datos.
  4. De nuevo, si estamos en un entorno de producción filtramos las alertas a aquéllas que sean, por lo menos, críticas. Existen hasta 7 niveles de prioridad.
  5. Establecemos el atributo $this->_logger.
  6. Guardamos una referencia de $logger en el registro, de modo que éste esté accesible para toda la aplicación.

Bueno ahora está ya todo listo. Nuestro servidor sabe cómo adjuntar estos logs, y nuestro cliente sabe cómo interpretarlos. ¿Qué nos queda? Pues un hola mundo :) Por ejemplo, modifiquemos el método _initLogging() para añadir una nueva línea al final del mismo:

$this->_logger->info('Bootstrap ' . __METHOD__);

Ahora sí que sí. Ya está todo listo. Accedamos a la página, abramos Firebug con las pestañas de consola y de red activadas, y con FirePHP también activado y veamos la magia:

Captura del resultado en Firebug

Captura del resultado en Firebug

Una maravilla que nos permitirá hacer un seguimiento de qué ocurre en cada petición a nuestra página web.

¿Pero cómo funciona todo esto? Fácil: Toda esta información se adjunta en forma de cabeceras HTTP, de modo que nunca interferirán en el cuerpo de la petición. Puedes usarlo por tanto en llamadas AJAX, ficheros binarios como imágenes, etc.

¡Pero espera, que aún hay más!

Profiling de bases de datos

Zend Framework te permite hacer profiling de la base de datos. Por si no sabes qué es esto, es un análisis del comportamiento de una aplicación cuyo objetivo normalmente es optimizar la ejecución. En este caso, podremos conocer cuáles son todas las consultas a base de datos que se han ejecutado, y cuánto tiempo han llevado. ¿Y cómo lo hacemos? Crearemos un nuevo método en el fichero bootstrap:

protected function _initDbProfiler()
{
   if ('production' !== $this->getEnvironment()) {
      $this->bootstrap('db');
      $profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
      $profiler->setEnabled(true);
      $this->getPluginResource('db')
         ->getDbAdapter()
         ->setProfiler($profiler);
      }
 }

En este caso, si la instancia de la aplicación no está en producción, realizaremos lo siguiente:

  1. Iniciamos la base de datos.
  2. Creamos una instancia del profiler especializado de Firebug pasándole como parámetro su etiqueta.
  3. Activamos el objeto profiler.
  4. Y finalmente, activamos el profiling en la base de datos por defecto.

Ahora ya puedes inspeccionar las consultas que hace tu aplicación, minimizar las llamadas, y solucionar cuellos de botella :)