Usage

Une fois le bundle installé et url + key renseignés, la remontée des exceptions fonctionne sans aucun code supplémentaire. La transmission des logs et la remontée manuelle demandent chacune une étape de plus.

Capture automatique des exceptions

Le bundle enregistre monitor.exception_subscriber, un event subscriber qui écoute l'événement kernel.exception de Symfony avec une priorité de -64 (basse, pour que les écouteurs du framework s'exécutent d'abord, le bundle ne fait qu'observer). Pour chaque throwable non géré, il :

  1. compare les environments configurés à kernel.environment et s'abstient si l'environnement courant n'est pas autorisé ;
  2. construit une charge utile à partir du throwable (classe, message, fichier, ligne et la pile d'appels, complète par défaut) ;
  3. attache le contexte de la requête, la méthode et l'URL HTTP, ainsi que l'environnement et la release ;
  4. masque les clés sensibles et envoie le résultat en POST sur /api/v1/ingest.

Les exceptions HTTP dont le code de statut est inférieur à 500 (NotFoundHttpException et les autres erreurs client attendues, comme les sondes de bots qui tombent sur des 404) sont ignorées : elles ne sont jamais remontées et ne comptent jamais dans votre quota d'événements. Les exceptions HTTP de code 500 et plus sont remontées comme n'importe quel autre throwable.

C'est additif : il ne modifie jamais la réponse, n'interrompt jamais la propagation et ne lève jamais d'erreur. Si le serveur est injoignable, l'envoi échoue silencieusement.

Le subscriber remonte les throwables qui atteignent le kernel. Les exceptions que vous attrapez et gérez vous-même ne sont, par définition, pas « non gérées », remontez-les manuellement (ci-dessous).

Transmettre les logs

Mettez logs.enabled: true pour activer la transmission des logs. Le service handler Monolog monitor.log_handler est toujours enregistré tant que le bundle est activé ; avec logs.enabled: false, il ignore simplement tous les enregistrements, et un monolog.yaml qui le référence continue donc de compiler. Le handler :

  • met en tampon les enregistrements au niveau logs.level ou au-dessus ;
  • respecte la liste environments exactement comme le subscriber d'exceptions : hors des environnements autorisés, aucun enregistrement ne quitte votre application ;
  • ignore les enregistrements qui portent une exception dans leur contexte: ceux-là sont déjà couverts par le pipeline d'exceptions ;
  • vide le tampon vers /api/v1/logs par lots de logs.max_batch, et à nouveau lorsque le handler se ferme à la fin de la requête.

Enregistrer le service ne suffit pas à lui seul, vous devez l'attacher à Monolog comme service handler :

yaml
# config/packages/monitor.yaml
monitor:
    logs:
        enabled: true
        level: warning
        max_batch: 200
yaml
# config/packages/prod/monolog.yaml
monolog:
    handlers:
        monitor:
            type: service
            id: monitor.log_handler

Les enregistrements qui transitent par Monolog (niveau warning et au-dessus par défaut) sont désormais regroupés et expédiés vers votre dashboard. Cela nécessite monolog/monolog ^3.0 dans votre application.

Remonter manuellement

Le Reporter partagé est enregistré sous l'identifiant de service monitor.reporter. Comme c'est un service privé non aliassé sur son nom de classe, l'autowiring par type (Reporter $reporter) ne le résout pas, câblez-le explicitement.

Avec l'attribut #[Autowire] sur un argument de constructeur :

php
use QuietGuard\Monitor\Reporter;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

class CheckoutService
{
    public function __construct(
        #[Autowire(service: 'monitor.reporter')]
        private readonly Reporter $monitor,
    ) {}

    public function settle(Order $order): void
    {
        try {
            // ...
        } catch (\Throwable $e) {
            $this->monitor->reportException($e, ['order_id' => $order->getId()]);

            throw $e;
        }
    }
}

Ou en le liant dans services.yaml :

yaml
# config/services.yaml
services:
    App\Service\CheckoutService:
        arguments:
            $monitor: '@monitor.reporter'

Le Reporter expose :

  • 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.

Chacune renvoie false (et ne lève jamais d'erreur) lorsque le client n'est pas configuré ou que l'envoi échoue.

Masquer les données sensibles

Avant que quoi que ce soit ne quitte votre application, les clés scrub configurées sont masquées récursivement dans le tableau de contexte par [scrubbed]. La correspondance est une recherche de sous-chaîne dans le nom de la clé, sans tenir compte de la casse : une clé password configurée masque aussi user_password. Les valeurs par défaut couvrent password, passphrase, token, secret, authorization, cookie, referer, referrer et api_key. Ajoutez vos propres clés via l'option scrub, voir la Configuration.

Le cœur ajoute une seconde passe que le bundle ne configure pas : les valeurs ayant la forme d'une adresse e-mail, d'un IBAN, d'un numéro de carte, d'un numéro de sécurité sociale ou d'un téléphone français sont masquées où qu'elles se trouvent, texte du message et segments d'URL compris, et le masque nomme ce qu'il cache ([redacted:email]). Elle est active par défaut et ne se désactive pas depuis l'arbre monitor aujourd'hui. Voir la page de masquage du cœur.

Analyse des dépendances

Le bundle ne fournit pas de commande console pour capturer votre composer.lock (contrairement au SDK Laravel). La méthode sous-jacente Reporter::sendDependencies() existe, et l'endpoint serveur /api/v1/dependencies est agnostique de plateforme : vous pouvez donc câbler votre propre commande console ou étape CI qui lit composer.lock et envoie la liste des packages avec votre clé de projet. Une commande dédiée pourra arriver dans une future version du bundle.

Vous lisez la documentation Symfony Bundle v1.0.