@nodefony/devkit 10.0.0-beta.2 → 10.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -5
- package/dist/_virtual/{_@oxc-project_runtime@0.152.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/decorate.js +1 -2
- package/dist/_virtual/{_@oxc-project_runtime@0.152.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/decorateParam.js +1 -2
- package/dist/index.js +24 -11
- package/dist/nodefony/config/config.js +16 -137
- package/dist/nodefony/config/defineModuleConfig.js +1 -2
- package/dist/nodefony/controllers/DevkitController.js +7 -14
- package/dist/nodefony/controllers/McpController.js +27 -163
- package/dist/nodefony/controllers/ProfileSessionController.js +47 -0
- package/dist/nodefony/mcp/observe.js +235 -0
- package/dist/nodefony/mcp/profileReport.js +242 -0
- package/dist/nodefony/mcp/profileRoute.js +521 -0
- package/dist/nodefony/mcp/shotClient.js +84 -0
- package/dist/nodefony/mcp/shutdown.js +44 -0
- package/dist/nodefony/mcp/tools.js +696 -0
- package/dist/nodefony/service/DevkitService.js +93 -29
- package/dist/nodefony/src/card.js +1 -2
- package/dist/nodefony/src/errors/DevkitError.js +1 -2
- package/dist/nodefony/src/profileSession.js +14 -0
- package/dist/types/index.d.ts +15 -1
- package/dist/types/nodefony/config/config.d.ts +1 -1
- package/dist/types/nodefony/controllers/McpController.d.ts +13 -17
- package/dist/types/nodefony/controllers/ProfileSessionController.d.ts +31 -0
- package/dist/types/nodefony/interfaces/IDevkitService.d.ts +22 -1
- package/dist/types/nodefony/mcp/observe.d.ts +83 -0
- package/dist/types/nodefony/mcp/profileReport.d.ts +138 -0
- package/dist/types/nodefony/mcp/profileRoute.d.ts +87 -0
- package/dist/types/nodefony/mcp/shotClient.d.ts +53 -0
- package/dist/types/nodefony/mcp/shutdown.d.ts +25 -0
- package/dist/types/nodefony/mcp/tools.d.ts +109 -0
- package/dist/types/nodefony/service/DevkitService.d.ts +41 -4
- package/dist/types/nodefony/src/profileSession.d.ts +12 -0
- package/docs/index.md +217 -20
- package/package.json +17 -12
- package/skills/nodefony-add-crud/SKILL.md +5 -0
- package/skills/nodefony-add-realtime-channel/SKILL.md +66 -9
- package/skills/nodefony-add-service/SKILL.md +14 -3
- package/skills/nodefony-authentication/SKILL.md +234 -0
- package/skills/nodefony-browser/SKILL.md +65 -21
- package/skills/nodefony-browser/references/socket.md +13 -4
- package/skills/nodefony-browser/references/sondes.md +13 -0
- package/skills/nodefony-browser/scripts/audit.mjs +59 -10
- package/skills/nodefony-browser/scripts/inspect.mjs +123 -5
- package/skills/nodefony-browser/scripts/lib/browser.mjs +112 -6
- package/skills/nodefony-browser/scripts/lib/probes.mjs +219 -7
- package/skills/nodefony-browser/scripts/socket.mjs +70 -4
- package/skills/nodefony-browser/scripts/watch.mjs +101 -0
- package/skills/nodefony-dev/SKILL.md +78 -82
- package/skills/nodefony-dev/scripts/docs.mjs +24 -8
- package/skills/nodefony-devops/SKILL.md +98 -74
- package/skills/nodefony-devops/references/compose.md +8 -0
- package/skills/nodefony-devops/references/dimensionnement.md +122 -0
- package/skills/nodefony-devops/references/frontal.md +282 -48
- package/skills/nodefony-devops/references/kubernetes.md +41 -14
- package/skills/nodefony-devops/references/secrets.md +30 -5
- package/skills/nodefony-devops/references/variables.md +66 -31
- package/skills/nodefony-migrate-schema/SKILL.md +5 -2
- package/skills/nodefony-migrate-schema/references/verdicts.md +20 -19
- package/skills/nodefony-protect-route/SKILL.md +124 -21
- package/skills/nodefony-security-review/SKILL.md +127 -0
- package/skills/nodefony-security-review/scripts/review-diff.mjs +1090 -0
- package/skills/nodefony-troubleshoot/SKILL.md +225 -0
- package/skills/nodefony-troubleshoot/scripts/log-errors.mjs +465 -0
- package/skills/nodefony-upgrade/SKILL.md +130 -0
- package/dist/_virtual/_@oxc-project_runtime@0.152.0/helpers/esm/decorateMetadata.js +0 -6
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nodefony-troubleshoot
|
|
3
|
+
description: >
|
|
4
|
+
Dépanne une application Nodefony en partant du SYMPTÔME constaté — démarrage qui échoue, route
|
|
5
|
+
en 404, refus 401 ou 403 inattendu, erreur au journal, colonne absente, tests rouges d'un coup,
|
|
6
|
+
page lente — et donne pour chacun le premier geste, la commande qui le constate et le skill qui
|
|
7
|
+
porte le détail. Extrait les erreurs du journal par un script ; mesure une route par l'outil MCP
|
|
8
|
+
`nodefony_profile_route` (il tire lui-même les requêtes), le trafic qu'on génère par
|
|
9
|
+
`nodefony_observe`. À charger DÈS qu'une chose qui marchait ne marche plus, AVANT de lire les
|
|
10
|
+
sources ou de contourner la panne. Coder une fonctionnalité → `nodefony-dev`.
|
|
11
|
+
Déclencheurs : "l'application ne démarre plus", "le serveur plante au démarrage", "ma route
|
|
12
|
+
répond 404", "ça marchait hier", "dépanner", "erreur dans les logs", "tous mes tests sont
|
|
13
|
+
rouges", "cette page est lente", "trop de requêtes SQL", "problème de N+1", "mesure cette route",
|
|
14
|
+
"est-ce plus rapide après ma modification", "erreur 500 intermittente", "EADDRINUSE",
|
|
15
|
+
"ECONNREFUSED".
|
|
16
|
+
metadata:
|
|
17
|
+
version: 1.1.0
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# nodefony-troubleshoot — du symptôme au geste, sans contourner
|
|
21
|
+
|
|
22
|
+
> **Maintenance** : vérité courante, jamais un journal. Éditer en place ; l'historique vit dans
|
|
23
|
+
> `git log`. Pas de `references/`, comme `nodefony-dev` et pour la même raison mesurée : une page
|
|
24
|
+
> de `references/` n'est presque jamais ouverte par un agent, un script cité comme commande l'est.
|
|
25
|
+
> Ce qui doit atteindre un agent s'EXÉCUTE ou vit dans ce corps.
|
|
26
|
+
|
|
27
|
+
## Passer la main
|
|
28
|
+
|
|
29
|
+
| Ce que tu fais en réalité | Le skill |
|
|
30
|
+
| -------------------------------------------------------------------- | ------------------------- |
|
|
31
|
+
| Tu codes une fonctionnalité, rien n'est cassé | `nodefony-dev` |
|
|
32
|
+
| Le refus 401/403 vient d'une route que tu protèges ou ouvres | `nodefony-protect-route` |
|
|
33
|
+
| La connexion elle-même échoue : mot de passe, second facteur, retour | `nodefony-authentication` |
|
|
34
|
+
| La base n'a pas la colonne ou la table que l'entité déclare | `nodefony-migrate-schema` |
|
|
35
|
+
| Le symptôme est À L'ÉCRAN : rien ne s'affiche, erreur de console | `nodefony-browser` |
|
|
36
|
+
| La panne n'apparaît qu'en conteneur, en production, au déploiement | `nodefony-devops` |
|
|
37
|
+
|
|
38
|
+
## 1. La règle — constater, puis corriger la cause
|
|
39
|
+
|
|
40
|
+
**Une panne se CONSTATE avant de se corriger.** L'application sait dire ce qui ne va pas : son
|
|
41
|
+
diagnostic, ses routes montées, son journal. Lire les sources pour deviner, c'est reconstruire à la
|
|
42
|
+
main ce qu'une commande rend en une seconde — et se tromper sur ce qui est réellement chargé.
|
|
43
|
+
|
|
44
|
+
**Ne contourne jamais une panne.** Élargir une zone pour faire taire un 401, retirer une garde,
|
|
45
|
+
sérialiser une suite pour faire passer un rouge, relâcher une assertion, effacer la base : chacun
|
|
46
|
+
fait disparaître le symptôme et garde la cause, qui revient ailleurs — souvent en production. Si la
|
|
47
|
+
cause t'échappe, dis-le, avec ce que tu as constaté.
|
|
48
|
+
|
|
49
|
+
## 2. Le symptôme → le premier geste
|
|
50
|
+
|
|
51
|
+
| Symptôme | Premier geste | Puis |
|
|
52
|
+
| --------------------------------------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
53
|
+
| L'application ne démarre pas, ou démarre puis s'arrête | `npx nodefony doctor` | le journal (§3) ; sortie `78` = clé de configuration refusée, elle est NOMMÉE |
|
|
54
|
+
| Elle démarre, mais quelque chose manque (module, base, fournisseur) | `npx nodefony doctor --live` | `var/last-boot.json` : le bilan du dernier démarrage, daté |
|
|
55
|
+
| Le superviseur avale le message de plantage | lance l'enfant seul : `NF_DEV_CHILD=1` puis `npx nodefony development` | le plantage brut s'affiche |
|
|
56
|
+
| Une route répond `404` | `npx nodefony inspect routes --json` | absente → `npm run build` ; présente → le chemin MONTÉ diffère (§4) |
|
|
57
|
+
| TOUT répond `404`, même les routes du gabarit | `npx nodefony status` | un autre serveur tient les ports, ou le tien a glissé (§4) |
|
|
58
|
+
| Refus `401` ou `403` inattendu | lire le corps et l'en-tête `WWW-Authenticate` de la réponse | `nodefony-protect-route` (zone, rôle, jeton anti-falsification) |
|
|
59
|
+
| `401` avec `error="insufficient_user_authentication"` | la route exige une connexion récente ou un second facteur | `nodefony-authentication` |
|
|
60
|
+
| `403` « Credentials must be sent over HTTPS » | un mot de passe envoyé en HTTP clair, refusé en production | servir en HTTPS, ou déclarer le proxy TLS (`trustProxy`) |
|
|
61
|
+
| Une erreur dans le journal | le script du §3 | la piste qu'il donne, sinon le message lui-même |
|
|
62
|
+
| « colonne inexistante », « no such table », migrations à appliquer | `npx nodefony doctor --live` | `nodefony-migrate-schema` |
|
|
63
|
+
| Des dizaines de tests d'intégration rouges d'un coup (`ECONNREFUSED`) | `npx nodefony status` | ils FRAPPENT un serveur, ils ne le lancent pas : il est éteint. En e2e, laisse la commande gérer le cycle |
|
|
64
|
+
| Une page est lente, trop de requêtes SQL, des `500` par intermittence | l'outil MCP `nodefony_profile_route { "path": "/la/page" }` | §5 : le rapport nomme la route, la cause et le geste |
|
|
65
|
+
| `nodefony <commande>` échoue là où `npm run dev` réussit | `npm ls nodefony` | deux copies du framework dans le processus (§4) |
|
|
66
|
+
|
|
67
|
+
**Lis toute la réponse d'une commande de diagnostic.** Ne la tronque jamais (`| head`, une
|
|
68
|
+
recherche dans sa sortie) : la ligne qui nomme la cause est presque toujours dans la partie coupée.
|
|
69
|
+
|
|
70
|
+
## 3. Le journal — extraire, pas lire
|
|
71
|
+
|
|
72
|
+
Un journal de développement fait des milliers de lignes, presque toutes saines. Le script lit tout,
|
|
73
|
+
garde les erreurs, recolle chaque pile d'appels à la ligne qui l'a levée, fusionne les répétitions,
|
|
74
|
+
date ce qu'il a lu, et nomme le premier geste quand la cause est établie :
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
node node_modules/@nodefony/devkit/skills/nodefony-troubleshoot/scripts/log-errors.mjs
|
|
78
|
+
node node_modules/@nodefony/devkit/skills/nodefony-troubleshoot/scripts/log-errors.mjs logs/dev.log
|
|
79
|
+
node node_modules/@nodefony/devkit/skills/nodefony-troubleshoot/scripts/log-errors.mjs --warnings --last 40
|
|
80
|
+
node node_modules/@nodefony/devkit/skills/nodefony-troubleshoot/scripts/log-errors.mjs --json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Sans argument, il lit `logs/*.log` et `logs/*.jsonl`. Sorties : `0` aucune erreur · `1` au moins
|
|
84
|
+
une · `64` usage · `66` aucun journal lisible.
|
|
85
|
+
|
|
86
|
+
⚠️ **En développement, le journal part sur la sortie du TERMINAL, pas dans un fichier.** Le script
|
|
87
|
+
répond alors `66` et dit comment l'obtenir : lancer le serveur avec `npx nodefony development
|
|
88
|
+
--detach` (journal dans `logs/nodefony-detached.log`), ou rediriger la sortie dans un fichier qu'on
|
|
89
|
+
lui passe. **Lis l'âge** qu'il affiche pour chaque fichier : un journal d'hier ne parle pas de la
|
|
90
|
+
panne d'aujourd'hui.
|
|
91
|
+
|
|
92
|
+
⚠️ **Une erreur du journal n'est pas toujours une panne.** Un port pris par l'outil du front se
|
|
93
|
+
rattrape seul sur le suivant (la ligne « retrying » qui suit le dit) ; un `CRITIC SIGTERM` est un
|
|
94
|
+
arrêt demandé. Le script le signale quand il le reconnaît — sinon, relie l'erreur au symptôme avant
|
|
95
|
+
de la corriger.
|
|
96
|
+
|
|
97
|
+
## 4. Les pannes qui trompent
|
|
98
|
+
|
|
99
|
+
Chacune a déjà coûté au moins une heure à quelqu'un.
|
|
100
|
+
|
|
101
|
+
- **Ta route répond `404` alors qu'elle existe dans les sources.** Le runtime charge `dist/`, pas
|
|
102
|
+
le source : `npm run build`. C'est la cause n°1.
|
|
103
|
+
- **Une classe que rien ne déclare compile, passe ses tests, et casse au démarrage suivant** —
|
|
104
|
+
entité hors `@entities([…])`, controller hors `@controllers([…])`. Table jamais créée, route en
|
|
105
|
+
`404`. C'est le mode d'échec de la COPIE : on recopie le voisin au lieu d'appeler le générateur,
|
|
106
|
+
qui, lui, déclare. `npx nodefony doctor` la NOMME.
|
|
107
|
+
- **Ta route NEUVE répond `404` et le `dist/` est à jour** : elle n'est pas montée où tu crois. Le
|
|
108
|
+
chemin réel est le PRÉFIXE de son controller suivi du `path` de la route — une action
|
|
109
|
+
`path: "/widget"` dans un controller `@controller("/api")` répond sur `/api/widget`.
|
|
110
|
+
`npx nodefony inspect routes --json` donne le chemin MONTÉ.
|
|
111
|
+
- **TOUT répond `404`** : un AUTRE serveur tient les ports — ou LE TIEN a glissé, le port voulu
|
|
112
|
+
étant pris. `npx nodefony status` montre les ports RÉELS, pas ceux que tu as configurés, et
|
|
113
|
+
NOMME le projet voisin.
|
|
114
|
+
- **Une clé de configuration mal orthographiée ARRÊTE le démarrage** (sortie `78`), en la nommant.
|
|
115
|
+
Une clé retirée par une version du framework produit le même arrêt après un `npm update` : lis
|
|
116
|
+
le message, il nomme la clé.
|
|
117
|
+
- 🔴 **`nodefony <commande>` échoue là où `npm run dev` réussit, sur la MÊME application** : DEUX
|
|
118
|
+
paquets `nodefony` tournent dans le processus — un binaire lié ailleurs (installation globale,
|
|
119
|
+
`npm link`) exécute un noyau pendant que l'application importe le sien. Chaque copie a ses
|
|
120
|
+
propres classes, son contexte de requête et ses registres d'injection : un module construit à la
|
|
121
|
+
frontière perd son container SANS la moindre erreur — il figure dans la liste des modules et ne
|
|
122
|
+
fait rien. ⚠️ Les deux copies peuvent être la MÊME version ; deux fichiers distincts suffisent,
|
|
123
|
+
il n'y a aucune incohérence à repérer. `npm ls nodefony` liste les copies (« deduped » partout = une seule) ;
|
|
124
|
+
`NF_CLI_DEBUG=1 nodefony --version` dit quel CLI s'exécute.
|
|
125
|
+
- **`localhost` et `127.0.0.1` te jouent des tours** : ce sont deux ORIGINES distinctes — cookies,
|
|
126
|
+
cache et passkeys ne les partagent pas. Une session ouverte sur l'une n'existe pas sur l'autre :
|
|
127
|
+
`401` assuré. Une seule origine en développement, partout, URL ouverte comme callbacks.
|
|
128
|
+
- **Ton application a démarré AMPUTÉE et tout a l'air sain** — base injoignable, module écarté par
|
|
129
|
+
sa politique. Seul `npx nodefony doctor` le dit, en relisant `var/last-boot.json`. ⚠️ Ce bilan
|
|
130
|
+
a un ÂGE : il décrit le **dernier démarrage**, et une commande console ne l'écrase pas — lis la
|
|
131
|
+
date avant d'en conclure.
|
|
132
|
+
- **Une suite lancée contre un serveur en `production` reçoit `404` partout** : les modules
|
|
133
|
+
`policy:"dev"` n'y sont pas. `NF_WITH_DEV_MODULES=1` déroge pour 30 minutes
|
|
134
|
+
(`NF_WITH_DEV_MODULES_TTL_MIN`, 4 h au plus), et le `CRITIC « arrêt automatique … dérogation »`
|
|
135
|
+
du journal est cette garde qui se referme — pas une panne.
|
|
136
|
+
- **Un test vert seul et rouge en suite accuse une RESSOURCE PARTAGÉE**, pas ton code : base ou
|
|
137
|
+
index réutilisé, port, store jamais purgé, assertion `count === N` qui suppose une table vierge.
|
|
138
|
+
Lance deux fichiers ENSEMBLE pour isoler la paire, puis cloisonne. **Ne sérialise jamais la
|
|
139
|
+
suite** pour faire passer le rouge : tu masques la cause et tu paies la lenteur à chaque
|
|
140
|
+
exécution.
|
|
141
|
+
- **Les routes authentifiées plafonnent quand le reste tient la charge** : le stockage de session
|
|
142
|
+
par défaut est SYNCHRONE — chaque reprise bloque la boucle d'événements. Compare une route
|
|
143
|
+
anonyme et une route authentifiée AVANT d'accuser TLS ou le pare-feu ; passe le stockage sur
|
|
144
|
+
redis pour la charge.
|
|
145
|
+
|
|
146
|
+
## 5. Mesurer l'application qui tourne — `nodefony_profile_route` et `nodefony_observe`
|
|
147
|
+
|
|
148
|
+
Le profileur de développement mesure chaque requête : temps de chaque phase, chaque requête SQL,
|
|
149
|
+
décision du pare-feu. Deux outils MCP te rendent ces mesures. C'est la seule façon de SAVOIR
|
|
150
|
+
qu'une page est lente ou qu'elle interroge la base dans une boucle — ni le code ni les tests ne le
|
|
151
|
+
montrent. **Mesure avant d'écrire un script de banc** : l'outil le fait déjà, et mieux.
|
|
152
|
+
|
|
153
|
+
| Tu veux… | L'outil | Qui envoie les requêtes |
|
|
154
|
+
| ---------------------------------------------------------------- | ------------------------ | --------------------------------------- |
|
|
155
|
+
| mesurer UNE page, avant/après une modification | `nodefony_profile_route` | l'outil lui-même, N fois, sur un chemin |
|
|
156
|
+
| voir ce que fait le trafic que TU génères (tests, navigation, …) | `nodefony_observe` | toi, pendant une fenêtre de secondes |
|
|
157
|
+
|
|
158
|
+
**Le protocole — mesurer, corriger, re-mesurer :**
|
|
159
|
+
|
|
160
|
+
1. **Une page** : `nodefony_profile_route { "path": "/orders?page=2" }` — un CHEMIN de
|
|
161
|
+
l'application, jamais une URL. `count` (défaut 50, max 200), `concurrency` (défaut 4, max 8),
|
|
162
|
+
`warmup` (défaut 3 : requêtes tirées AVANT et hors mesures — la première compile la route et
|
|
163
|
+
ouvre la connexion à la base). GET (défaut) ou HEAD seulement.
|
|
164
|
+
**Un trafic** : `nodefony_observe { "durationSec": 10 }` (1 à 50 s), et PENDANT la fenêtre,
|
|
165
|
+
sollicite le code — l'outil n'envoie RIEN ; sans trafic, son verdict est « rien à juger ».
|
|
166
|
+
`"route"` restreint à une route, par son NOM (`nodefony_inspect` sujet `routes`).
|
|
167
|
+
2. Lis le rapport (ci-dessous), corrige la cause nommée.
|
|
168
|
+
3. **Rappelle l'outil avec les MÊMES arguments** et compare le bloc `Données (JSON…)` des deux
|
|
169
|
+
appels : un correctif qu'on n'a pas vu changer le chiffre est une hypothèse. Exemple réel, un
|
|
170
|
+
N+1 corrigé par `$in` : 18 requêtes SQL par page → 3, p50 1,2 ms → 0,7 ms.
|
|
171
|
+
|
|
172
|
+
**Au nom de qui — une page protégée vue sans compte ne mesure que des refus.**
|
|
173
|
+
`nodefony_profile_route` joue par défaut le **propriétaire du jeton MCP** si ce jeton porte le
|
|
174
|
+
scope `admin:write` : il ouvre une vraie session à son nom (tous ses rôles), tire avec, puis la
|
|
175
|
+
détruit — l'audit l'écrit (`login.success`, raison `devkit`). `"as": "<identifiant>"` joue un autre
|
|
176
|
+
compte, dont les rôles doivent être inclus dans ceux du propriétaire (jamais de montée en droits).
|
|
177
|
+
`"anonymous": true` force l'anonyme. Sans `admin:write`, l'outil joue l'anonyme et le rapport dit
|
|
178
|
+
la commande : `npx nodefony security:mcp:token --scope "admin:read admin:write" --write` — puis
|
|
179
|
+
relance l'agent, qui lit son jeton au démarrage.
|
|
180
|
+
|
|
181
|
+
**Lire le rapport, dans l'ordre où il s'écrit :**
|
|
182
|
+
|
|
183
|
+
| Ligne | Ce qu'elle dit | Le geste |
|
|
184
|
+
| -------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
185
|
+
| `Verdict : … INCOMPLÈTE` + `⚠️` | les chiffres ne portent pas sur tout — la cause suit, AVANT tout chiffre | lever la cause nommée, rappeler l'outil |
|
|
186
|
+
| `⚠️ … REFUSÉE(S) (401×…, 403×…)` | la page est protégée : ces requêtes ne mesurent rien (verdict « rien à juger ») | anonyme → le jeton `admin:write` ; compte → un compte qui a le rôle (`as`), ou la zone n'accepte pas la session |
|
|
187
|
+
| `⚠️ … REDIRIGÉE(S) vers /login` | la page renvoie vers la connexion : on mesure la redirection, pas la page | jouer un compte, comme ci-dessus |
|
|
188
|
+
| `Tir :` · `Joué en tant que :` | ce qui a été envoyé, la chauffe, l'identité réellement jouée | vérifier que c'est bien la mesure voulue |
|
|
189
|
+
| `N+1 — route … ×N dans une requête` | la même requête SQL répétée N fois dans UNE requête HTTP : une boucle sur la base | charger d'un coup : `relations` du dépôt, ou `$in` sur les identifiants |
|
|
190
|
+
| `Erreurs — route …` + `Journal …` | les `5xx` et les lignes WARNING/ERROR de leur journal, par `requestId` | corriger d'après le message ; `nodefony_admin_call` syslog `logs` pour la suite du journal |
|
|
191
|
+
| `Lente — route … p95 …` | p95 ≥ 500 ms, avec ce qui coûte par requête | `action.self` domine → le code de l'action ou d'un service ; `SQL (cumul)` → les requêtes ; `render` → la vue |
|
|
192
|
+
| `Boucle d'événements bloquée` | un traitement SYNCHRONE a gelé le process ≥ 100 ms : toutes les routes ont attendu | chercher la boucle lourde, l'API `*Sync`, le gros `JSON.parse` ; juste après un démarrage, rappeler plus tard |
|
|
193
|
+
| `Refus (hors percentiles)` (`observe`) | des `401`/`403` dans le trafic observé : ces requêtes ne mesurent rien | appeler avec une session ou un jeton, pas conclure sur ces durées |
|
|
194
|
+
|
|
195
|
+
**Pièges :**
|
|
196
|
+
|
|
197
|
+
- **Ne modifie AUCUN fichier pendant la mesure** : le serveur de développement redémarre, l'outil
|
|
198
|
+
rend un rapport partiel marqué « interrompu ». Rappelle-le une fois le serveur relancé.
|
|
199
|
+
- **Les requêtes de `nodefony_profile_route` sont de VRAIES requêtes** : une page qui écrit en GET
|
|
200
|
+
(compteur, session créée pour chaque visiteur anonyme) écrit N fois. Le rapport le montre — c'est
|
|
201
|
+
souvent une découverte en soi.
|
|
202
|
+
- **Les zones à jeton (`jwt`, `external-jwt`) ne sont pas jouées** : seule la session l'est ; leurs
|
|
203
|
+
requêtes rendent `401`, et le rapport le dit.
|
|
204
|
+
- **Le journal d'une `5xx` n'est lu que par un appelant authentifié** (scope `admin:read`). Sans
|
|
205
|
+
jeton, le rapport le dit et nomme le geste.
|
|
206
|
+
- **`nodefony_observe` écarte l'outillage (`/nodefony/…`)** — console, API d'administration, porte
|
|
207
|
+
MCP ; `"includeTooling": true` le compte. `nodefony_profile_route` mesure le chemin qu'on lui
|
|
208
|
+
donne, quel qu'il soit.
|
|
209
|
+
- **Les valeurs SQL sont masquées** (`?`) : le rapport montre la FORME d'une requête, jamais une
|
|
210
|
+
donnée.
|
|
211
|
+
- **« boucle d'événements : non mesurée »** : le tir a duré moins de cinq périodes de la sonde ;
|
|
212
|
+
augmente `count` pour la lire.
|
|
213
|
+
- **Abandonner l'appel** n'arrête pas toujours l'outil côté serveur : selon le client, il va au bout
|
|
214
|
+
de son tir (45 s au plus) ou de sa fenêtre.
|
|
215
|
+
- Les deux outils n'existent qu'en **développement** (`@nodefony/devkit`) ; ailleurs, ils répondent
|
|
216
|
+
qu'il n'y a aucun profileur.
|
|
217
|
+
|
|
218
|
+
## 6. Avant de dire « réparé »
|
|
219
|
+
|
|
220
|
+
1. **Rejoue le symptôme d'origine** — la même requête, la même commande — et constate qu'il a
|
|
221
|
+
disparu. Un correctif qu'on n'a pas vu agir sur le symptôme est une hypothèse.
|
|
222
|
+
2. **`npx nodefony doctor`** ne signale plus rien de neuf.
|
|
223
|
+
3. **`npm run verify`** : le correctif n'a rien cassé ailleurs.
|
|
224
|
+
4. **Dis la cause**, pas seulement le geste : « le `dist/` était en retard » apprend quelque chose
|
|
225
|
+
au suivant ; « j'ai relancé le build » ne lui apprend rien.
|