Documentation : structure README / CLAUDE / DECISIONS / MONITORING
Nouveaux documents :
- README.md : porte d'entrée humaine, absente jusqu'ici. Objet du projet,
installation, npm test, branchement Claude Desktop, ajout d'un profil WMS,
compilation de l'exécutable.
- DECISIONS.md : 20 décisions et pièges vérifiés sur un WMS réel (D1..D20),
chacun avec son pourquoi. Extrait ce qui était noyé dans CLAUDE.md :
100 % API, tenant_code OAuth, réponses {entities}, casse des propriétés,
dotenv sur stderr, dates relatives LINQ non traduisibles, absence de
CommandParameterData, etc.
- MONITORING.md : supervision du serveur MCP. Préfixes de logs, séquence
d'un démarrage sain, cycle de vie du token OAuth et ses trois filets,
état des caches, table symptôme -> cause. Une section dit explicitement
ce qui n'est pas instrumenté (ni healthcheck, ni métriques, ni alerte).
- docs/logs.md : accès aux logs du WMS. Chemins, placeholder {host},
blocage volontaire sur les profils SaaS, les trois outils, format des
lignes, limites connues.
Mises à jour :
- CLAUDE.md réécrit et aligné sur le code. Correction de l'écart le plus
gênant : le code utilise QueryType 0 (Reading), la doc annonçait 1, soit
l'inverse de ce qui fonctionne pour les comparaisons de statut par
chaîne. Corrigés également : 6 resources et non 7 (workflows://categories
n'existe pas), section .env mono-profil obsolète, références à des
fichiers de test absents, README annoncé mais inexistant. Le suivi de
projet et les checklists de phases sont retirés.
- docs/README.md : index réel du dossier. L'ancien promettait une resource
docs:// qui n'a jamais existé.
- docs/getting_started.md : avertissement en tête, c'est une capture
partielle du portail Mecalux dont les liens internes ne résolvent pas.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+165
@@ -0,0 +1,165 @@
|
||||
# Logs du WMS
|
||||
|
||||
Comment le serveur MCP accède aux fichiers de logs du WMS, ce qu'il sait faire
|
||||
et ce qu'il ne peut pas faire.
|
||||
|
||||
Pour superviser **le serveur MCP lui-même**, voir
|
||||
[MONITORING.md](../MONITORING.md).
|
||||
|
||||
---
|
||||
|
||||
## 1. Où sont les logs
|
||||
|
||||
Les logs sont lus **directement sur le système de fichiers** du serveur WMS,
|
||||
via des partages réseau Windows — jamais par API.
|
||||
|
||||
| Emplacement | Contenu |
|
||||
|---|---|
|
||||
| `\\<host>\inetpub\logs\LogFiles\Mecalux` | logs applicatifs IIS, organisés en sous-dossiers par composant |
|
||||
| `\\<host>\ProgramData\Mecalux\ETLLogs` | logs du middleware ETL |
|
||||
|
||||
Configuration dans `.env`, plusieurs chemins séparés par des `;` :
|
||||
|
||||
```env
|
||||
LOGS_PATH=\\{host}\inetpub\logs\LogFiles\Mecalux;\\{host}\ProgramData\Mecalux\ETLLogs
|
||||
```
|
||||
|
||||
**Le placeholder `{host}` est remplacé à chaque appel** par le host du profil
|
||||
actif. Il n'y a donc pas de chemin de logs à redéfinir par profil : un seul
|
||||
gabarit suffit, et il suit automatiquement `switch_wms_profile`.
|
||||
|
||||
Le scan est **récursif** et ne retient que les fichiers dont le nom se termine
|
||||
par `.log`. Un dossier absent ou inaccessible n'interrompt pas le scan : il est
|
||||
journalisé (`[Logs] Cannot scan directory …`) et ignoré.
|
||||
|
||||
---
|
||||
|
||||
## 2. Prérequis d'accès
|
||||
|
||||
Les partages `\\<host>\...` doivent être joignables **depuis la machine qui
|
||||
exécute le serveur MCP**, avec les droits de lecture du compte Windows courant.
|
||||
Le serveur ne présente aucun credential propre pour SMB — il hérite de la
|
||||
session Windows.
|
||||
|
||||
Vérification rapide, hors serveur MCP :
|
||||
|
||||
```bash
|
||||
Test-Path "\\10.255.255.2\inetpub\logs\LogFiles\Mecalux"
|
||||
```
|
||||
|
||||
Si cette commande renvoie `False`, aucun outil de log ne fonctionnera : le
|
||||
problème est réseau ou droits, pas applicatif.
|
||||
|
||||
---
|
||||
|
||||
## 3. Profils SaaS : les logs ne sont pas accessibles
|
||||
|
||||
Quand le profil actif est déclaré `<PROFIL>_SAAS=true`, les trois outils de log
|
||||
**échouent volontairement** avec :
|
||||
|
||||
> Log access is disabled for SaaS profile "X". The WMS is cloud-hosted — local
|
||||
> log files are not reachable. Use the WMS API (query/command/workflow tools)
|
||||
> instead.
|
||||
|
||||
C'est un choix explicite, pas une régression : le WMS est hébergé dans le cloud
|
||||
Mecalux, son système de fichiers n'est pas exposé. Retourner « 0 fichier »
|
||||
laisserait croire à une absence d'erreurs — un faux négatif dangereux en
|
||||
diagnostic. Voir D9 dans [DECISIONS.md](../DECISIONS.md).
|
||||
|
||||
**Sur un profil SaaS, le diagnostic passe donc uniquement par les API** :
|
||||
`query_wms_entities`, `count_wms_entities`, `search_wms_data`, les outils AD et
|
||||
`get_system_parameters`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Les trois outils
|
||||
|
||||
### `list_log_files`
|
||||
|
||||
Liste tous les `.log` trouvés sous `LOGS_PATH`, **triés du plus récent au plus
|
||||
ancien**, avec taille, date de modification et dossier d'origine. Point de
|
||||
départ naturel : il montre quels composants ont écrit récemment.
|
||||
|
||||
Si aucun fichier n'est trouvé, l'erreur **énumère les chemins scannés** — c'est
|
||||
généralement suffisant pour diagnostiquer un `{host}` mal résolu.
|
||||
|
||||
### `read_recent_logs(count, log_file)`
|
||||
|
||||
Renvoie les `count` dernières lignes (100 par défaut). Sans `log_file`, prend
|
||||
**le fichier le plus récemment modifié, tous dossiers confondus** — ce qui n'est
|
||||
pas forcément celui que l'on croit sur un serveur multi-composants ; préférez
|
||||
nommer le fichier.
|
||||
|
||||
La résolution de `log_file` se fait en trois passes, de la plus stricte à la
|
||||
plus permissive :
|
||||
|
||||
1. chemin direct sous le premier `LOGS_PATH`
|
||||
(ex. `ApplicationDictionary\ApplicationDictionary.log`) ;
|
||||
2. nom exact recherché dans chaque sous-dossier immédiat ;
|
||||
3. correspondance partielle, insensible à la casse.
|
||||
|
||||
En cas d'échec, l'erreur liste les fichiers disponibles.
|
||||
|
||||
### `search_logs(keyword, max_results, context_lines)`
|
||||
|
||||
Recherche insensible à la casse dans **tous** les fichiers, du plus récent au
|
||||
plus ancien, en s'arrêtant à `max_results` (50 par défaut). Chaque résultat
|
||||
porte son fichier, son numéro de ligne et `context_lines` lignes avant/après (2
|
||||
par défaut), la ligne trouvée étant marquée `isMatch`.
|
||||
|
||||
C'est l'outil à privilégier pour tracer un identifiant métier (numéro de
|
||||
commande, code produit, id de tâche) à travers les composants.
|
||||
|
||||
---
|
||||
|
||||
## 5. Format des lignes
|
||||
|
||||
`ApplicationService.log` suit ce format :
|
||||
|
||||
```
|
||||
YYYY-MM-DD HH:MM:SS.ffff [thread] [Level] [Component] [message]
|
||||
```
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
2026-08-24 09:14:22.1873 [42] [ERROR] [OutboundOrderService] [Order 4711 not found]
|
||||
```
|
||||
|
||||
Conséquence pratique : une recherche par **date préfixe** (`2026-08-24 09:`)
|
||||
fonctionne bien, et le niveau se filtre par `[ERROR]` — crochets inclus, pour
|
||||
éviter les faux positifs sur le mot « error » dans un message.
|
||||
|
||||
Les logs ETL n'ont pas le même format ; ne présumez pas d'une structure commune
|
||||
entre les deux emplacements.
|
||||
|
||||
---
|
||||
|
||||
## 6. Limites à connaître
|
||||
|
||||
- **Lecture intégrale en mémoire.** `read_recent_logs` et `search_logs`
|
||||
chargent chaque fichier entier avant de le découper. Sur un log de plusieurs
|
||||
centaines de Mo, c'est lent et coûteux en RAM. Vérifiez les tailles avec
|
||||
`list_log_files` avant de lancer une recherche large.
|
||||
- **Recherche par sous-chaîne uniquement**, pas d'expression régulière.
|
||||
- **Pas de filtre temporel** : `search_logs` ne sait pas restreindre à une
|
||||
plage horaire. Le contournement est d'inclure le préfixe de date dans le
|
||||
mot-clé.
|
||||
- **Aucun filtre de nom de fichier configurable.** Le scan retient tous les
|
||||
`.log`. (Une variable `LOG_FILE_PATTERN` a existé dans `.env` sans jamais
|
||||
être appliquée ; elle a été supprimée — voir D20.)
|
||||
- **Pas de rotation ni de purge** : le serveur MCP lit, il n'écrit ni ne
|
||||
supprime rien.
|
||||
|
||||
---
|
||||
|
||||
## 7. Hors périmètre : l'historique des shipment templates
|
||||
|
||||
Les logs `ApplyShipmentTemplates` **ne sont pas présents** sur l'hôte joignable
|
||||
(`10.255.255.2`) : ils résident sur les serveurs de production / ETL des
|
||||
clients. Aucun outil ne les analyse, car il n'y aurait rien à lire.
|
||||
|
||||
Ce que l'on peut obtenir par API se limite à la **dernière** exécution, via
|
||||
l'entité Reading `ShipmentTemplate` (`LastExecuteDate`, `Status`,
|
||||
`IsEnabled`). Voir D16 dans [DECISIONS.md](../DECISIONS.md) et les recettes de
|
||||
la resource `wms://query-examples`.
|
||||
Reference in New Issue
Block a user