khalid #1
1
.gitignore
vendored
1
.gitignore
vendored
@@ -15,3 +15,4 @@ docs/
|
||||
*.spec
|
||||
build/
|
||||
dist/
|
||||
docs/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,188 +0,0 @@
|
||||
# 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`** — classe `UserMonitor` : thread de fond, parsing des logs, cache thread-safe. Miroir exact de `SystemMonitor`.
|
||||
|
||||
### 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-02` pour 2026-04-02)
|
||||
- Tous les fichiers du jour sont lus, triés par index `N` croissant
|
||||
- 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 :
|
||||
```python
|
||||
r'^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*login=([^,]+),action=([^,]+),Label=(.+)"?$'
|
||||
```
|
||||
|
||||
- `timestamp` → groupe 1
|
||||
- `login` → 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 :
|
||||
```python
|
||||
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 :
|
||||
```python
|
||||
r'^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*method=closeSession'
|
||||
```
|
||||
|
||||
### Modèle par utilisateur (cache)
|
||||
|
||||
```python
|
||||
{
|
||||
"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`
|
||||
|
||||
```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-8` avec `errors='ignore'` pour tolérer les caractères invalides
|
||||
- **Performance** : les fichiers `isoft_*.log` peuvent être très volumineux (index > 80). Le parsing lit ligne par ligne sans charger le fichier en mémoire (`for line in f`)
|
||||
@@ -1,151 +0,0 @@
|
||||
# Design — supervision-rs
|
||||
|
||||
**Date :** 2026-04-07
|
||||
**Objectif :** Réécrire l'application de supervision système en Rust pour produire un exécutable Windows standalone, sans dépendances, déployable par simple copie.
|
||||
|
||||
---
|
||||
|
||||
## Contexte
|
||||
|
||||
L'application actuelle est en Python (Flask + psutil + PyInstaller). Le tuteur a recommandé une réécriture en Rust pour obtenir un exécutable plus stable sur Windows. Le binaire doit être autonome : on le copie sur n'importe quel serveur Windows, on l'installe comme service, et c'est tout.
|
||||
|
||||
---
|
||||
|
||||
## Périmètre fonctionnel
|
||||
|
||||
Parité complète avec l'app Python actuelle :
|
||||
|
||||
- Interface web sécurisée (login admin, cookie de session)
|
||||
- Dashboard temps réel : CPU, RAM, disques, processus surveillés
|
||||
- Alertes email (SMTP plain ou STARTTLS) avec cooldown configurable
|
||||
- Configuration via UI (seuils, SMTP, intervalle, processus)
|
||||
- Historique des alertes (max 500, rotation automatique)
|
||||
- Fonctionne comme service Windows (démarre avec Windows, tourne en arrière-plan)
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Structure du projet
|
||||
|
||||
```
|
||||
supervision-rs/
|
||||
├── Cargo.toml
|
||||
├── src/
|
||||
│ ├── main.rs # Point d'entrée + intégration service Windows
|
||||
│ ├── config.rs # Lecture/écriture config.json et alerts.json
|
||||
│ ├── monitor.rs # Thread de collecte métriques + évaluation seuils
|
||||
│ ├── alerter.rs # Envoi email SMTP
|
||||
│ ├── auth.rs # Session admin, rate limiting login
|
||||
│ └── routes.rs # Endpoints Axum (dashboard, API, config, login)
|
||||
├── templates/ # Templates Tera (portés depuis Jinja2)
|
||||
│ ├── base.html
|
||||
│ ├── dashboard.html
|
||||
│ ├── login.html
|
||||
│ ├── config.html
|
||||
│ └── alerts.html
|
||||
└── data/ # Créé au premier lancement (gitignored)
|
||||
├── config.json
|
||||
└── alerts.json
|
||||
```
|
||||
|
||||
### Crates
|
||||
|
||||
| Crate | Rôle | Équivalent Python |
|
||||
|---|---|---|
|
||||
| `axum` | Serveur HTTP async | Flask |
|
||||
| `tokio` | Runtime async | — |
|
||||
| `tera` | Templates HTML | Jinja2 |
|
||||
| `sysinfo` | Métriques CPU/RAM/disque/processus | psutil |
|
||||
| `lettre` | Email SMTP | smtplib |
|
||||
| `serde` + `serde_json` | Sérialisation config/alertes | json |
|
||||
| `windows-service` | Intégration service Windows | — |
|
||||
| `tower-sessions` | Sessions auth (cookie signé) | Flask-Login |
|
||||
| `tower_governor` | Rate limiting | Flask-Limiter |
|
||||
| `tracing` | Logs | logging |
|
||||
|
||||
---
|
||||
|
||||
## Modes de démarrage
|
||||
|
||||
```
|
||||
supervision.exe → mode console (test, développement)
|
||||
supervision.exe install → installe le service Windows
|
||||
supervision.exe uninstall → supprime le service Windows
|
||||
(lancé par Windows SCM) → mode service (background automatique)
|
||||
```
|
||||
|
||||
Détection automatique dans `main.rs` : si lancé par le Service Control Manager de Windows, entre en mode service. Sinon, mode console.
|
||||
|
||||
**Installation sur un serveur :**
|
||||
```cmd
|
||||
supervision.exe install
|
||||
sc start Supervision
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## State partagé (concurrence)
|
||||
|
||||
```
|
||||
Arc<AppState>
|
||||
├── config: RwLock<Config> # Config lue/écrite par routes + monitor
|
||||
├── metrics: RwLock<Metrics> # Écrit par monitor, lu par /api/metrics
|
||||
└── alerter: Alerter # Utilisé par monitor
|
||||
```
|
||||
|
||||
Le thread de monitoring est une `tokio::task` qui tourne en arrière-plan. Il met à jour `metrics` via `RwLock`. Les routes Axum lisent ce state sans bloquer.
|
||||
|
||||
---
|
||||
|
||||
## Authentification
|
||||
|
||||
- Un seul admin, identifiants stockés dans `config.json` (mot de passe hashé bcrypt)
|
||||
- Session via cookie signé (`tower-sessions`)
|
||||
- Rate limiting sur `POST /login` : 10 tentatives/minute
|
||||
- Toutes les routes (sauf `/login`, `/static`) redirigent vers login si non authentifié
|
||||
|
||||
---
|
||||
|
||||
## Métriques & seuils
|
||||
|
||||
Collecte via `sysinfo` :
|
||||
- CPU : pourcentage global
|
||||
- RAM : pourcentage utilisé, total/utilisé/disponible en Go
|
||||
- Disques : partitions physiques ≥1 Go, pourcentage, espace total/utilisé/libre
|
||||
- Processus : recherche par pattern dans nom ou ligne de commande, mémoire RSS, CPU
|
||||
|
||||
Niveaux de statut (identique au Python) :
|
||||
- `ok` : < 80% du seuil
|
||||
- `warning` : ≥ 80% du seuil
|
||||
- `critical` : ≥ 100% du seuil
|
||||
|
||||
---
|
||||
|
||||
## Alertes email
|
||||
|
||||
- SMTP plain ou STARTTLS (configurable)
|
||||
- Cooldown par clé (en mémoire, réinitialisé au redémarrage)
|
||||
- Alertes déclenchées sur : CPU critique, RAM critique, disque critique, processus arrêté, mémoire processus critique
|
||||
- Stockage dans `alerts.json` (max 500 entrées, rotation FIFO)
|
||||
|
||||
---
|
||||
|
||||
## Persistance
|
||||
|
||||
- `data/config.json` : configuration complète (seuils, SMTP, admin, processus surveillés, intervalle)
|
||||
- `data/alerts.json` : historique des alertes
|
||||
- Dossier `data/` créé automatiquement au premier lancement, dans le même répertoire que l'exe
|
||||
- Pas de base de données
|
||||
|
||||
---
|
||||
|
||||
## Déploiement
|
||||
|
||||
1. Compiler sur Windows : `cargo build --release`
|
||||
2. Récupérer `target/release/supervision.exe`
|
||||
3. Copier l'exe seul sur le serveur cible
|
||||
4. Lancer `supervision.exe install` puis `sc start Supervision`
|
||||
5. Accéder à `http://localhost:5000` dans le navigateur
|
||||
|
||||
Aucune autre dépendance requise sur le serveur cible.
|
||||
Reference in New Issue
Block a user