From 697527675a9861ddd405c78248f50f8ba081b688 Mon Sep 17 00:00:00 2001 From: SinuS Von SifriduS Date: Fri, 14 Aug 2026 18:10:38 +0200 Subject: [PATCH] v0.1.2-pre.002-fix --- Cargo.toml | 4 +- crates/ksp-logging-lib/src/settings.rs | 16 +-- crates/ksp-logging-lib/src/span.rs | 5 +- crates/ksp-logging-lib/tests/callsite.rs | 14 +- crates/ksp-logging-lib/tests/public_api.rs | 4 +- deltas/0.1.2/pre.002-fix.001.md | 125 ++++++++++++++++++ .../004-V0_1_2_LOGGING_FOUNDATION_PLAN.md | 5 +- 7 files changed, 153 insertions(+), 20 deletions(-) create mode 100644 deltas/0.1.2/pre.002-fix.001.md diff --git a/Cargo.toml b/Cargo.toml index a70fb24..4fc3aa7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 27 +# version: 28 [workspace] resolver = "3" members = ["crates/ksp-core-lib", "crates/ksp-logging-lib"] [workspace.package] -version = "0.1.2-pre.2" +version = "0.1.2-pre.2.fix.1" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/crates/ksp-logging-lib/src/settings.rs b/crates/ksp-logging-lib/src/settings.rs index 91154a0..e7db7af 100644 --- a/crates/ksp-logging-lib/src/settings.rs +++ b/crates/ksp-logging-lib/src/settings.rs @@ -1,5 +1,5 @@ // file: crates/ksp-logging-lib/src/settings.rs -// version: 1 +// version: 2 /// Runtime filter level used by KSP logging settings. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] @@ -216,13 +216,13 @@ impl LoggingSettings { ); } } - if let std::option::Option::Some(file) = self.file.as_ref() { - if file.file_name_prefix().is_empty() { - return std::result::Result::Err( - ksp_core_lib::Error::new(crate::ERROR_CODE_INVALID_SETTINGS, "file name prefix must not be empty") - .with_context("field", "file.file_name_prefix"), - ); - } + if let std::option::Option::Some(file) = self.file.as_ref() + && file.file_name_prefix().is_empty() + { + return std::result::Result::Err( + ksp_core_lib::Error::new(crate::ERROR_CODE_INVALID_SETTINGS, "file name prefix must not be empty") + .with_context("field", "file.file_name_prefix"), + ); } return std::result::Result::Ok(()); } diff --git a/crates/ksp-logging-lib/src/span.rs b/crates/ksp-logging-lib/src/span.rs index acedae2..c82f69c 100644 --- a/crates/ksp-logging-lib/src/span.rs +++ b/crates/ksp-logging-lib/src/span.rs @@ -1,5 +1,5 @@ // file: crates/ksp-logging-lib/src/span.rs -// version: 1 +// version: 2 /// KSP-owned handle to a tracing span. #[derive(Clone, Debug)] @@ -28,8 +28,7 @@ impl Span { /// Instruments an asynchronous future with a KSP span. /// -/// The span is entered whenever the future is polled and exited whenever it yields, so no enter guard is held across an `.await` point. -#[must_use] +/// The span is entered whenever the future is polled or dropped and exited when that operation returns, so no enter guard is held across an `.await` point. pub fn instrument(span: crate::Span, future: F) -> impl std::future::Future where F: std::future::Future, diff --git a/crates/ksp-logging-lib/tests/callsite.rs b/crates/ksp-logging-lib/tests/callsite.rs index 5b2a46e..7d7f51a 100644 --- a/crates/ksp-logging-lib/tests/callsite.rs +++ b/crates/ksp-logging-lib/tests/callsite.rs @@ -1,5 +1,7 @@ // file: crates/ksp-logging-lib/tests/callsite.rs -// version: 1 +// version: 2 + +//! Integration tests for KSP logging callsite and async span instrumentation behavior. const TEST_TARGET: &str = "ksp-logging-lib"; @@ -137,7 +139,7 @@ fn span_macro_preserves_consumer_callsite() { } #[test] -fn async_instrumentation_enters_and_exits_span_during_poll() { +fn async_instrumentation_enters_and_exits_span_during_poll_and_drop() { let captured = std::sync::Arc::new(std::sync::Mutex::new(std::vec::Vec::new())); let enters = std::sync::Arc::new(std::sync::atomic::AtomicU64::new(0)); let exits = std::sync::Arc::new(std::sync::atomic::AtomicU64::new(0)); @@ -150,8 +152,12 @@ fn async_instrumentation_enters_and_exits_span_during_poll() { let mut context = std::task::Context::from_waker(waker); let poll = std::future::Future::poll(future.as_mut(), &mut context); assert_eq!(poll, std::task::Poll::Ready(42_u32)); + assert_eq!(enters.load(std::sync::atomic::Ordering::Relaxed), 1); + assert_eq!(exits.load(std::sync::atomic::Ordering::Relaxed), 1); + std::mem::drop(future); + assert_eq!(enters.load(std::sync::atomic::Ordering::Relaxed), 2); + assert_eq!(exits.load(std::sync::atomic::Ordering::Relaxed), 2); return; }); - assert_eq!(enters.load(std::sync::atomic::Ordering::Relaxed), 1); - assert_eq!(exits.load(std::sync::atomic::Ordering::Relaxed), 1); + assert_eq!(enters.load(std::sync::atomic::Ordering::Relaxed), exits.load(std::sync::atomic::Ordering::Relaxed)); } diff --git a/crates/ksp-logging-lib/tests/public_api.rs b/crates/ksp-logging-lib/tests/public_api.rs index 53ead1e..4a0b270 100644 --- a/crates/ksp-logging-lib/tests/public_api.rs +++ b/crates/ksp-logging-lib/tests/public_api.rs @@ -1,5 +1,7 @@ // file: crates/ksp-logging-lib/tests/public_api.rs -// version: 1 +// version: 2 + +//! Integration tests for the public crate-root surface of `ksp-logging-lib`. const TEST_TARGET: &str = "ksp-logging-lib"; diff --git a/deltas/0.1.2/pre.002-fix.001.md b/deltas/0.1.2/pre.002-fix.001.md new file mode 100644 index 0000000..99d5d71 --- /dev/null +++ b/deltas/0.1.2/pre.002-fix.001.md @@ -0,0 +1,125 @@ + + + +# Delta 0.1.2-pre.002-fix.001 + +## Base requise + +Livraison précédente : + +```text +0.1.2-pre.002 +``` + +Ce correctif traite uniquement les résultats de validation remontés après `pre.002`. Il ne modifie pas le périmètre fonctionnel de la prerelease et n'ouvre pas `pre.003`. + +## Résultats de validation à corriger + +Les commandes exécutées sur le workspace de développement ont montré : + +- `cargo fmt --all` : exécuté sans erreur ; +- `cargo check --workspace` : réussi ; +- `cargo clippy --workspace --all-targets` : terminé avec quatre catégories de warnings à nettoyer dans Logging/tests ; +- `cargo test --workspace` : tous les tests Core et les tests unitaires Logging réussissent, mais `async_instrumentation_enters_and_exits_span_during_poll` échoue avec `enters = 2` au lieu de l'attente `1`. + +## Cause du test async + +Le test `pre.002` supposait qu'une future instrumentée n'entrait dans son span que pendant son unique `poll`. + +Le contrat de `tracing::Instrument` est plus précis : la future instrumentée entre dans le span lors de chaque `poll` **et lors de son `Drop`**. Pour `std::future::ready(42_u32)`, le test observe donc : + +```text +poll -> enter + exit +Drop -> enter + exit +``` + +Le compteur final `2` est donc conforme au comportement de `tracing`; c'est l'attente du test qui était incorrecte. + +Le test corrigé vérifie séparément : + +1. une paire `enter` / `exit` immédiatement après le `poll` ; +2. une deuxième paire après destruction explicite de la future instrumentée ; +3. l'équilibre final entre le nombre d'entrées et de sorties. + +Le plan actif documente désormais explicitement cette sémantique afin qu'un futur test async ne réintroduise pas l'hypothèse erronée d'une seule paire `enter` / `exit` sur toute la durée de vie d'une future. + +## Nettoyage Clippy + +### `collapsible_if` + +La validation du préfixe de fichier utilise désormais un `if let` avec condition chaînée compatible Rust 2024 au lieu de deux `if` imbriqués. + +### `double_must_use` + +L'attribut `#[must_use]` explicite de `ksp_logging_lib::instrument(...)` est supprimé : la fonction retourne déjà un type `Future`, lui-même marqué `must_use` par son contrat standard. + +## Documentation des tests d'intégration + +Les crates de tests d'intégration : + +```text +crates/ksp-logging-lib/tests/callsite.rs +crates/ksp-logging-lib/tests/public_api.rs +``` + +reçoivent chacune une documentation crate-root `//! ...` afin de satisfaire `missing_docs = "warn"` lorsque les tests sont compilés comme crates séparées. + +## Version Cargo + +La version reste : + +```text +0.1.2-pre.2 +``` + +Aucune dépendance et aucun manifest ne sont modifiés. + +L'identifiant de livraison de ce correctif est : + +```text +0.1.2-pre.002-fix.001 +``` + +## Fichiers modifiés + +- `crates/ksp-logging-lib/src/settings.rs` +- `crates/ksp-logging-lib/src/span.rs` +- `crates/ksp-logging-lib/tests/callsite.rs` +- `crates/ksp-logging-lib/tests/public_api.rs` +- `docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md` + +## Fichier ajouté + +- `deltas/0.1.2/pre.002-fix.001.md` + +## Validations statiques exécutées lors de la préparation + +- contrôle des headers `file:` / `version:` des fichiers du correctif ; +- contrôle que `Cargo.toml` n'est pas inclus dans le delta ; +- contrôle que la version Cargo de la base reste `0.1.2-pre.2` ; +- contrôle de l'absence de nouvelle dépendance ; +- contrôle que le correctif ne contient aucun ajout `unwrap`, `expect`, `panic` ou opérateur `?` dans le code production modifié ; +- contrôle que l'archive contient uniquement les cinq fichiers modifiés et le nouveau delta. + +## Validations à réexécuter sur le workspace + +```bash +cargo fmt --all +cargo check --workspace +cargo test --workspace +cargo clippy --workspace --all-targets +``` + +Puis, pour compléter les validations prévues pour `pre.002` si elles ne l'ont pas encore été : + +```bash +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 par ce delta. + +## Suite + +Une fois ce correctif validé, `0.1.2-pre.002` peut être considérée propre et la session peut passer à `0.1.2-pre.003` pour le subscriber runtime, le takeover, le filtering, la console non bloquante et la fondation du hot reload. diff --git a/docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md b/docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md index cc358f8..6c61f74 100644 --- a/docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md +++ b/docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md @@ -1,5 +1,5 @@ - + # Plan KSP 0.1.2 — Logging foundation @@ -223,7 +223,7 @@ La façade ne doit pas obliger les consumers à importer `tracing::Span` ou `tra Pour le code synchrone, la surface doit permettre d'associer un scope d'exécution au span sans déplacer le callsite. -Pour le code async, la surface doit instrumenter la `Future` elle-même. Un guard issu de `Span::enter()` ne doit pas être maintenu à travers un `.await`, car cela produit des traces incorrectes lorsque l'exécution change de tâche/thread ou que la future yield. +Pour le code async, la surface doit instrumenter la `Future` elle-même. Un guard issu de `Span::enter()` ne doit pas être maintenu à travers un `.await`, car cela produit des traces incorrectes lorsque l'exécution change de tâche/thread ou que la future yield. La primitive `tracing::Instrument` entre dans le span à chaque `poll` **et lors du `Drop`** de la future instrumentée ; les tests KSP doivent donc distinguer explicitement ces deux opérations au lieu de supposer une seule paire `enter`/`exit` sur toute la durée de vie de la future. ### Mesure de durée @@ -791,6 +791,7 @@ Cette arborescence reste ajustable si une séparation plus petite suffit. Aucun - target explicite conservé ; - scope synchrone correctement associé au span ; - future async instrumentée par la façade KSP ; +- entrée/sortie du span vérifiée pendant chaque `poll` pertinent et lors du `Drop` de la future instrumentée ; - aucun enter guard conservé à travers `.await` dans l'API recommandée ; - `SpanEvents::NewAndClose` produit les événements lifecycle attendus ; - `CLOSE` contient les temps `busy`/`idle` lorsque les timestamps sont actifs ;