v0.1.2-pre.002-fix
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
# file: Cargo.toml
|
# file: Cargo.toml
|
||||||
# version: 27
|
# version: 28
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["crates/ksp-core-lib", "crates/ksp-logging-lib"]
|
members = ["crates/ksp-core-lib", "crates/ksp-logging-lib"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.2-pre.2"
|
version = "0.1.2-pre.2.fix.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-logging-lib/src/settings.rs
|
// file: crates/ksp-logging-lib/src/settings.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
/// Runtime filter level used by KSP logging settings.
|
/// Runtime filter level used by KSP logging settings.
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[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 let std::option::Option::Some(file) = self.file.as_ref()
|
||||||
if file.file_name_prefix().is_empty() {
|
&& 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")
|
return std::result::Result::Err(
|
||||||
.with_context("field", "file.file_name_prefix"),
|
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(());
|
return std::result::Result::Ok(());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-logging-lib/src/span.rs
|
// file: crates/ksp-logging-lib/src/span.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
/// KSP-owned handle to a tracing span.
|
/// KSP-owned handle to a tracing span.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -28,8 +28,7 @@ impl Span {
|
|||||||
|
|
||||||
/// Instruments an asynchronous future with a KSP 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.
|
/// 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.
|
||||||
#[must_use]
|
|
||||||
pub fn instrument<F>(span: crate::Span, future: F) -> impl std::future::Future<Output = F::Output>
|
pub fn instrument<F>(span: crate::Span, future: F) -> impl std::future::Future<Output = F::Output>
|
||||||
where
|
where
|
||||||
F: std::future::Future,
|
F: std::future::Future,
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// file: crates/ksp-logging-lib/tests/callsite.rs
|
// 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";
|
const TEST_TARGET: &str = "ksp-logging-lib";
|
||||||
|
|
||||||
@@ -137,7 +139,7 @@ fn span_macro_preserves_consumer_callsite() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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 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 enters = std::sync::Arc::new(std::sync::atomic::AtomicU64::new(0));
|
||||||
let exits = 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 mut context = std::task::Context::from_waker(waker);
|
||||||
let poll = std::future::Future::poll(future.as_mut(), &mut context);
|
let poll = std::future::Future::poll(future.as_mut(), &mut context);
|
||||||
assert_eq!(poll, std::task::Poll::Ready(42_u32));
|
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;
|
return;
|
||||||
});
|
});
|
||||||
assert_eq!(enters.load(std::sync::atomic::Ordering::Relaxed), 1);
|
assert_eq!(enters.load(std::sync::atomic::Ordering::Relaxed), exits.load(std::sync::atomic::Ordering::Relaxed));
|
||||||
assert_eq!(exits.load(std::sync::atomic::Ordering::Relaxed), 1);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// file: crates/ksp-logging-lib/tests/public_api.rs
|
// 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";
|
const TEST_TARGET: &str = "ksp-logging-lib";
|
||||||
|
|
||||||
|
|||||||
125
deltas/0.1.2/pre.002-fix.001.md
Normal file
125
deltas/0.1.2/pre.002-fix.001.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
<!-- file: deltas/0.1.2/pre.002-fix.001.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# 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.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md -->
|
<!-- file: docs/plans/004-V0_1_2_LOGGING_FOUNDATION_PLAN.md -->
|
||||||
<!-- version: 3 -->
|
<!-- version: 4 -->
|
||||||
|
|
||||||
# Plan KSP 0.1.2 — Logging foundation
|
# 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 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
|
### Mesure de durée
|
||||||
|
|
||||||
@@ -791,6 +791,7 @@ Cette arborescence reste ajustable si une séparation plus petite suffit. Aucun
|
|||||||
- target explicite conservé ;
|
- target explicite conservé ;
|
||||||
- scope synchrone correctement associé au span ;
|
- scope synchrone correctement associé au span ;
|
||||||
- future async instrumentée par la façade KSP ;
|
- 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 ;
|
- aucun enter guard conservé à travers `.await` dans l'API recommandée ;
|
||||||
- `SpanEvents::NewAndClose` produit les événements lifecycle attendus ;
|
- `SpanEvents::NewAndClose` produit les événements lifecycle attendus ;
|
||||||
- `CLOSE` contient les temps `busy`/`idle` lorsque les timestamps sont actifs ;
|
- `CLOSE` contient les temps `busy`/`idle` lorsque les timestamps sont actifs ;
|
||||||
|
|||||||
Reference in New Issue
Block a user