Files
khadhroony-solana-project/deltas/0.1.2/pre.003.md
2026-08-14 18:24:28 +02:00

306 lines
8.9 KiB
Markdown

<!-- file: deltas/0.1.2/pre.003.md -->
<!-- version: 1 -->
# Delta 0.1.2-pre.003
## Base requise
Livraison précédente validée :
```text
0.1.2-pre.002-fix.001
```
La base de développement validée porte :
```text
workspace.package.version = "0.1.2-pre.2.fix.1"
Cargo.toml header version = 28
```
Les validations remontées avant l'ouverture de cette tranche sont propres :
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test --workspace
```
## Objectif
Introduire le runtime subscriber de Logging sans encore ouvrir le backend fichier/non bloquant :
- ajouter `tracing-subscriber` avec la feature minimale `fmt` ;
- installer une seule fois le subscriber global KSP ;
- appliquer le takeover KSP et rendre silencieux les targets externes par défaut ;
- mapper `LogFilterLevel` vers `LevelFilter` ;
- appliquer un niveau KSP global puis les overrides par préfixe de target ;
- introduire une première couche console stdout/stderr ;
- intégrer les événements de lifecycle des spans `Off`, `NewAndClose` et `Full` ;
- introduire `LoggingGuard`, `initialize()` et `reinitialize()` ;
- permettre un démarrage sans sink puis une activation à chaud ;
- vérifier le hot reload sans second subscriber global.
La console reste volontairement synchrone dans cette tranche intermédiaire. `pre.004` la remplacera par un writer `tracing-appender` non bloquant et ajoutera fichier, guards, dropped-line counters et stripping ANSI avant toute stabilisation de `0.1.2`.
## Version Cargo
`workspace.package.version` passe de :
```text
0.1.2-pre.2.fix.1
```
à :
```text
0.1.2-pre.3
```
L'identifiant de livraison est :
```text
0.1.2-pre.003
```
Le header du `Cargo.toml` racine passe de version 28 à 29.
## Dépendance `tracing-subscriber`
L'audit du 2026-08-14 confirme `tracing-subscriber 0.3.23` dans la génération `^0.3`.
La dépendance est centralisée sous `[workspace.dependencies]` :
```toml
tracing-subscriber = { version = "^0.3", default-features = false, features = ["fmt"] }
```
`ksp-logging-lib` la consomme avec :
```toml
tracing-subscriber.workspace = true
```
La feature `fmt` fournit le formatter et entraîne les capacités `registry`/`std` nécessaires à la composition retenue. Ne sont pas activés par anticipation :
- `env-filter` ;
- `ansi` ;
- `tracing-log` ;
- `json` ;
- `time` ;
- `chrono` ;
- `parking_lot`.
`tracing-appender` reste absent jusqu'à `pre.004`.
## Takeover et filtering
Le runtime utilise `tracing_subscriber::filter::Targets`.
La construction est conceptuellement :
```text
default unmatched targets = OFF
ksp-* = LoggingSettings.default_filter
target overrides = TargetFilter entries
```
Conséquences :
- un événement `sqlx`, `hyper`, `rustls` ou autre target externe reste silencieux même à `ERROR` tant qu'aucune couche KSP ne le réémet explicitement ;
- les crates KSP utilisent leur nom Cargo comme target ;
- `ksp-logging-lib`, `ksp-store-lib`, etc. suivent le niveau global KSP ;
- un `TargetFilter` plus spécifique peut relever ou abaisser le niveau d'une crate KSP donnée ;
- aucune chaîne `RUST_LOG` ou `EnvFilter` n'est introduite.
## Console initiale
`ConsoleSettings::stdout()` et `ConsoleSettings::stderr()` construisent une couche `fmt` avec :
- target affiché ;
- ANSI explicitement désactivé ;
- lifecycle de span selon `SpanEvents` ;
- filtering KSP `Targets`.
Cette couche utilise encore directement `std::io::stdout` / `std::io::stderr`. Ce writer synchrone est uniquement la fondation de `pre.003`; il n'est pas le contrat final de la release.
## Spans runtime
Le mapping retenu est :
```text
SpanEvents::Off -> FmtSpan::NONE
SpanEvents::NewAndClose -> FmtSpan::NEW | FmtSpan::CLOSE
SpanEvents::Full -> FmtSpan::FULL
```
`NewAndClose` active ainsi la surface nécessaire aux diagnostics de début/fin et de temps busy/idle fournis par le formatter sans obliger les consumers à utiliser directement `tracing-subscriber`.
## Subscriber global
La nouvelle API publique est :
```text
ksp_logging_lib::LoggingGuard
ksp_logging_lib::initialize(&LoggingSettings) -> Result<LoggingGuard>
ksp_logging_lib::reinitialize(&mut LoggingGuard, &LoggingSettings) -> Result<()>
```
`initialize()` :
1. valide/prépare les layers ;
2. crée une unique infrastructure `reload::Layer` ;
3. installe le subscriber global avec l'API fallible `tracing::subscriber::set_global_default` ;
4. retourne un `LoggingGuard` possédant le handle de reload et les settings actifs.
Une seconde installation globale retourne :
```text
logging.already_initialized
```
La cause `SetGlobalDefaultError` est conservée comme `source` Core.
## Hot reload
La composition interne retenue est :
```text
Registry
-> reload::Layer
-> Vec<Box<dyn Layer<Registry> + Send + Sync>>
```
Le `Vec` peut être vide. Cela permet :
```text
initialize(no sink)
-> subscriber global installé mais silencieux
reinitialize(console enabled)
-> console activée sans second subscriber global
```
Le choix d'un `Vec` de layers boxed prépare directement `pre.004`, qui pourra ajouter ou retirer console/fichier sans changer la surface publique de reload.
`reinitialize()` prépare d'abord complètement la nouvelle représentation. Une erreur de validation/préparation retourne avant le swap et conserve :
- les settings actifs du `LoggingGuard` ;
- les layers actuellement installés ;
- le comportement de filtering en cours.
Une erreur effective du handle `reload` retourne :
```text
logging.reload_failed
```
et conserve sa cause externe via le contrat `source` Core.
## File settings pendant `pre.003`
`FileSettings` reste dans la surface publique définie par `pre.002`, mais le backend fichier n'est pas encore construit dans cette tranche.
`initialize()` / `reinitialize()` refusent donc temporairement une configuration avec `file = Some(...)` avec `logging.invalid_settings` et contexte `field = file` au lieu d'ignorer silencieusement la demande.
Cette restriction transitoire disparaîtra lorsque le backend fichier réel sera introduit en `pre.004`.
## Erreurs ajoutées
```text
logging.already_initialized
logging.reload_failed
```
Elles s'ajoutent à :
```text
logging.invalid_settings
```
Aucune connaissance Logging n'est ajoutée à Core.
## Tests ajoutés
### Unitaires runtime
- mapping complet des niveaux KSP ;
- silence des targets externes ;
- default KSP `Info` ;
- override `ksp-logging-lib = Trace` ;
- mapping des événements de span ;
- rejet temporaire du backend fichier avant `pre.004`.
### Intégration runtime global
Un seul test global dans sa crate de test dédiée vérifie :
1. `initialize()` avec aucun sink ;
2. absence d'admission des callsites tant que Logging est désactivé ;
3. `reinitialize()` avec console active ;
4. activation `Trace` de `ksp-logging-lib` par override ;
5. maintien de `ksp-store-lib` à `Info` ;
6. maintien de `sqlx` à `Off` même pour `Error` ;
7. échec d'un reload demandant le backend fichier non encore disponible ;
8. conservation des anciens settings/filtering après cet échec ;
9. refus d'un deuxième `initialize()`.
Le changement de filtering est observé via des fonctions contenant des callsites `tracing::enabled!` stables, afin de vérifier que le reload invalide correctement l'intérêt mis en cache.
## Fichiers ajoutés
- `crates/ksp-logging-lib/src/runtime.rs`
- `crates/ksp-logging-lib/unit_tests/runtime.rs`
- `crates/ksp-logging-lib/tests/runtime.rs`
- `deltas/0.1.2/pre.003.md`
## Fichiers modifiés
- `Cargo.toml`
- `crates/ksp-logging-lib/Cargo.toml`
- `crates/ksp-logging-lib/src/error.rs`
- `crates/ksp-logging-lib/src/lib.rs`
- `crates/ksp-logging-lib/tests/public_api.rs`
- `docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md`
## Fichiers supprimés
Aucun.
## Validations exécutées pendant la préparation
- revérification documentaire de `tracing-subscriber 0.3.23` et de ses features ;
- contrôle TOML des manifests ;
- contrôle des headers `file:` / `version:` ;
- contrôle de la centralisation de `tracing-subscriber` sous `[workspace.dependencies]` ;
- contrôle que `tracing-appender` reste absent ;
- contrôle que le code production ajouté n'utilise ni `unwrap`, ni `expect`, ni `panic`, ni opérateur `?`, ni `unsafe` ;
- contrôle que les usages directs de la stack tracing restent dans `ksp-logging-lib` ;
- contrôle du contenu du delta contre la base reconstruite `0.1.2-pre.2.fix.1`.
## Validations à exécuter dans le workspace
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test --workspace
cargo tree -p ksp-logging-lib
cargo tree -p ksp-logging-lib -d
cargo tree -p ksp-logging-lib -e features
```
Aucune validation Cargo non exécutable dans l'environnement de préparation n'est déclarée réussie.
## Suite
Après validation de `pre.003`, passer à `0.1.2-pre.004` :
- `tracing-appender` ;
- console non bloquante ;
- fichier Never/Hourly/Daily ;
- `WorkerGuard` / `ErrorCounter` ;
- stripping ANSI fichier ;
- hot reload des sinks non bloquants et de leurs guards.