6.7 KiB
Design — Onglet Utilisateurs Amadea
Date : 2026-04-02
Statut : Approuvé
Contexte
Ajouter un onglet "Utilisateurs" à l'application de supervision, affichant en temps réel les utilisateurs connectés à Amadea Web 8 x64, leur statut d'activité, et un graphique d'utilisation horaire. Le chemin des logs Amadea et les seuils de statut sont rendus configurables dans l'onglet Configuration existant.
Architecture générale
Nouveaux fichiers
user_monitor.py— classeUserMonitor: thread de fond, parsing des logs, cache thread-safe. Miroir exact deSystemMonitor.
Fichiers modifiés
| Fichier | Modification |
|---|---|
config_manager.py |
Ajout des clés amadea_log_path et user_status_thresholds dans la config par défaut |
app.py |
Instanciation de UserMonitor, routes /users et /api/users |
templates/base.html |
Lien "Utilisateurs" dans la navbar |
templates/settings.html |
2 nouveaux blocs de configuration |
templates/users.html |
Nouvelle page (tableau + graphique CSS) |
Flux de données
UserMonitor (background thread)
├─ parse awevents_YY-MM-DD_*.log → activité utilisateur + déconnexions explicites
└─ parse isoft_YY-MM-DD_*.log → événements de session (login/timeout)
↓ cache thread-safe (dict par login)
/api/users → JSON
/users → rendu Jinja2 initial + auto-refresh JS (30s, même pattern que dashboard)
Parsing et modèle de données
Sélection des fichiers du jour
Les fichiers de logs suivent le pattern PREFIX_YY-MM-DD_N.ext (ex: awevents_26-04-02_1.log).
- Date du jour formatée en
%y-%m-%d(ex:26-04-02pour 2026-04-02) - Tous les fichiers du jour sont lus, triés par index
Ncroissant - Si plusieurs fichiers du même jour existent (index incrémental), ils sont tous parsés dans l'ordre
Format awevents_YY-MM-DD_N.log (source principale)
2026-03-30 10:34:24.034;INFO ;;;;"login=JENKINS,action=SelectionChange,Label=BAO_Main/..."
Regex d'extraction :
r'^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*login=([^,]+),action=([^,]+),Label=(.+)"?$'
timestamp→ groupe 1login→ groupe 2 (identifiant utilisateur)action→ groupe 3 (SelectionChange, Action, Click, ValueChange…)label→ groupe 4 (contexte UI)
Déconnexion explicite : ligne dont le label contient se deconnecter
Format isoft_YY-MM-DD_N.log (complément sessions)
2026-03-30 10:33:05.830;INFO ;"ISExecutingThread...";...;"method=OpenUserSession,...,login=JENKINS"
Regex pour login réussi :
r'^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*method=OpenUserSession.*login=([A-Za-z0-9_]+)'
Regex pour timeout de session :
r'^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*method=closeSession'
Modèle par utilisateur (cache)
{
"login": str, # identifiant (ex: "JENKINS")
"last_action_time": datetime, # horodatage de la dernière action
"last_action_label": str, # label de la dernière action (tronqué à 60 chars)
"action_count_24h": int, # nombre d'actions dans les dernières 24h
"status": str, # "actif" | "inactif" | "deconnecte"
"explicit_logout": bool, # True si déconnexion explicite détectée
"connected_since": datetime | None, # heure de la première action du jour (premier awevents du jour pour cet utilisateur)
}
Règles de statut
Seuils configurables (clé user_status_thresholds, défauts : active_minutes=5, inactive_minutes=30) :
| Condition | Statut |
|---|---|
| Déconnexion explicite détectée | DÉCONNECTÉ |
Dernière action > inactive_minutes |
DÉCONNECTÉ |
Dernière action entre active_minutes et inactive_minutes |
INACTIF |
Dernière action < active_minutes |
ACTIF |
Graphique d'activité horaire
Comptage du nombre d'utilisateurs distincts ayant au moins une action par tranche horaire (H:00 → H:59). Données issues uniquement des fichiers du jour (awevents_*.log).
Pour le sélecteur "7 derniers jours" : si les fichiers zippés ne sont pas disponibles (cas nominal en prod), afficher un alert-info : "Les données historiques des jours précédents ne sont pas disponibles (fichiers archivés)."
Configuration
Nouvelles clés dans config.json
{
"amadea_log_path": "C:\\ProgramData\\ISoft\\Amadea Web 8 x64\\data\\logs",
"user_status_thresholds": {
"active_minutes": 5,
"inactive_minutes": 30
}
}
Nouveaux blocs dans settings.html
Bloc 1 — Chemin des logs Amadea (même style card + form-control + btn btn-primary) :
- Champ texte pré-rempli avec la valeur actuelle
- Bouton "Enregistrer"
- Route POST :
/settings/amadea-log-path
Bloc 2 — Seuils statut utilisateurs (même style que le bloc "Seuils d'alerte") :
- Champ numérique "Actif si dernière action < N min" (défaut: 5)
- Champ numérique "Inactif si dernière action < N min" (défaut: 30)
- Bouton "Enregistrer"
- Route POST :
/settings/user-thresholds
Interface utilisateurs (users.html)
Tableau
Colonnes : Utilisateur | Statut | Dernière action | Actions (24h) | Depuis
Tri par défaut : Actifs → Inactifs → Déconnectés (ordre de priorité statut).
Badges Bootstrap cohérents avec l'existant :
- ACTIF →
<span class="badge bg-success">ACTIF</span> - INACTIF →
<span class="badge bg-warning text-dark">INACTIF</span> - DÉCONNECTÉ →
<span class="badge bg-secondary">DÉCONNECTÉ</span>
Graphique d'activité
Barres CSS Bootstrap (divs avec hauteur proportionnelle), aucune librairie externe.
Une barre par heure de la journée (00h–23h), largeur fixe, hauteur = (valeur / max) * 100%.
Couleur : bg-primary. Tooltip au survol (attribut title).
Auto-refresh
setInterval toutes les 30 secondes, appel fetch('/api/users'), même pattern que refreshMetrics() dans dashboard.html.
Gestion d'erreurs
| Cas | Affichage |
|---|---|
| Dossier de logs introuvable | alert alert-warning avec le chemin configuré |
| Aucun fichier du jour trouvé | alert alert-info "Aucun log disponible pour aujourd'hui" |
| Fichier verrouillé/illisible | Ignoré silencieusement, parsing continue |
| Aucun utilisateur détecté | Message text-muted dans le tableau |
Choix techniques
- Librairie graphique : barres CSS Bootstrap pures (aucune dépendance externe)
- Thread : daemon thread (comme
SystemMonitor), s'arrête avec l'application - Encodage fichiers :
utf-8avecerrors='ignore'pour tolérer les caractères invalides - Performance : les fichiers
isoft_*.logpeuvent être très volumineux (index > 80). Le parsing lit ligne par ligne sans charger le fichier en mémoire (for line in f)