Skip to content

feat(logging): add proper logging - #55

Draft
Arseni10Lk wants to merge 33 commits into
mainfrom
feature/logging
Draft

Arseni10Lk wants to merge 33 commits into
mainfrom
feature/logging

Conversation

@Arseni10Lk

@Arseni10Lk Arseni10Lk commented Sep 10, 2026

Copy link
Copy Markdown
Member

Resolves #19

Prior to this PR, solver analyses across YAADO_Core lacked a unified logging and output framework. Solvers relied on ad-hoc print() statements and frequently wrote temporary files (JSON results, CSV sweeps, and PNG plots) directly into module source directories (__file__.parent) or the repository root.

This PR introduces the FlightLogger subsystem and standardizes simulation persistence across YAADO. It ensures:

  • Clean isolation: Core solver code (YAADO_Core/) never writes outputs inside its own source tree. All run artifacts are segregated into timestamped directories under FlightLogs/{vehicle}/{analysis}_{timestamp}/.
  • First-class metadata discipline: Replaces brittle variable name suffix guessing with explicit physical unit metadata (units: dict[str, str]) on AnalysisResults.
  • Dual-role persistence: Generates human-friendly spreadsheets (summary.csv) alongside machine-readable simulation checkpoints (results.json) and auxiliary files (artifacts/).
  • Zero-overhead optimization mode: When enabled=False, all disk I/O, file logging, and plot rendering are skipped to avoid performance penalties in high-speed OpenMDAO evaluation loops.

Key Architectural Changes

A. Centralized Run Directory Structure

Each analysis run produces a dedicated, self-contained directory under FlightLogs/:

FlightLogs/{vehicle_name}/{analysis_name}_{YYYY-MM-DD_HHMM}/
├── execution.log        # Text diagnostics (info, debug, warnings, exceptions)
├── summary.csv          # Headline scalar metrics + run metadata (for Excel)
├── results.json         # Checkpoint container for load_results() and OpenMDAO
├── figures/             # Visual plots saved via save_figure()
└── artifacts/           # Multi-row sweeps, dense trajectories, mesh/CAD dumps

B. FlightLogger Core (YAADO_Core/Foundation/flight_logger.py)

  • Diagnostic Proxies: info(), warning(), error(), debug(), exception() logging to execution.log (with timestamped formatting) and optional console output. Handlers are safely cleaned up and detached in close() to prevent file descriptor leaks.
  • Robust JSON Serialization (YaadoJSONEncoder): Custom encoder supporting NumPy scalars (.item()), multi-element NumPy arrays (.tolist()), Enums, Pydantic models, Path objects, and datetimes.
  • Visual Persistence (save_figure):
    • Saves Matplotlib figures directly to figures/.
    • Conditional pop-ups governed by self.show_figures and show: enabling figure display shows only priority figures tagged with show=True.
    • Gracefully handles headless environments and closes figures by default (close=True) to prevent memory leaks.
  • Simulation Checkpointing (save_results & load_results):
    • save_results enforces results: AnalysisResults (rejecting unvalidated types with TypeError).
    • Serializes full data, explicit units, fidelity level, vehicle name, and metadata to results.json.
    • load_results reconstructs AnalysisResults and validates fidelity against FidelityLevel, failing loudly with ValueError on corrupted or missing fidelity rather than silently masking errors.
  • Human-Friendly 2-Table Summary (summary.csv):
    • Top Table (Row 1): metric,value,unit for primary scalar physics outputs. Placing this at Row 1 allows immediate auto-filtering, sorting, and graphing in Excel / LibreOffice Calc.
    • Bottom Table: Preceded by a blank line, an aligned metadata,value,unit table records checkpoint context (vehicle, analysis, timestamp, fidelity, iterations, converged, solver).
    • Filters out nested/complex metadata (which remains in results.json) to keep the spreadsheet lightweight and rectangular.
  • Auxiliary Artifact Storage (save_artifact):
    • Supports writing arbitrary text (str) or binary data (bytes) into artifacts/ (e.g. parametric sweeps, dense flight trajectories, mesh files, solver configuration scripts).

C. First-Class Units in AnalysisResults (YAADO_Core/Foundation/analysis_base.py)

  • Added explicit units: dict[str, str] = field(default_factory=dict) attribute.
  • Added get_unit(key) -> str: Returns the declared physical unit (e.g., "N", "m/s", "Pa"), defaulting cleanly to "-" when unannotated or dimensionless.
  • Added to_dict() -> dict[str, Any] for uniform serialization.
  • Removed brittle suffix-guessing (rpartition("_")), establishing a deterministic first-class metadata contract across the framework.

Verification & Testing

uv run pytest tests/ --tb=short

Test Coverage Summary:

  • Total Tests Passing: 183 passed (0 failures).
  • New Tests Added (test_flight_logger.py):
    1. test_first_class_units_in_analysis_results: Verifies explicit units and clean default fallback ("-") without guessing.
    2. test_flight_logger_directories_created: Confirms automatic directory creation (figures/, artifacts/, execution.log).
    3. test_diagnostic_logging: Verifies log format, log level filtering, and handler detachment.
    4. test_console_logging: Verifies optional console StreamHandler output.
    5. test_save_figure_basic_and_headless: Tests saving PNGs, closing figures, and headless environment handling.
    6. test_save_and_load_results_checkpoint: Validates end-to-end JSON roundtrip, 2-table summary.csv generation, and metadata extraction.
    7. test_yaado_json_encoder_numpy: Confirms safe serialization of NumPy scalars, arrays, Paths, Enums, and datetimes.
    8. test_save_artifact: Tests string and binary writing into artifacts/.
    9. test_disabled_logger_zero_overhead: Confirms zero disk I/O when enabled=False.
    10. test_save_results_rejects_dict_or_invalid_type: Asserts strict AnalysisResults type enforcement.
    11. test_load_results_rejects_missing_or_invalid_fidelity: Asserts loud ValueError on missing or corrupted fidelity integers.

PR Checklist Compliance and Remaining tasks

  • Ran uv run pytest tests/ --tb=short — all tests pass.
  • Updated architectural documentation in YAADO_Core/Foundation/README.md.
  • Update the TOML examples to match the new units format
  • Commit the test suite expansion
  • Integrate logging in at least one module method

Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
…ained

Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Signed-off-by: Arseni10Lk <arseniy230606@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement a centralized logging module to replace print()

1 participant