---
puppeteer:
    format: A4
    margin:
        top: "0.5cm"
        left: "0.5cm"
        right: "0.5cm"
        bottom: "0.5cm"
---

# Application Web - Activité 2 - Service d'observation des données d'utilisation de la machine

## Objectifs

- Développement d'une application Python qui collecte les métriques système
- Communication entre une application Python et une base PostgreSQL
- Développement d'une image Docker pour intégrer votre application dans le système

## Évaluation

- L'évaluation aura lieu
  - au cours de l'activité sous forme orale
  - à la fin de l'activité grâce aux livrables rendus

### Compétences évaluées


## Validation
### Livrables

Livrer le code et le dossier de conception à l'issue des 3 activités.

### Résultats attendus

- [ ] Un programme python qui observe les données du système et les enregistre en base de données
- [ ] Une image docker contenant le programme : le service de monitoring
- [ ] Une mise à jour du fichier docker-compose pour intégrer le service avec la base de données dans les bonnes pratiques de sécurité

## Étapes

### Étape 0 – Démarrage et configuration de l’environnement

**Objectif :** Créer un environnement pour le développement de l'application de monitoring, et installation des dépendances. 

!!! example À faire
    Nous repartons de l'environnement créé lors de l'activité précédente
    - Créez un nouveau répertoire `monitoring` dans votre dépôt.
    - Ajoutez-y un fichier [`requirements.txt`](https://pip.pypa.io/en/stable/reference/requirements-file-format/) listant les dépendances : `psutil==7.1.3` et `psycopg[binary]==3.2.12`.
    - Créez un environnement virtuel Python (`venv`) et installez ces dépendances. (voir aide)
      - Installer dépendances d'un `requirements.txt` : (dans un environnement virtuel activé) `pip install -r requirements.txt`
    - À l’intérieur de `monitoring`, créez un sous-dossier `src` pour les sources Python, et dedans un fichier `app.py`

!!! question Aide
    - Un environnement virtuel Python (venv) est un espace isolé qui contient une installation indépendante de Python ainsi que ses propres bibliothèques, ce qui évite les conflits entre projets. 
    - Pour créer un venv, on utilise la commande : `python -m venv .venv`. 
    - Ensuite, on active cet environnement avec la commande `source .venv/bin/activate` 
    - Enfin, on peut installer des dépendances spécifiques au projet sans impacter l’installation globale de Python ni d’autres projets

### Étape 1 – Script de collecte des données

**Objectif :** Écrire la fonction qui collectera les données de fonctionnement du système

!!! example À faire
    - Écrivez une fonction `collect_metrics()` qui récupère les données de monitoring système.
      - Cette fonction doit retourner un dictionnaire Python contenant les métriques nécessaires
      - Utilisez la bibliothèque `psutil` et sa [documentation](https://psutil.readthedocs.io/en/latest/#) pour récupérer ces données
      - Les données dont vous avez besoin sont celles demandées par le cahier des charges et pour lesquelles vous avez conçu votre base lors de l'activité précédente
    - Écrivez une fonction main et appelez-la dans votre script. Elle devra appeler votre fonction `collect_metrics()`.
    - Testez et validez votre code (en affichant, par exemple, le résultat obtenu)
    - Complétez votre document de conception et faites un nouveau commit

!!! note Dans le document de conception
    Expliquez ce que vous avez réalisé dans cette partie

### Étape 2 - Écriture en base de données

**Objectif:** Écrire la fonction pour insérer les données récoltées en base de données

!!! example À faire
    - Récupérez les informations de connexion (hôte, base, utilisateur, mot de passe, port) [depuis les variables d’environnement](https://docs.python.org/3/library/os.html#os.environ) Python suivantes : `DB_HOST`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `DB_PORT`.
    - Utilisez `psycopg3.connect()` pour établir la connexion.
        ```python
        conn = psycopg3.connect(
            host=DB_HOST,
            dbname=DB_NAME,
            user=DB_USER,
            password=DB_PASSWORD,
            port=DB_PORT
        )
        ```
    - Écrire la fonction qui permettra d'insérer les données en base (voir aide). Cette fonction prendra en paramètre le dictionnaire créé dans l'étape précédente.
    - Ajouter la nouvelle fonction à la fonction `main`. 
    - Pour tester votre programme localement (avec la base de données dans le conteneur)
      - Lier le port 5432 du conteneur au port 5432 de la machine hôte dans le docker compose (et le relancer)
      - Ajouter les variables d'environnement dans la commande permettant de lancer votre script, comme ci-dessous :
        ```bash
        DB_HOST=localhost DB_NAME=sysmon DB_USER=metricwriter DB_PASSWORD=metricwriter DB_PORT=5432 python app.py
        ```
    - Tester votre code et le valider
    - Pour finir, il faut utiliser `time.sleep` et une boucle `while` infinie dans `main` pour recommencer l'opération chaque seconde.
      - La période de mesure doit être configurable par variable d'environnement également. 1 seconde sera la valeur par défaut.
    - Mettre à jour le document de conception et faire un nouveau commit

!!! question Aide
    Pour insérer des données dans une base Postgres en Python :
    ```py
    cur = conn.cursor() # Création d'un curseur à partir de la connexion : c'est l'objet qui va permettre d'exécuter les commandes SQL.
    sql = "remplacer par requête" # Définition de la requête SQL d'insertion sous forme de chaîne de caractères. Ici, il faut remplacer cette chaîne par la requête INSERT adaptée.

    cur.execute(sql, metrics) # Exécution de la requête SQL en passant les valeurs à insérer via le dictionnaire 'metrics'. Cela évite les injections SQL en utilisant des paramètres.

    conn.commit() # Validation de la transaction : sans cet appel, les changements effectués ne seraient pas enregistrés définitivement dans la base.
    cur.close() # Fermeture du curseur pour libérer les ressources utilisées par cet objet.
    conn.close() # Fermeture de la connexion à la base, elle doit être fermée proprement pour éviter les fuites de connexions et libérer les ressources.
    ```

!!! warning Attention
    Vous avez lié le port 5432 du conteneur postgres à celui de l'hôte. C'est utile en debug mais à proscrire en production, sauf si vous savez ce que vous faites. N'oubliez pas de retirer cette directive lorsque votre code est validé.

!!! note Dans le document de conception
    - Expliquez les différentes étapes pour se connecter et écrire dans une base de données PostgresSQL depuis un programme Python
    - Le port 5432 est le port standard de postgreSQL. Quel est le risque si on le laisse mappé sur le port 5432 de la machine hôte ?
    - Expliquer le fonctionnement actuel de votre programme

### Étape 3 – Conteneurisation avec Docker

!!! example À faire
    - Créer un nouveau fichier appelé `Dockerfile` dans votre répertoire `monitoring`. Il servira à créer votre image docker pour le service de monitoring. 
    - Ce fichier sera basé sur l'image `python:3.13-slim-bookworm`
    - Écrire le Dockerfile à l'aide des informations suivantes :
      - S'inspirer de la [documentation de l'image Python](https://hub.docker.com/_/python/)
      - Il faudra installer les dépendances du fichier `requirements.txt`
      - Il faut ajouter les fichiers du répertoire `src`
      - Votre commande sera `python app.py`
    - Construire l'image pour valider sa compilation : `docker build -t monitoring-service monitoring`

!!! note Dans le document de conception
    - Expliquez l'intérêt d'utiliser `python:3.13-slim-bookworm` par rapport aux autres tags de l'image python (pourquoi `slim`, pourquoi `bookworm` ?)
    - Pourquoi est-il inutile de créer un environnement virtuel dans notre image ?
    - Expliquez les différentes étapes de votre Dockerfile et vos choix

### Étape 4 – Intégration dans un environnement multi-conteneurs

!!! example À faire
    - Compléter le fichier `docker-compose.yml` pour y ajouter le service de monitoring. Compléter les informations :
      - image : monitoring-service
      - réseau : voir cahier des charges (architecture). Attention à le déclarer et à l'ajouter aussi au service postgres
      - environment : variables de connexion à la base de données
    - Démarrer votre stack et vérifier que tout fonctionne

!!! note Dans le document de conception
    - Pourquoi a-t-on choisi d'avoir un réseau distinct pour accéder à la base de données ?
    - Expliquez ce que vous avez réalisé dans cette partie, et dans cette activité.
    - Donnez les difficultés rencontrées et la manière dont vous les avez résolues.

