HealthCheck & Debug Toolbar
HealthCheck & Debug Toolbar
Deux outils bien distincts : HealthCheck répond « est-ce que ça tourne maintenant ? »
(supervision), la Debug Toolbar répond « qu'est-ce que cette requête a fait ? » (développement).
HealthCheck
Niang\Core\HealthCheck::run() est la logique partagée entre
GET /health (et son alias /up) et niang health en CLI —
une seule vérification, deux façades. Quatre services testés en conditions réelles,
pas juste « le fichier de config existe » :
| Service | Vérification réelle |
|---|---|
| database | SELECT 1 sur la connexion configurée |
| cache | écrit puis relit une clé (Cache::put()/get()) |
| storage | storage/ existe et est accessible en écriture |
| queue | Queue::pending() ne lève pas d'exception |
curl http://localhost:8000/health
{"status":"ok","services":{"database":"ok","cache":"ok","storage":"ok","queue":"ok"}}
Statut HTTP 200 si tout est ok, 503 sinon — pensé pour
un check de load balancer ou un outil de supervision (Uptime Kuma...), à brancher directement.
Équivalent en CLI, pour vérifier avant un déploiement sans faire de requête HTTP :
./bin/niang health
À ne pas confondre avec niang doctor : doctor vérifie l'environnement
statique (version PHP, extensions chargées, .env présent, APP_KEY
configurée, permissions d'écriture, routes chargeables) — utile juste après une installation
ou un déploiement. health/HealthCheck vérifie l'état
d'exécution — ces services répondent-ils maintenant ?
Sondes live et ready
| Route | Vérifie | Usage |
|---|---|---|
GET /health, /up, /health/ready | base, cache, stockage, file d'attente ; 503 si l'un échoue | supervision, sonde readiness |
GET /health/live | rien : le process PHP répond | sonde liveness (redémarrer un conteneur bloqué) |
Les quatre routes restent accessibles en mode maintenance.
Observabilité
Identifiant de requête et traces
Chaque réponse porte un en-tête X-Request-Id, ajouté aussi à chaque ligne de log écrite pendant la
requête : une erreur signalée par un utilisateur se retrouve dans les logs à partir de cet identifiant. Un
identifiant fourni par le répartiteur de charge (X-Request-Id, 8 à 128 caractères sûrs) est
conservé. Un job mis en file garde celui de la requête qui l'a créé.
Le framework suit W3C Trace Context : un en-tête
traceparent entrant (proxy, APM, collecteur OpenTelemetry) est rejoint, et les appels de
Http\Client (webhooks, OAuth, S3) le transmettent au service appelé. Sans SDK : l'outil placé
devant l'application relie ses traces aux logs.
use Niang\Core\Log;
use Niang\Core\Trace;
Log::withContext(['user_id' => $user['id']]); // ajouté à tous les messages suivants
Trace::requestId(); // pour l'afficher sur une page d'erreur, par exemple
Logs JSON
LOG_FORMAT=json
LOG_CHANNEL=stderr # conteneurs ; ou daily, syslog...
{"timestamp":"2026-09-27T13:34:33.500+00:00","level":"info","message":"commande 7 créée","context":{"id":7},"request_id":"4bf92f3577b34da6a3ce929d0e0e4736"}
Un objet par ligne, pour Loki, Elasticsearch, CloudWatch ou Datadog. Une exception passée en contexte garde sa
classe, son message et son emplacement ; les clés sensibles restent masquées. line (défaut) garde le
format lisible.
Métriques Prometheus
METRICS_ENABLED=true
METRICS_TOKEN=une-longue-valeur-aleatoire
scrape_configs:
- job_name: niangpro
scheme: https
authorization:
credentials: une-longue-valeur-aleatoire
static_configs:
- targets: ['app.exemple.sn']
| Métrique | Type |
|---|---|
niangpro_http_requests_total{method, status} | compteur (statut par classe : 2xx, 5xx...) |
niangpro_http_request_duration_seconds | histogramme |
niangpro_jobs_processed_total, niangpro_jobs_failed_total | compteurs (workers) |
app_* | vos compteurs et jauges |
// config/metrics.php
'counters' => ['orders_created_total' => 'Commandes créées'],
// dans le code
Metrics::increment('orders_created_total');
// dans AppServiceProvider::boot() : calculée à chaque lecture
Metrics::gauge('jobs_pending', 'Jobs en attente', fn () => DB::table('jobs')->count());
Sans METRICS_TOKEN, /metrics répond 404 : jamais exposé par défaut. Les compteurs sont
dans le cache : avec plusieurs serveurs, CACHE_DRIVER=database ou redis les partage ;
cache:clear les remet à zéro, ce que Prometheus traite comme un redémarrage. Aucune étiquette par
URL : le nombre de séries reste fixe. niang doctor signale des métriques activées sans jeton.
Debug Toolbar
Injectée automatiquement en bas de chaque réponse HTML quand APP_DEBUG=true (voir
cycle de vie d'une requête, Application::handle()) :
temps de réponse, nombre de requêtes SQL exécutées (DB::queryCount(), remis à zéro
à chaque requête), pic mémoire, code de statut. Visible sur toutes les pages de cette
documentation en développement local.
Trois conditions doivent toutes être vraies pour qu'elle s'injecte — jamais sur une réponse qu'elle risquerait de corrompre :
APP_DEBUG=truedans.env.- La réponse a un
Content-Typequi commence partext/html— jamais sur du JSON. - Le corps contient une balise
</body>où s'accrocher (la barre est insérée juste avant).
APP_DEBUG=false en production — sans quoi la barre de debug s'affiche à vos visiteurs. niang doctor avertit (sans faire échouer) si APP_ENV=production et APP_DEBUG=true sont actifs en même temps.