Comment identifier simplement les requêtes à problème dans une application
publié le 14 oct. 2023
Autant je n'aime pas fliquer les utilisateurs de mes applications, pour des questions à la fois éthiques et de performance, autant j'ai une obsession sur le bon fonctionnement de ces applications, et notamment la bonne santé des fonctions et des temps de calcul de l'application. Mon principe de base est :
Si une requête donnée met plus de 1 seconde à "tourner", il y a matière à l'améliorer.
L'enjeu va donc être de capter ce genre de requêtes.
Pour cela, j'utilise la possibilité dans Laravel d'ajouter ses propres middlewares (des scripts qui vont tourner avant de faire travailler le serveur ou avant l'envoi de la réponse, ou les deux).
Voici mon setup :
app/Http/Middleware/MeasureResponseTime.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class MeasureResponseTime
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);
return $response;
}
// On ajoute à la fonction terminate() le code suivant
// pour qu'il s'exécute quand la réponse est envoyée.
public function terminate($request, $response)
{
$timeMeasure = round(microtime(true) - LARAVEL_START,1);
// A noter que LARAVEL_START est une variable définie
// par Laravel à chaque demande. A adapter selon vos besoins.
$scopedUri = Str::startsWith($request->getRequestUri(), '/nova/') ? 0 : 1;
// Ici on peut réduire le périmètre qui nous intéresse,
// ou exclure certaines requêtes.
if (defined('LARAVEL_START') && $request instanceof Request && $scopedUri) {
// On a défini dans app.treshold_for_logs une constante pour le seuil,
// par exemple '1' pour une seconde
if ($timeMeasure > config('app.treshold_for_logs') ) {
// Si le seuil est dépassé, on enregistre le temps avec plusieurs propriétés
// pour retrouver où est le problème. A adapter selon vos besoins.
app('log')->debug('Response time too long', [
'method' => $request->getMethod(),
'uri' => $request->getRequestUri(),
'seconds' => $timeMeasure,
'ip' => $request->ip(),
'user_id' => $request->user()->id ?? '',
'livewire_path' => $request->all()['fingerprint']['path'] ?? '',
]);
}
}
}