v0.1.2-pre.004

This commit is contained in:
2026-08-14 18:43:54 +02:00
parent 488d8ae0a8
commit 151590422d
12 changed files with 803 additions and 91 deletions

View File

@@ -1,13 +1,13 @@
<!-- file: docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md -->
<!-- version: 6 -->
<!-- version: 7 -->
# Plan KSP 0.1.2 — Logging foundation
## Statut
Plan actif de `0.1.2`, établi par `0.1.2-pre.001`, corrigé par `0.1.2-pre.001-fix.001`, concrétisé par la façade de `0.1.2-pre.002` puis étendu au runtime subscriber par `0.1.2-pre.003` et son correctif `0.1.2-pre.003-fix.001`.
Plan actif de `0.1.2`, établi par `0.1.2-pre.001`, corrigé par `0.1.2-pre.001-fix.001`, concrétisé par la façade de `0.1.2-pre.002`, étendu au runtime subscriber par `0.1.2-pre.003`/`pre.003-fix.001`, puis complété par les sorties non bloquantes de `0.1.2-pre.004`.
`pre.002-fix.001` a été validé dans l'environnement de développement avec `cargo fmt`, `cargo check`, `cargo clippy --workspace --all-targets` et `cargo test --workspace` propres sur la version Cargo `0.1.2-pre.2.fix.1`. Pour `pre.003`, `cargo fmt`, `cargo check` et `cargo clippy --workspace --all-targets` sont propres, mais `cargo test --workspace` a révélé un panic de `tracing-subscriber` lors du premier hot reload avec console : un `Filtered` nouvellement injecté dans le `Vec` reloadable ne possédait pas de `FilterId` enregistré. `pre.003-fix.001` sépare donc le `Targets` global du formatter afin qu'aucun `Filtered` ne soit remplacé par `Handle::reload`. Les writers non bloquants, le fichier, les guards et le stripping ANSI restent réservés à `pre.004`.
`pre.003-fix.001` a été validé dans l'environnement de développement avec `cargo fmt --all`, `cargo check --workspace`, `cargo clippy --workspace --all-targets` et `cargo test --workspace` propres sur la version Cargo `0.1.2-pre.3.fix.1`. `pre.004` ajoute `tracing-appender`, remplace la console synchrone par un writer non bloquant, introduit le fichier `Never/Hourly/Daily`, possède les `WorkerGuard`, expose des compteurs cumulés de dropped lines, déporte le stripping ANSI côté worker fichier et conserve le hot reload transactionnel des sinks. Les validations Cargo de cette nouvelle tranche restent à exécuter dans le workspace utilisateur avant validation.
## Base auditée
@@ -93,7 +93,7 @@ tracing-appender 0.2.5 MSRV annoncé : rustc 1.63+
Ces exigences restent inférieures au MSRV déjà imposé indirectement par la génération Solana retenue dans `0.1.1` (`solana-pubkey 4.3.0` / workspace Solana SDK auditée à Rust 1.89.0). Logging ne relève donc pas le plancher observé du workspace.
Les versions sont revérifiées au moment exact de leur ajout effectif au manifest. Pour `pre.002`, `tracing` reste à `0.1.44`, publié dans la génération `^0.1`; `tracing-subscriber` et `tracing-appender` ne sont pas encore ajoutés.
Les versions sont revérifiées au moment exact de leur ajout effectif au manifest. `pre.002` a ajouté `tracing` dans la génération `^0.1`, `pre.003` a ajouté `tracing-subscriber` dans la génération `^0.3`, et `pre.004` revérifie puis ajoute `tracing-appender 0.2.5` dans la génération `^0.2`.
### `tracing`
@@ -155,7 +155,15 @@ tracing-appender = { version = "^0.2", default-features = false }
tracing-subscriber = { version = "^0.3", default-features = false, features = ["fmt"] }
```
La feature `fmt` apporte `registry` et `std`, nécessaires à la composition des layers, `Targets`, `reload` et au formatter console. `env-filter`, `ansi`, `tracing-log`, `json`, `time` et les autres features optionnelles ne sont pas activées. `tracing-appender` reste absent jusqu'à `pre.004`, où il sera réellement consommé.
La feature `fmt` apporte `registry` et `std`, nécessaires à la composition des layers, `Targets`, `reload` et aux formatters. `env-filter`, `ansi`, `tracing-log`, `json`, `time` et les autres features optionnelles ne sont pas activées.
`pre.004` revérifie `tracing-appender 0.2.5` et ajoute réellement :
```toml
tracing-appender = { version = "^0.2", default-features = false }
```
Aucune feature optionnelle n'est activée. Le `NonBlockingBuilder` reste explicitement en mode lossy afin que la saturation de sa queue n'applique pas de backpressure au hot path.
Après chaque ajout réel :
@@ -468,7 +476,7 @@ Objectifs :
Le mode de queue doit privilégier le non-blocage du caller : lorsque la queue est saturée, les lignes peuvent être abandonnées plutôt que d'appliquer une backpressure au hot path.
Le compteur `ErrorCounter` correspondant est conservé par le runtime afin que les pertes puissent être observées/inspectées ; l'API publique exacte de cette statistique sera fixée pendant l'implémentation.
Le compteur `ErrorCounter` correspondant est conservé par le runtime. `pre.004` stabilise l'observation publique via `LoggingGuard::dropped_lines() -> DroppedLines`, avec compteurs `console`, `file` et `total` cumulés pendant toute la durée de vie du guard, y compris à travers les hot reloads.
Le format initial est un format humain unique. Il doit inclure au minimum :
@@ -522,6 +530,8 @@ La taille de file reste celle du backend tant qu'un besoin réel ne justifie pas
La sortie fichier passe par un writer KSP de stripping ANSI avant persistence afin de supprimer les séquences de terminal déjà présentes dans les données écrites.
`pre.004` place ce writer **derrière** la queue `NonBlocking`, autour du `RollingFileAppender`. Le parsing/stripping et l'I/O disque s'exécutent donc sur le worker logging plutôt que dans le hot path du caller. Le stripper conserve son état entre plusieurs appels `Write` afin de gérer une séquence ANSI coupée entre deux buffers ; les séquences CSI ainsi que les séquences terminal de type OSC/string terminées par BEL/ST sont couvertes.
Cette responsabilité reste générique : `ksp-logging-lib` ne dépend pas de Tauri. Elle évite simplement que des séquences ANSI injectées par une couche d'application/framework se retrouvent persistées dans les fichiers.
Le stripping n'est pas présenté comme un mécanisme de redaction de données.
@@ -740,6 +750,7 @@ ksp_logging_lib::ConsoleSettings
ksp_logging_lib::FileRotation
ksp_logging_lib::FileSettings
ksp_logging_lib::LoggingSettings
ksp_logging_lib::DroppedLines
ksp_logging_lib::LoggingGuard
ksp_logging_lib::initialize
ksp_logging_lib::reinitialize
@@ -765,14 +776,16 @@ crates/ksp-logging-lib/
│ ├── macros.rs
│ ├── settings.rs
│ ├── span.rs
── runtime.rs
── runtime.rs
│ └── writer.rs
├── unit_tests/
│ ├── settings.rs
│ ├── span.rs
── runtime.rs
── runtime.rs
│ └── writer.rs
└── tests/
├── callsite.rs
├── reload.rs
├── runtime.rs
└── public_api.rs
```
@@ -947,16 +960,23 @@ Le runtime reloadable reste un `Vec<Box<dyn Layer<Registry>>>` placé derrière
### `0.1.2-pre.004` — non-blocking console/fichier + guards + ANSI + reload sinks
Objectifs :
Statut : implémenté, validations Cargo à exécuter.
- revérifier puis ajouter `tracing-appender` ;
- passer console et fichier sur writers non bloquants ;
- implémenter `FileSettings` et Never/Hourly/Daily ;
- utiliser le builder fallible du file appender ;
- conserver les `WorkerGuard` et `ErrorCounter` ;
- implémenter le stripping ANSI fichier ;
- permettre le remplacement à chaud des sinks/settings concernés ;
- tester flush/lifetime, saturation et erreurs de fichier.
Réalisé :
- `tracing-appender 0.2.5` ajouté via `^0.2`, sans feature optionnelle ;
- console stdout/stderr remplacée par `NonBlockingBuilder` en mode lossy ;
- fichier optionnel réellement activé avec `RollingFileAppender::builder()` fallible et rotations `Never/Hourly/Daily` ;
- console et fichier possèdent chacun leur `WorkerGuard` et leur `ErrorCounter` ;
- `LoggingGuard::dropped_lines()` expose un `DroppedLines` cumulatif pour console/fichier/total, sans perdre les compteurs des sinks retirés lors d'un reload ;
- formatter humain enrichi avec target, source file et line, ANSI du formatter désactivé ;
- stripping ANSI fichier effectué côté worker, avant persistence, avec état conservé entre buffers ;
- hot reload prépare les nouveaux writers/guards avant le swap, remplace les layers, mémorise les dropped lines des anciens sinks puis détruit leurs guards pour provoquer leur flush ;
- une erreur de construction du nouveau file appender retourne `logging.file_output_initialization_failed` et conserve la configuration précédente ;
- test d'intégration étendu pour couvrir fichier, erreur transactionnelle, flush lors du retrait du sink, takeover externe et stripping ANSI ;
- tests unitaires ajoutés pour rotations, runtime disabled/non bloquant, statistiques et stripper ANSI.
La saturation déterministe des queues, les reloads concurrents et l'audit complet des dépendances restent à renforcer dans `pre.005`.
### `0.1.2-pre.005` — intégration + concurrence + tests + audits
@@ -1031,7 +1051,7 @@ La release peut être stabilisée lorsque :
- les validations workspace et audits présents sont propres ;
- la documentation finale et le prompt `0.1.3` sont prêts.
## Questions ouvertes après `pre.003`
## Questions ouvertes après `pre.004`
Les deux questions d'API propres à `pre.002` sont résolues :
@@ -1042,8 +1062,8 @@ La composition de reload est désormais fixée pour cette release à un `Vec` de
Restent à confirmer par les prereleases suivantes sans remettre en cause ce contrat :
1. l'API publique exacte d'observation des dropped lines ;
2. le détail visuel exact du formatter humain, sans transformer sa ponctuation en contrat public ;
3. le comportement de flush/rotation et le swap transactionnel des `WorkerGuard` lorsque les sinks non bloquants seront introduits.
1. le détail visuel exact du formatter humain, sans transformer sa ponctuation en contrat public ;
2. la stratégie de test déterministe de saturation des queues avec writer injecté, sans exposer la taille de queue dans `LoggingSettings` ;
3. les mesures d'overhead et tests de concurrence/reload prévus pour `pre.005`.
La prochaine action après validation de `pre.003-fix.001` est `0.1.2-pre.004` : `tracing-appender`, console/fichier non bloquants, guards, rotation, stripping ANSI et reload des sinks.
La prochaine action après validation de `pre.004` est `0.1.2-pre.005` : intégration, concurrence, saturation déterministe, audits de façade/dépendances/features et mesure grossière de l'overhead de reload.