Uso
Una vez instalado el bundle y definida su clave (key), el reporte de excepciones funciona sin ningún código adicional; url solo se define para una instancia autoalojada. La transmisión de logs y el reporte manual requieren cada uno un paso más.
Captura automática de excepciones
El bundle registra monitor.exception_subscriber, un event subscriber que escucha el evento kernel.exception de Symfony con una prioridad de -64 (baja, para que los listeners del framework se ejecuten primero, el bundle solo observa). Para cada throwable no gestionado:
- compara los
environmentsconfigurados conkernel.environmenty se abstiene si el entorno actual no está autorizado; - construye una carga útil a partir del throwable (clase, mensaje, archivo, línea y la pila de llamadas, completa por defecto);
- adjunta el contexto de la petición, el método y la URL HTTP, así como el entorno y la release;
- enmascara las claves sensibles y envía el resultado mediante POST a
/api/v1/ingest.
Las excepciones HTTP con un código de estado inferior a 500 (NotFoundHttpException y otros errores de cliente esperados, como los sondeos de bots que terminan en 404) se omiten: nunca se reportan y nunca cuentan para su cuota de eventos. Las excepciones HTTP de código 500 o superior se reportan como cualquier otro throwable.
Es aditivo: nunca modifica la respuesta, nunca interrumpe la propagación y nunca lanza errores. Un envío que falla nunca llega a sus usuarios.
Tampoco es ya silencioso. El bundle pasa el logger de su aplicación al Reporter cuando el servicio existe: un servidor inalcanzable, y un rechazo que el servidor explica (un 401 por una clave mal pegada, un 402 mientras hay un pago pendiente, un 403 por un límite de plan), se escriben en su propio log como advertencia, nombrando el estado y la dirección. Antes no se pasaba ningún logger, y este cliente no tiene consola propia: un cliente que nunca había funcionado no lo decía en ninguna parte.
El subscriber reporta los throwables que llegan al kernel. Las excepciones que usted captura y gestiona por su cuenta no son, por definición, "no gestionadas", repórtelas manualmente (más abajo).
Transmitir los logs
Establezca logs.enabled: true para activar la transmisión de logs. El servicio handler de Monolog monitor.log_handler siempre está registrado mientras el bundle está activado; con logs.enabled: false simplemente descarta todos los registros, de modo que un monolog.yaml que lo referencie sigue compilando. El handler:
- almacena en un búfer los registros de nivel
logs.levelo superior; - respeta la lista
environmentsexactamente igual que el subscriber de excepciones: fuera de los entornos autorizados, ningún registro sale de su aplicación; - ignora los registros que llevan una
exceptionen su contexto: esos ya están cubiertos por el pipeline de excepciones; - vacía el búfer hacia
/api/v1/logsen lotes delogs.max_batch, y de nuevo cuando el handler se cierra al final de la petición.
Registrar el servicio no basta por sí solo, debe adjuntarlo a Monolog como servicio handler:
Los registros que pasan por Monolog (nivel warning y superior por defecto) se agrupan ahora en lotes y se envían a su dashboard. Esto requiere monolog/monolog ^3.0 en su aplicación.
Reportar manualmente
El Reporter compartido está registrado con el identificador de servicio monitor.reporter. Como es un servicio privado sin alias sobre su nombre de clase, el autowiring por tipo (Reporter $reporter) no lo resuelve, conéctelo explícitamente.
Con el atributo #[Autowire] sobre un argumento del constructor:
O enlazándolo en services.yaml:
El Reporter expone:
reportException(Throwable $e, array $context = []): bool: POST/api/v1/ingest;sendLogs(array $logs): bool: POST/api/v1/logs;sendDependencies(array $packages): bool: POST/api/v1/dependencies.
Cada una devuelve false (y nunca lanza errores) cuando el cliente no está configurado o el envío falla.
Enmascarar los datos sensibles
Antes de que nada salga de su aplicación, las claves scrub configuradas se enmascaran recursivamente en el array de contexto con [scrubbed]. La coincidencia es una búsqueda de subcadena en el nombre de la clave, sin distinguir mayúsculas y minúsculas: una clave password configurada también enmascara user_password. Los valores por defecto cubren password, password_confirmation, passphrase, token, signature, secret, authorization, cookie, referer, referrer y api_key. Añada sus propias claves mediante la opción scrub, vea la Configuración.
A partir de la versión 0.3.1, un guion y un guion bajo cuentan como el mismo carácter (api_key enmascara también una clave x-api-key), y el enmascaramiento entra en las cadenas que llevan valores con nombre. La URL de la petición (request.url) pierde el valor de sus parámetros nombrados en la lista (?token=abc sale como ?token=%5Bscrubbed%5D) y todo segmento de ruta formado por cuarenta letras o cifras seguidas; un valor JSON escrito como cadena se abre y se enmascara por clave; y el mensaje de cada log transmitido pasa por la misma regla: cuando empieza por una URL o es JSON, los valores que lleva se enmascaran como arriba, y el resto de su texto se conserva. También a partir de la versión 0.3.1, cuatro parámetros de URL se enmascaran sea cual sea la lista scrub, porque una dirección que lleva uno abre una puerta hasta que caduca: hash (los enlaces de inicio de sesión, login_link), _hash (el UriSigner), sig y signature; el nombre debe ser exacto, de modo que un parámetro content_hash o una clave hash se conservan. Vea la página de enmascarado del núcleo.
El núcleo añade una segunda pasada: los valores con forma de dirección de correo, IBAN, número de tarjeta, número de seguridad social o teléfono franceses se enmascaran estén donde estén, texto del mensaje y segmentos de URL incluidos, y la máscara nombra lo que oculta ([redacted:email]). Viene activa por defecto y se ajusta con las claves redact y redact_custom del árbol monitor, y una lista redact vacía la desactiva. Vea Configuración y la página de enmascarado del núcleo.
Análisis de dependencias
El bundle no incluye un comando de consola para capturar su composer.lock (a diferencia del SDK de Laravel). El método subyacente Reporter::sendDependencies() existe, y el endpoint del servidor /api/v1/dependencies es agnóstico de plataforma: puede por tanto crear su propio comando de consola o paso de CI que lea composer.lock y envíe la lista de paquetes con su clave de proyecto. Un comando dedicado podría llegar en una futura versión del bundle.
Está leyendo la documentación Symfony Bundle v1.0.