Skip to content

Add formalized diagnostic tracing system#84

Merged
Aaronontheweb merged 4 commits intodevfrom
feature/diagnostic-logging
Dec 17, 2025
Merged

Add formalized diagnostic tracing system#84
Aaronontheweb merged 4 commits intodevfrom
feature/diagnostic-logging

Conversation

@Aaronontheweb
Copy link
Owner

@Aaronontheweb Aaronontheweb commented Dec 17, 2025

Summary

Closes #72

Implements a lightweight, zero-cost-when-disabled tracing system for debugging Termina TUI applications.

Key Features

  • Custom abstraction over M.E.Logging - No direct dependency required
  • Deferred string formatting - TraceEvent struct captures template + args, formats only when needed
  • Lock-free file output - Uses Channel with single reader pattern to avoid blocking UI thread
  • Category-based filtering - Focus, Layout, Input, Page, Reactive, Render, Platform
  • Level-based filtering - Trace, Debug, Info, Warning, Error
  • MEL integration - Optional LoggerTraceListener adapter
  • DI extension methods - AddTerminaFileTracing, AddTerminaLoggerTracing

Default Behavior

Tracing is completely disabled by default. When no listener is configured:

  • All trace calls are no-ops (single inlined boolean check)
  • No string formatting occurs
  • No memory allocations occur
  • No TraceEvent structs are created

Enabling Tracing

// 1. File tracing - lock-free channel design
services.AddTerminaFileTracing("termina-trace.log");

// 2. With category and level filtering
services.AddTerminaFileTracing(
    "termina-trace.log",
    TerminaTraceCategory.Focus | TerminaTraceCategory.Input,
    TerminaTraceLevel.Debug);

// 3. M.E.Logging integration
services.AddLogging(builder => builder.AddConsole())
        .AddTerminaLoggerTracing();

// 4. Stderr output (debugging without file I/O)
TerminaTrace.Configure(
    FileTraceListener.CreateStdErr(),
    TerminaTraceCategory.All,
    TerminaTraceLevel.Debug);

Output Format

2024-01-15 10:30:45.123 [DEBUG] [Focus] FocusManager#12345678 - PushFocus: TextInputNode, stack depth=1
2024-01-15 10:30:45.125 [TRACE] [Input] TextInputNode#87654321 - HandleInput: key=A, char='A'

Architecture Decisions (per user requirements)

  • TraceEvent struct - Captures timestamp, level, category, source at creation; formats only when listener needs it
  • Lock-free FileTraceListener - Unbounded channel with TryWrite (non-blocking), background task consumes
  • Zero allocation when disabled - Template args stored in struct, string.Format only called when logging

Components with Tracing

  • FocusManager - Focus push/pop/route operations
  • TerminaApplication - Input processing, navigation, lifecycle
  • TextInputNode - Focus events, key handling

Benchmark Results

Benchmarks confirm zero-cost-when-disabled design goal:

Disabled (No Listener) - Zero overhead

Method Mean Allocated
Disabled_NoArgs ~1 ns 0 B
Disabled_OneArg ~1 ns 0 B
Disabled_TwoArgs ~1 ns 0 B
Disabled_ThreeArgs ~1 ns 0 B

Enabled with Null Listener (TraceEvent creation only)

Method Mean Allocated
NullListener_NoArgs ~29 ns 0 B
NullListener_OneArg ~32 ns 24 B
NullListener_TwoArgs ~32 ns 24 B
NullListener_ThreeArgs ~37 ns 48 B

Enabled with Formatting (full cost)

Method Mean Allocated
Formatting_NoArgs ~64 ns 80 B
Formatting_OneArg ~78 ns 104 B
Formatting_TwoArgs ~87 ns 104 B
Formatting_ThreeArgs ~110 ns 128 B

Key takeaway: When disabled, tracing has <1ns overhead and zero allocations - the check is a single inlined boolean test.

Demo App Integration

The Termina.Demo app now includes file tracing:

  • Logs go to %TEMP%/termina-logs/trace-{timestamp}.log
  • Trace file path displayed in status bar
  • README added with usage instructions for interactive and headless modes
# Interactive
dotnet run --project demos/Termina.Demo

# Headless/CI mode
dotnet run --project demos/Termina.Demo -- --test

Documentation

Added comprehensive documentation at docs/advanced/diagnostics.md covering:

  • Default behavior and enabling tracing
  • Category and level filtering
  • Output format
  • Adding traces to custom code
  • Custom listener implementation
  • Performance characteristics
  • Best practices

Test plan

  • Build passes
  • All 635 tests pass
  • Benchmark project builds
  • Run benchmarks - verified zero allocations when disabled
  • Test file tracing with demo app
  • Documentation added
  • Test MEL integration

Implement a lightweight, zero-cost-when-disabled tracing system for
debugging Termina TUI applications.

Key features:
- Custom abstraction over M.E.Logging (no direct dependency required)
- Deferred string formatting via TraceEvent struct with template + args
- Lock-free file output using Channel with single reader pattern
- Category-based filtering (Focus, Layout, Input, Page, Render, etc.)
- Level-based filtering (Trace, Debug, Info, Warning, Error)
- Optional MEL integration via LoggerTraceListener adapter
- DI extension methods for easy configuration

Architecture decisions per user requirements:
- TraceEvent captures timestamp, level, category, source at creation
- FormatMessage() only called when listener needs the string
- FileTraceListener uses unbounded channel with TryWrite (non-blocking)
- Background task consumes channel and writes to file
- Zero allocation overhead when tracing disabled

Added trace calls to:
- FocusManager (focus push/pop/route operations)
- TerminaApplication (input processing, navigation, lifecycle)
- TextInputNode (focus events, key handling)
@Aaronontheweb Aaronontheweb marked this pull request as draft December 17, 2025 19:01
Add BenchmarkDotNet project to measure tracing system performance:

- TracingDisabledBenchmarks: Measures overhead when tracing is disabled
  (should show zero allocations and minimal CPU)
- TracingEnabledNullListenerBenchmarks: Measures TraceEvent creation overhead
- TracingEnabledFormattingBenchmarks: Measures full cost including string formatting

These benchmarks verify our zero-cost-when-disabled design goal.

Run with: dotnet run -c Release --project benchmarks/Termina.Benchmarks
- Add comprehensive diagnostics documentation (docs/advanced/diagnostics.md)
- Update advanced topics index with diagnostics link
- Integrate file tracing into Termina.Demo app
- Display trace log path in status bar on both Counter and Todo pages
- Add TraceFileInfo service for DI-based path sharing
- Add README for demo app with usage instructions

Trace logs are written to %TEMP%/termina-logs/ with timestamped filenames.
@Aaronontheweb Aaronontheweb marked this pull request as ready for review December 17, 2025 19:39
@Aaronontheweb Aaronontheweb merged commit b89c186 into dev Dec 17, 2025
7 checks passed
@Aaronontheweb Aaronontheweb deleted the feature/diagnostic-logging branch December 17, 2025 19:43
@Aaronontheweb Aaronontheweb mentioned this pull request Dec 18, 2025
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.

Add Formalized Trace Logging System with Microsoft.Extensions.Logging Support

1 participant