273 lines
9.2 KiB
Markdown
273 lines
9.2 KiB
Markdown
# Story 9.6: Amélioration Logging Validation Énergie
|
|
|
|
Status: done
|
|
|
|
**Epic:** 9 - Coherence Corrections (Post-Audit)
|
|
**Priorité:** P2-IMPORTANTE
|
|
**Estimation:** 1h
|
|
**Dépendances:** Stories 9.3, 9.4, 9.5 (all done)
|
|
|
|
---
|
|
|
|
## Story
|
|
|
|
> En tant que développeur debuggant une simulation,
|
|
> Je veux un avertissement explicite quand des composants sont ignorés dans la validation énergétique,
|
|
> Afin d'identifier rapidement les implémentations manquantes.
|
|
|
|
---
|
|
|
|
## Contexte
|
|
|
|
L'audit de cohérence a révélé que `check_energy_balance()` utilise un logging de niveau DEBUG pour les composants skippés, ce qui les rend invisibles en configuration par défaut.
|
|
|
|
---
|
|
|
|
## Problème Actuel
|
|
|
|
```rust
|
|
// crates/solver/src/system.rs:1873-1879
|
|
_ => {
|
|
components_skipped += 1;
|
|
tracing::debug!( // ← Niveau DEBUG, pas WARNING
|
|
node_index = node_idx.index(),
|
|
"Component lacks full energy transfer or enthalpy data - skipping energy balance check"
|
|
);
|
|
}
|
|
```
|
|
|
|
**Conséquence** : Les développeurs ne sont pas avertis que certains composants sont ignorés dans la validation.
|
|
|
|
---
|
|
|
|
## Solution Proposée
|
|
|
|
### Changements
|
|
|
|
1. **Passer de DEBUG à WARN** pour les composants skippés
|
|
2. **Inclure le type du composant** dans le message
|
|
3. **Ajouter un résumé final** si des composants ont été skippés
|
|
|
|
### Implémentation
|
|
|
|
```rust
|
|
// crates/solver/src/system.rs
|
|
|
|
pub fn check_energy_balance(&self, state: &SystemState) -> Result<(), ValidationError> {
|
|
let mut total_heat_in = Power::from_watts(0.0);
|
|
let mut total_heat_out = Power::from_watts(0.0);
|
|
let mut total_work_in = Power::from_watts(0.0);
|
|
let mut total_work_out = Power::from_watts(0.0);
|
|
let mut components_validated = 0;
|
|
let mut components_skipped = 0;
|
|
let mut skipped_components: Vec<String> = Vec::new();
|
|
|
|
for node_idx in self.graph.node_indices() {
|
|
let component = &self.graph[node_idx];
|
|
|
|
let energy_transfers = component.energy_transfers(state);
|
|
let mass_flows = component.port_mass_flows(state);
|
|
let enthalpies = component.port_enthalpies(state);
|
|
|
|
match (energy_transfers, mass_flows, enthalpies) {
|
|
(Some((heat, work)), Ok(m_flows), Ok(h_flows)) if m_flows.len() == h_flows.len() => {
|
|
// ... existing validation logic ...
|
|
components_validated += 1;
|
|
}
|
|
_ => {
|
|
components_skipped += 1;
|
|
let component_info = format!(
|
|
"{} (type: {})",
|
|
component.name(),
|
|
std::any::type_name_of_val(component)
|
|
.split("::")
|
|
.last()
|
|
.unwrap_or("unknown")
|
|
);
|
|
skipped_components.push(component_info.clone());
|
|
|
|
tracing::warn!(
|
|
component = %component_info,
|
|
node_index = node_idx.index(),
|
|
"Component lacks energy_transfers() or port_enthalpies() - SKIPPED in energy balance validation"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Résumé final si des composants ont été skippés
|
|
if components_skipped > 0 {
|
|
tracing::warn!(
|
|
components_validated = components_validated,
|
|
components_skipped = components_skipped,
|
|
skipped = ?skipped_components,
|
|
"Energy balance validation incomplete: {} component(s) skipped. \
|
|
Implement energy_transfers() and port_enthalpies() for full validation.",
|
|
components_skipped
|
|
);
|
|
}
|
|
|
|
// ... rest of validation ...
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Fichiers à Modifier
|
|
|
|
| Fichier | Action |
|
|
|---------|--------|
|
|
| `crates/solver/src/system.rs` | Modifier `check_energy_balance()` |
|
|
|
|
---
|
|
|
|
## Critères d'Acceptation
|
|
|
|
- [x] Logging au niveau WARN (pas DEBUG)
|
|
- [x] Message inclut le nom et type du composant
|
|
- [x] Résumé final avec liste des composants skippés
|
|
- [x] Test que le warning est bien émis
|
|
|
|
---
|
|
|
|
## Tests Requis
|
|
|
|
```rust
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use tracing::subscriber;
|
|
use tracing_subscriber::layer::SubscriberExt;
|
|
|
|
#[test]
|
|
fn test_warn_emitted_for_skipped_component() {
|
|
// Setup tracing capture
|
|
let (layer, handle) = tracing_subscriber::layer::with_test_writer();
|
|
let _guard = subscriber::set_default(tracing_subscriber::registry().with(layer));
|
|
|
|
// Create system with component that lacks energy methods
|
|
let mut system = System::new();
|
|
// ... add component without energy_transfers() ...
|
|
|
|
let state = SystemState::default();
|
|
let _ = system.check_energy_balance(&state);
|
|
|
|
// Verify warning was emitted
|
|
let logs = handle.read();
|
|
assert!(logs.contains("SKIPPED in energy balance validation"));
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Exemple de Sortie
|
|
|
|
### Avant correction
|
|
|
|
```
|
|
DEBUG entropyk_solver::system: Component lacks full energy transfer or enthalpy data - skipping energy balance check node_index=2
|
|
```
|
|
|
|
### Après correction
|
|
|
|
```
|
|
WARN entropyk_solver::system: Component lacks energy_transfers() or port_enthalpies() - SKIPPED in energy balance validation component="EV-01 (type: ExpansionValve)" node_index=2
|
|
WARN entropyk_solver::system: Energy balance validation incomplete: 1 component(s) skipped. Implement energy_transfers() and port_enthalpies() for full validation. components_validated=4 components_skipped=1 skipped=["EV-01 (type: ExpansionValve)"]
|
|
```
|
|
|
|
---
|
|
|
|
## Dev Notes
|
|
|
|
### Architecture Patterns
|
|
|
|
- **Tracing crate**: The project uses `tracing` for structured logging with spans
|
|
- **Log levels**: DEBUG for detailed diagnostics, WARN for actionable issues
|
|
- **Pattern**: Use structured fields (`node_index = value`) for searchable logs
|
|
|
|
### Current Implementation Analysis
|
|
|
|
The current code at [`crates/solver/src/system.rs:1855-1861`](crates/solver/src/system.rs:1855):
|
|
|
|
```rust
|
|
_ => {
|
|
components_skipped += 1;
|
|
tracing::debug!(
|
|
node_index = node_idx.index(),
|
|
"Component lacks full energy transfer or enthalpy data - skipping energy balance check"
|
|
);
|
|
}
|
|
```
|
|
|
|
**Key observations:**
|
|
1. Uses `tracing::debug!` - invisible with default `RUST_LOG=info`
|
|
2. Missing component type information
|
|
3. No summary at the end of validation
|
|
|
|
### Implementation Notes
|
|
|
|
1. **Getting component type**: Use `std::any::type_name_of_val(component)` (stabilized in Rust 1.76)
|
|
2. **Component name**: Access via `component.name()` method from `Component` trait
|
|
3. **Tracking skipped components**: Add `Vec<String>` to collect skipped component info
|
|
|
|
### Dependencies Status
|
|
|
|
| Story | Status | Notes |
|
|
|-------|--------|-------|
|
|
| 9-3 ExpansionValve Energy Methods | done | `ExpansionValve` now has `energy_transfers()` |
|
|
| 9-4 RefrigerantSource/RefrigerantSink Energy Methods | review | Implementation complete, pending review |
|
|
| 9-5 FlowSplitter/FlowMerger Energy Methods | ready-for-dev | Depends on this story |
|
|
|
|
**Note**: This story can be implemented independently - it improves logging regardless of whether other components have complete energy methods.
|
|
|
|
### Testing Strategy
|
|
|
|
1. **Unit test**: Create a mock component without energy methods, verify warning is emitted
|
|
2. **Integration test**: Run `check_energy_balance()` on a system with mixed components
|
|
3. **Manual verification**: Run with `RUST_LOG=warn` and verify warnings appear
|
|
|
|
### Project Structure Notes
|
|
|
|
- File to modify: `crates/solver/src/system.rs`
|
|
- Function: `check_energy_balance(&self, state: &StateSlice)`
|
|
- Line range: ~1855-1861 (the `_ =>` match arm)
|
|
|
|
### References
|
|
|
|
- [Coherence Audit Report](./coherence-audit-remediation-plan.md)
|
|
- [Story 7-2 Energy Balance Validation](./7-2-energy-balance-validation.md)
|
|
- [Rust tracing crate docs](https://docs.rs/tracing/latest/tracing/)
|
|
- [std::any::type_name_of_val](https://doc.rust-lang.org/std/any/fn.type_name_of_val.html)
|
|
|
|
---
|
|
|
|
## Dev Agent Record
|
|
|
|
### Agent Model Used
|
|
|
|
z-ai/glm-5:free
|
|
|
|
### Debug Log References
|
|
|
|
- Build succeeded with `cargo build --package entropyk-solver`
|
|
- All tests passed with `cargo test --package entropyk-solver`
|
|
|
|
### Completion Notes List
|
|
|
|
- **Implementation**: Modified `check_energy_balance()` in `crates/solver/src/system.rs` to:
|
|
1. Use `tracing::warn!` instead of `tracing::debug!` for skipped components
|
|
2. Include component signature and type name in the warning message using `component.signature()` and `std::any::type_name_of_val()`
|
|
3. Track skipped components in a `Vec<String>` and emit a summary warning at the end if any components were skipped
|
|
- **Note**: Used `component.signature()` instead of `component.name()` because the `Component` trait doesn't have a `name()` method - `signature()` provides component identification information
|
|
- **Tests**: Added three unit tests with proper tracing capture using `tracing_subscriber`:
|
|
- `test_energy_balance_warns_for_skipped_components`: Verifies warning is emitted with "SKIPPED in energy balance validation"
|
|
- `test_energy_balance_includes_component_type_in_warning`: Verifies component type is included in warning
|
|
- `test_energy_balance_summary_warning`: Verifies summary warning with "Energy balance validation incomplete"
|
|
- **Code Review Fix**: Added `tracing-subscriber` to dev-dependencies for proper log capture in tests
|
|
- All acceptance criteria satisfied
|
|
|
|
### File List
|
|
|
|
- `crates/solver/src/system.rs` (modified)
|