Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
1 result

cp4cip

  • Clone with SSH
  • Clone with HTTPS
  • Module unicaen/livelog

    Le module unicaen/livelog propose une solution pour afficher des logs "en live" dans le navigateur web, çàd au fur et à mesure qu'ils sont "publiés".

    Ceci est réalisé à l'aide de :

    • un Logger Monolog affublé d'un LiveLogSocketLogHandler qui envoie chaque ligne de log à une socket Unix ;
    • une socket Unix recevant chaque ligne de log envoyée par le LiveLogSocketHandler et les passant à une websocket ;
    • une websocket envoyant aux clients (navigateurs) connectés et identifiés chaque ligne de log.

    Installation

    composer require unicaen/livelog

    Configuration

    Copiez le fichier config/unicaen-livelog.local.php.dist dans le répertoire config/autoload de votre appli sans son extension .dist, exmeple :

    cp -n vendor/unicaen-livelog/config/unicaen-livelog.local.php.dist config/autoload/unicaen-livelog.local.php
        'unicaen-livelog' => [
            /**
             * Configuration de la websocket.
             */
            'websocket' => [
                /**
                 * Adresse "privée" à laquelle écoute la websocket.
                 */
                'private_url' => '0.0.0.0:7443',
    
                /**
                 * Adresse "public" à laquelle la websocket est accessible par les clients (navigateurs).
                 * Dans cet exemple, un navigateur web pourrait se connecter à l'adresse 'wss://serveur.unicaen.fr/livelog'. 
                 */
                'public_url' => '/livelog',
    
                /**
                 * Mode verbeux ou pas.
                 */
                'verbose' => false,
            ],
            /**
             * Configuration de la socket.
             */
            'socket' => [
                /**
                 * Chemin de la socket Unix.
                 */
                'path' => 'unix:///tmp/unicaen_livelog.sock',
    
                /**
                 * Mode verbeux ou pas.
                 */
                'verbose' => false,
            ],

    Lancement des sockets

    Pour lancer la websocket et la socket en mode verbeux, ouvrez un terminal et lancez ceci en tant que root :

    runuser -u www-data -- php public/index.php unicaen-livelog run-sockets --verbose 1

    Si vous rencontrez l'erreur suivante, supprimez la socket Unix (ex : rm /tmp/unicaen_livelog.sock) :

    RuntimeException
    Failed to listen on Unix domain socket "unix:///tmp/unicaen_livelog.sock": Unknown error

    Test de la socket

    Pour tester la socket, ouvrez un 2e terminal et lancez ceci :

    runuser -u www-data -- php public/index.php unicaen-livelog test

    Et vous devriez voir dans le terminal de lancement un truc qui ressemble à ça :

    [socket]>    DATA {"formatted":"[2022-02-01T15:09:39.070488+01:00] mylogger.INFO: Ceci est un test \u00e0 2$ ! D'ac ? ~ % [] []\n","clientId":"client_61f93f2312813"}
    [websocket]> SEND : Stop, client client_61f93f2312813 inconnu !

    Où l'on voit que la socket reçoit bien le message de test mis en forme par le logger (date, etc.) On voit ensuite que la websocket se plaint qu'elle ne connait pas le client client_61f93f2312813. C'est normal : seuls les clients (navigateurs) disposant d'un identifiant officiel fourni par l'application sont reconnus et peuvent recevoir les logs.

    Test de la websocket

    Avant de pouvoir tester la websocket, il faut configurer Apache.

    Plus difficile de tester la websocket si ce n'est en ouvrant une page de votre appli qui établie une connexion. C'est possible d'utiliser websocat (https://github.com/vi/websocat).

    Inspirez-vous de cette commande pour vous connecter à la websocket :

    websocat --insecure --protocol "livelog" 'wss://localhost.unicaen.fr:8003/livelog?client=client_1234'

    Ensuite tapez au clavier Un message de log ! suivi de la touche "Entrée" puis "CTRL+C" pour stopper websocat. Vous devriez voir dans le terminal de lancement un truc qui ressemble à ça :

    [websocket]> OPEN : client_1234
    [websocket]> MESSAGE : un message de log !
    
    [websocket]> CLOSE : client_1234

    Configurer Apache

    Pour que la websocket soit accessible depuis un navigateur web, il faut faire un peu de config Apache.

    • Le module proxy_wstunnel doit être activé, exemple :
    a2enmod proxy_wstunnel
    • L'URL d'accès à la websocket (ex : wss://localhost.unicaen.fr:8003/livelog) doit être accessible de façon sécurisée, voici un exemple de conf à mettre dans /etc/apache2/conf-available/livelog.conf :
    # Websocket pour unicaen/livelog.
    # ==> accessible de l'extérieur à l'adresse wss://serveur.unicaen.fr/livelog
    SSLProxyEngine On
    ProxyPass        /livelog  ws://0.0.0.0:7443
    ProxyPassReverse /livelog  ws://0.0.0.0:7443

    NB : 0.0.0.0:7443 doit correspondre à la clé 'private_url' que vous avez spécifiée dans la config du module ; idem pour /livelog et la clé 'public_url'.

    • Ensuite, cette conf doit être activée :
    a2enconf livelog

    Code

    Côté contrôleur

    Exemple d'une page "voir" (action voirAction) affichant les caractéristiques d'un import de données et contenant un bouton "Lancer l'import" (action lancerAction).

    L'action lancerAction lance l'import via un service qui utilise un Logger pour produire des logs. Ce sont ces lignes de logs que l'on veut afficher au fur et à mesure qu'elles sont produites.

    • ImportController.php
    use Laminas\Mvc\Controller\AbstractActionController;
    use Monolog\Logger;
    use UnicaenLiveLog\Log\LivelogSocketLogHandler;
    
    class ImportController extends AbstractActionController
    {
        use LivelogSocketLogHandlerAwareTrait;
            
        public function voirAction(): array
        {
            //...
        }
            
        public function lancerAction(): bool
        {
            //...
            
            $logger = new Logger('livelog');
            $logger->pushHandler($this->livelogSocketHandler);
            $this->importService->setLogger($logger);
            $result = $this->importService->runImport($import);
            
            return false;
        }
    
        //...
    }
    • ImportControllerFactory.php
    use Psr\Container\ContainerInterface;
    use UnicaenLivelog\Log\LivelogSocketLogHandler;
    
    class ImportControllerFactory
    {
        function __invoke(ContainerInterface $container): ImportController
        {
            $controller = new ImportController();
            
            $livelogSocketHandler = $container->get(LivelogSocketLogHandler::class);
            $controller->setLivelogSocketHandler($livelogSocketHandler);
           
            //...
            
            return $controller;
        }
    }

    Notez bien le LivelogSocketLogHandler injecté dans le contrôleur puis branché sur un Logger afin que chaque ligne de log soit envoyée à la socket.

    Côté vues

    Dans la vue voir.phtml associée à voirAction, vous aurez typiquement un bouton déclenchant l'opération dont les logs vous intéressent. Vous devez intercepter le clic sur ce bouton afin de lancer la requête en mode AJAX (car il faut rester sur la page courante afin de voir les logs !) On le fait dans cet exemple uniquement lorsque la connexion à la websocket peut être établie, permettant ainsi de retomber sur le fonctionnement non-AJAX éventuelelement supporté.

    Exemple :

    <a class="btn btn-warning"
       id="lancer"
       href="<?php echo $this->url(
           'unicaen-db-import/import/lancer',
           ['name' => $import->getName()]
       ) ?>"><span class="fas fa-play"></span> Lancer l'import</a>
    
    <script>
      $(function() {
        // `conn` est de type `WebSocket` (https://developer.mozilla.org/fr/docs/Web/API/WebSocket)
        let conn = $("#livelog-div").data('conn');
        conn.addEventListener('open', function(e) {
          $("#lancer").on('click', function(event) {
            let trigger = $(this).addClass('disabled');
            $.get(trigger.attr("href"), function() {
              trigger.removeClass('disabled');
            });
          });
        });
      });
    </script>

    Vous devez créer le conteneur dans lequel s'afficheront les logs (et quelques autres petites choses) avec l'aide de vue fournie par le module.

    <?php
    /** @var \UnicaenLivelog\View\Helper\LivelogPanelHelper $livelogPanelHelper */
    $livelogPanelHelper = $this->plugin('livelogPanel');
    $livelogPanelHelper->setDivId($divId = 'livelog-div');
    echo $livelogPanelHelper;
    ?>

    Une pincée de style, peut-être :

    <style>
        .livelog-panel {
            line-height: normal;
            font-family: monospace;
            font-size: 9px;
            
            border: 2px grey dotted;
            
            height: 300px;
            overflow-y: scroll;
            overflow-x: scroll;
            white-space: nowrap;
            
            padding: 0.5em;
            margin-top: 1em;
        }
    </style>

    Dans un navigateur web, lorsque vous vous rendez sur la page correspondant à voirAction, vous devriez voir une div contenant un message du genre :-) Connexion WebSocket OK si la connexion à la websocket a pu être établie (ou :-( Connexion WebSocket KO dans le cas contraire).

    Lorsque vous cliquez sur le bouton "Lancer" (ou équivalent), des lignes de logs devraient s'afficher les unes sous les autres au fur et à mesure qu'elles sont produites dans lancerAction.

    NB : Pas de vue lancer.phtml associée à lancerAction puisqu'elle est requêtée en mode AJAX.