Ver índice de contenidos del libro

18.4. El perfilador

Cuando se encuentra activado, el perfilador de Symfony2 recoge información útil sobre cada petición recibida por tu aplicación y la almacena para su posterior análisis. Utiliza el perfilador en el entorno de desarrollo para que te ayude a depurar tu código y mejorar el rendimiento; actívalo en el entorno de producción para descubrir la causa de los errores.

Normalmente no tendrás que lidiar con el perfilador directamente, ya que Symfony2 proporciona herramientas visuales como la barra de depuración web y el perfilador web. Si utilizas la edición estándar de Symfony2, el perfilador, la barra de depuración web, y el perfilador web, ya están preconfigurados.

Nota El perfilador recopila información para todas las peticiones (peticiones simples, redirecciones, excepciones, peticiones Ajax, peticiones ESI, y para todos los métodos HTTP y todos los formatos). Esto significa que para una única URL, puedes tener varios perfiles de datos asociados.

18.4.1. Visualizando la información del perfilador

18.4.1.1. Usando la barra de depuración web

En el entorno de desarrollo, la barra de depuración web está disponible en la parte inferior de todas las páginas. Esta barra muestra un completo resumen de los datos perfilados y te da acceso instantáneo a una gran cantidad de información útil cuando algo no funciona como esperabas.

Si el resumen presentado por la barra de depuración web no es suficiente, puedes acceder al perfilador web pinchando en el enlace del token, que es una cadena compuesta por 13 caracteres aleatorios.

Nota Si no se puede hacer clic en el token, eso significa que las rutas del perfilador no están registradas (tal y como se explica más adelante).

18.4.1.2. Analizando los datos con el perfilador web

El perfilador web es una herramienta que muestra visualmente los datos recolectados por el perfilador. Puedes usarlo en el entorno de desarrollo para depurar tu código y mejorar el rendimiento; pero también lo puedes utilizar para descubrir la causa de los problemas que ocurren en producción. El perfilador web muestra toda la información recogida por el perfilador en una interfaz web.

18.4.1.3. Accediendo a la información del perfilador

Si no quieres, no es obligatorio utilizar el visualizador para acceder a la información del perfilador. ¿Cómo se puede recuperar la información sobre una petición concreta, después de que se haya producido? Cuando el perfilador almacena datos sobre una petición, le asocia un token, cuyo valor está disponible en la cabecera X-Debug-Token de la respuesta:

$profile = $container->get('profiler')->loadProfileFromResponse($response);
 
$profile = $container->get('profiler')->loadProfile($token);

Truco Cuando el perfilador está habilitado pero no así la barra de depuración web, o cuando desees obtener el token de una petición Ajax, utiliza una herramienta como Firebug para obtener el valor de la cabecera X-Debug-Token.

Usa el método Profiler::find() para acceder a los tokens en función de algún criterio de búsqueda:

// obtiene los 10 últimos tokens
$tokens = $container->get('profiler')->find('', '', 10);
 
// obtiene los 10 últimos tokens de todas las URL que contienen /admin/
$tokens = $container->get('profiler')->find('', '/admin/', 10);
 
// obtiene los 10 últimos tokens de peticiones locales
$tokens = $container->get('profiler')->find('127.0.0.1', '', 10);

Si deseas obtener los datos del perfilador en una máquina diferente a la que generó la información, utiliza los métodos Profiler::export() e Profiler::import():

// en la máquina de producción
$profile = $container->get('profiler')->loadProfile($token);
$data = $profiler->export($profile);
 
// en la máquina de desarrollo
$profiler->import($data);

18.4.1.4. Configuración

Por defecto el perfilador de Symfony2, la barra de depuración web, y el perfilador web ya vienen preconfigurados. Esta es por ejemplo la configuración para el entorno de desarrollo:

# carga el perfilador
framework:
    profiler: { only_exceptions: false }
 
# activa el perfilador web
web_profiler:
    toolbar:             true
    intercept_redirects: true
