# Les exceptions Laravel en push sur votre téléphone

> Chaque exception Laravel devient un push avec Honk::reportable(), limité par exception, avec les alertes du planificateur et Honk::fake() pour les tests.

Source: https://honk-me.app/fr/guides/notifications-exceptions-laravel

Laravel signale déjà les exceptions : dans vos logs et, avec un canal comme Slack, dans votre messagerie d’équipe. Le problème, c’est quand la même exception tombe 300 fois en une minute. Vous voulez être prévenu une fois, avec de quoi agir, puis avoir la paix jusqu’à la prochaine panne.

Ce guide met cela en place avec le paquet `honk-me/honk-me` et Laravel 13 : les exceptions deviennent des push, les répétitions d’une même erreur sont regroupées, et les tâches planifiées vous préviennent quand elles échouent, puis quand elles repartent.

## Avant de commencer

- Laravel 13 avec PHP 8.3 ou plus récent.
- Un compte Honk (pour l’instant sur invitation : [demandez un accès](https://honk-me.app/fr/demander-un-acces)) et un projet avec une clé d’ingestion : dans l’app web, ouvrez le projet, puis **Clés**.

## 1. Installer le paquet

```sh
composer require honk-me/honk-me
# publishes config/honk.php and adds HONK_URL and HONK_KEY to .env.example
php artisan honk:install
```

Indiquez le serveur et la clé dans `.env`. Ne commitez jamais la clé : `.env.example` ne contient que des valeurs vides.

```dotenv
HONK_URL=https://honk-me.app
HONK_KEY=honk_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Vérifiez la connexion. `honk:test` envoie un Petit coup de klaxon et affiche l’identifiant du message :

```sh
php artisan honk:test         # sends a light honk and prints the message id
php artisan about --only=honk # URL, key prefix (never the secret), queue, Context metadata
```

## 2. Signaler les exceptions

Une ligne dans `bootstrap/app.php` :

```php
// bootstrap/app.php
use HonkMe\Laravel\Facades\Honk;

->withExceptions(function (Exceptions $exceptions): void {
    $exceptions->report(Honk::reportable());
})
```

Désormais, chaque exception signalée devient un Long coup de klaxon, envoyé comme *problème*. Trois mécanismes évitent le déluge :

- **Un groupe par emplacement dans le code.** La clé de groupe est `exceptions/<Class>@<file>:<line>` : 300 exceptions identiques forment un seul incident avec un compteur, et une autre exception, un autre incident.
- **Au plus une alerte par groupe toutes les 5 minutes.** La limitation s’appuie sur votre cache : les 299 répétitions ne quittent même pas votre serveur.
- **Un envoi après la réponse.** Le mode par défaut, `defer`, envoie une fois la réponse HTTP partie : un réseau lent ne ralentit jamais une page.

Tant que `HONK_URL` ou `HONK_KEY` manque, rien n’est envoyé, ce qui laisse en paix le développement local et la CI. Et l’envoi ne lève jamais d’exception.

Vous pouvez choisir un autre niveau ou une autre fenêtre de limitation par app, par exemple un Klaxon continu limité à un par minute pour un service de paiement :

```php
$exceptions->report(Honk::reportable(severity: 'blast', throttleSeconds: 60));
```

Le reste se règle dans `config/honk.php`. Ignorez-y les exceptions attendues, comme un paiement refusé que l’interface explique déjà, et choisissez le mode d’envoi :

```php
// config/honk.php (published by php artisan honk:install)
'exceptions' => [
    'enabled' => (bool) env('HONK_EXCEPTIONS', true),
    'severity' => 'long',
    'channel' => 'exceptions',
    'throttle' => 300,          // seconds per group
    'mode' => 'defer',          // defer (after the response), sync or queue
    'ignore' => [
        \App\Exceptions\PaymentDeclined::class,   // expected, already handled in the UI
    ],
],
```

Les messages d’exception sont envoyés tels quels, tronqués si nécessaire. N’y mettez pas de données personnelles : elles finiraient dans un push.

## 3. Immédiatement, après la réponse ou via la file d’attente

Vous avez le même choix pour tout ce que vous envoyez vous-même :

```php
use HonkMe\Laravel\Facades\Honk;
use HonkMe\Message;

Honk::defer()->beep('New order', "{$order->email} paid {$order->total} €");   // after the response
Honk::queue(Message::make('Imported 1 204 rows')->beep()->channel('imports'));   // a queued job
Honk::loud('Disk 91%', '/var on app-01', ['groupKey' => 'disk/app-01/var']);     // right now
```

- `Honk::defer()` s’exécute dans ce processus, après la réponse, sans worker. Si le processus s’arrête avant, cette alerte est perdue ; pour la plupart des alertes, ce n’est pas grave.
- `Honk::queue()` s’exécute dans un worker de file d’attente, avec nouvelles tentatives et backoff, et résiste aux redémarrages. Utilisez-le pour ce qui doit arriver à coup sûr.
- Les helpers simples envoient immédiatement, avec nouvelles tentatives, ce qui convient aux commandes, aux jobs et au planificateur.

`defer()` comme `queue()` valident le message tout de suite : un champ invalide provoque une erreur dans votre code, pas plus tard dans un worker.

## 4. Tâches planifiées

```php
// routes/console.php
Schedule::command('backup:run')->daily()->honkOnFailure();          // problem on failure, recovery once it works again
Schedule::command('reports:send')->hourly()->honkOnSuccess();       // a beep after every successful run
```

`honkOnFailure()` envoie un problème, groupé par tâche, avec le code de sortie et les dernières lignes affichées. Dès que la tâche réussit de nouveau, il envoie un rétablissement, et seulement après un échec : une tâche qui va bien ne vous dérange jamais. `honkOnSuccess()` envoie un Bip-bip après chaque exécution réussie, pour les rapports que vous tenez à recevoir.

## 5. Tester

`Honk::fake()` enregistre ce qui serait envoyé ou mis en file d’attente, sans jamais toucher au réseau. Il valide comme le vrai client, si bien qu’un message invalide fait quand même échouer le test :

```php
use HonkMe\Laravel\Facades\Honk;
use HonkMe\Message;
use HonkMe\Severity;

Honk::fake();

$this->post(route('quote.store'), $data);

Honk::assertSent(fn (Message $m) => $m->groupKey === 'requests/1' && $m->severity === Severity::Light);
Honk::assertSentTimes(1);
Honk::assertNotSent(fn (Message $m) => $m->severity === Severity::Blast);
Honk::assertQueued(fn (Message $m, string $idempotencyKey) => $m->channel === 'imports');
Honk::assertNothingSent(); // also assertNothingQueued(), assertNothingOutgoing()
```

## Ce que Honk ajoute à Laravel

Vos logs reçoivent toujours toutes les exceptions. Honk y ajoute un push par nouvelle erreur sur votre iPhone, votre Apple Watch ou votre navigateur, regroupe les répétitions avec un compteur et les range dans une seule boîte de réception, avec vos tâches cron et vos serveurs. Pour en gérer certaines autrement sans toucher au code, ajoutez une règle au projet, par exemple pour envoyer dans le récapitulatif les `exceptions/` d’une intégration bavarde.
