Comment recevoir les logs symfony directement dans slack ?
Vendredi 24 Fevrier 2023 08:30

Comment recevoir les logs symfony directement dans slack ?

Lorsque notre site tourne en production, on a rarement le nez dans les logs. Après tout, si il est en prod c’est qu’il n’y a plus de bug…

Il n'y a plus de bugs n'est ce pas?

Mais bon dans le doute il serait intéressant, juste au cas où, de recevoir une notification directement sur slack en cas de problème et c’est ce que nous allons mettre en place.

Créer une application slack

Première chose à faire si l’on veut communiquer avec Slack c’est de créer une application.

Pour ce faire, rendez-vous à l’adresse https://api.slack.com/apps et cliquez sur Créer une application.

Slack - Etape01

Choisissez From scratch

Slack - Etape02

Remplissez maintenant les quelques informations demandées et validez.

Slack - Etape03

Déplacez vous dans le menu concernant les permissions

Slack - Etape04

Il faut désormais définir les actions pouvant être effectuées.
Nous allons sélectionner:

  • chat:write afin de pouvoir simplement envoyer les messages
  • chat:write.public nous permet de ne pas avoir à gérer les accès channel
  • chat:write.customize permet d'afficher un nom de bot défini dans notre application

Slack - Etape05

Tout est pret, nous pouvons générer le token

Slack - Etape06

On valide

Et voici notre token

Pour la partie Slack, c'est terminé, nous avons notre précieux token.

Configuration de Symfony

Nous allons directement ajouter le token slack que nous venons de créer dans notre fichier d’environnement local et on en profite pour ajouter deux autres champs qui vont nous être utiles: le nom du channel et le nom du bot.

SLACK_TOKEN=xoxp-1111111-22222222-33333333-aaaaaaaaaaaaaaaaaaaaaa
SLACK_CHANNEL="logdemonprojets"
SLACK_BOT_NAME="Nono"

N’oubliez pas les bonnes pratique des fichiers d’environnement dans mon article dédié: Comment fonctionnent les fichiers d’environnements Symfony ?

Symfony se base sur Monolog pour la gestion des logs.
Nous allons donc configurer le fichier config/packages/monolog.yaml

Si vous n’avez pas la dépendance:

composer require symfony/monolog-bundle
when@production:
    monolog:
        handlers:
            # Slack
            slack_errors:
                type: slack
                token: '%env(SLACK_TOKEN)%'
                channel: '%env(SLACK_CHANNEL)%'
                bot_name: '%env(SLACK_BOT_NAME)%'
                icon_emoji: ':boom:'
                level: critical
                include_extra: true

Vous aurez remarquez plusieurs choses:

  • when@production nous sert à préciser qu’il ne faut utiliser la notification slack qu’en production et il vaut clairement mieux effectivement ne pas l’activer en dev local…
  • icon_emoji est purement esthétique et affiche cette icône dans la notification slack. Utile pour différencier les différents niveaux d’alertes.
  • level permet justement de définir quelles sont les alertes qui seront transmise: debug, info, notice, warning, error, critical, alert, emergency

Petite astuce, vous pouvez ajouter un petit affixe au nom du channel ou du bot pour différencier les environnement si par exemple vous récupérer les erreurs de la prod et de votre staging.

Ex: bot_name: '%env(SLACK_BOT_NAME)%-prod'

Notre configuration est terminée.
Non, il ne faut rien de plus !

Testons

On va partir du principe que votre code est parfait et ne sortira aucune erreur…

Doubt

Du coup, dans l’un de nos contrôleurs, nous allons générer une erreur:

#[Route('/test/slack', name: 'test_slack')]
public function testSlack(): Response
{
    throw new \RuntimeException('Hello Ghost!');
}

On accède à l’url (spoiler: ça va planter) et on regarde dans Slack.

Symfony error

Slack error

Les bonnes nouvelles aussi

Pourquoi ne recevoir que des mauvaises nouvelles? On pourrait par exemple vouloir être notifié dans le cas où une commande cron se serait bien exécutée.

#[AsCommand(name: 'test:slack')]
class TestSlackCommand extends Command
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->logger->info('Slack confirm');

        return Command::SUCCESS;
    }

}

On test notre commande

symfony console test:slack

Et slack nous notifie

Slack info

Mais bien entendu vous n’êtes pas restreint aux commandes, libre à vous de l’utiliser où vous voulez !

Si vous désirez plus d’infos, n’oubliez jamais que la doc officielle est là et qu’elle est bien faite!