<!-- xmlns:webprofiler="http://symfony.com/schema/dic/webprofiler" -->
<!-- xsi:schemaLocation="http://symfony.com/schema/dic/webprofiler http://symfony.com/schema/dic/webprofiler/webprofiler-1.0.xsd"> -->
 
<!-- carga el perfilador -->
<framework:config>
    <framework:profiler only-exceptions="false" />
</framework:config>
 
<!-- activa el perfilador web -->
<webprofiler:config
    toolbar="true"
    intercept-redirects="true"
/>
// carga el perfilador
$container->loadFromExtension('framework', array(
    'profiler' => array('only-exceptions' => false),
));
 
// activa el perfilador web
$container->loadFromExtension('web_profiler', array(
    'toolbar'             => true,
    'intercept-redirects' => true,
));

Cuando la opción only-exceptions se establece a true, el perfilador sólo recoge datos cuando tu aplicación lanza una excepción.

Cuando la opción intercept-redirects está establecida en true, el perfilador web intercepta las redirecciones y te permite analizar los datos recogidos antes de seguir la redirección.

Si activas el perfilador web, también debes importar sus rutas:

_profiler:
    resource: @WebProfilerBundle/Resources/config/routing/profiler.xml
    prefix:   /_profiler
<import resource="@WebProfilerBundle/Resources/config/routing/profiler.xml" prefix="/_profiler" />
$collection->addCollection($loader->import("@WebProfilerBundle/Resources/config/routing/profiler.xml"), '/_profiler');

Dado que el perfilador añade algo de sobrecarga, en el entorno de producción sólo deberías activarlo si se producen ciertas circunstancias. La opción only-exceptions limita al perfilador a 500 páginas, pero ¿qué sucede si quieres obtener información cuando la petición viene de una determinada IP? ¿y qué sucede si quieres obtener información detallada sobre una parte del sitio web? En estos casos puedes utilizar la opción matcher:

# activa el perfilador sólo para peticiones entrantes de la red 192.168.0.0
framework:
    profiler:
        matcher: { ip: 192.168.0.0/24 }
 
# activa el perfilador sólo para las URL /admin
framework:
    profiler:
        matcher: { path: "^/admin/" }
 
# ejemplo que combina las dos reglas anteriores
framework:
    profiler:
        matcher: { ip: 192.168.0.0/24, path: "^/admin/" }
 
# utiliza un servicio propio para determinar si se activa el perfilador
framework:
    profiler:
        matcher: { service: custom_matcher }
<!-- activa el perfilador sólo para peticiones entrantes de la red 192.168.0.0 -->
<framework:config>
    <framework:profiler>
        <framework:matcher ip="192.168.0.0/24" />
    </framework:profiler>
</framework:config>
 
<!-- activa el perfilador sólo para las URL /admin -->
<framework:config>
    <framework:profiler>
        <framework:matcher path="^/admin/" />
    </framework:profiler>
</framework:config>
 
<!-- ejemplo que combina las dos reglas anteriores -->
<framework:config>
    <framework:profiler>
        <framework:matcher ip="192.168.0.0/24" path="^/admin/" />
    </framework:profiler>
</framework:config>
 
<!-- utiliza un servicio propio para determinar si se activa el perfilador -->
<framework:config>
    <framework:profiler>
        <framework:matcher service="custom_matcher" />
    </framework:profiler>
</framework:config>
// activa el perfilador sólo para peticiones entrantes de la red 192.168.0.0
$container->loadFromExtension('framework', array(
    'profiler' => array(
        'matcher' => array('ip' => '192.168.0.0/24'),
    ),
));
 
// activa el perfilador sólo para las URL /admin
$container->loadFromExtension('framework', array(
    'profiler' => array(
        'matcher' => array('path' => '^/admin/'),
    ),
));
 
// ejemplo que combina las dos reglas anteriores
$container->loadFromExtension('framework', array(
    'profiler' => array(
        'matcher' => array('ip' => '192.168.0.0/24', 'path' => '^/admin/'),
    ),
));
 
# utiliza un servicio propio para determinar si se activa el perfilador
$container->loadFromExtension('framework', array(
    'profiler' => array(
        'matcher' => array('service' => 'custom_matcher'),
    ),
));