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…
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.
Choisissez From scratch
Remplissez maintenant les quelques informations demandées et validez.
Déplacez vous dans le menu concernant les permissions
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
Tout est pret, nous pouvons générer le token
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…
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.
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
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!