Skip to content

Add FormatterOverride trait for alternative output formats (JSON, structured logs)#134

Merged
josecelano merged 3 commits into
mainfrom
copilot/add-formatter-override-support
Nov 4, 2025
Merged

Add FormatterOverride trait for alternative output formats (JSON, structured logs)#134
josecelano merged 3 commits into
mainfrom
copilot/add-formatter-override-support

Conversation

Copilot AI commented Nov 4, 2025

Copy link
Copy Markdown
Contributor

Adds optional post-processing of formatted messages to enable machine-readable outputs (JSON, structured logs, ANSI colors) without modifying individual message types. Extends the trait-based architecture (issue #102) while preserving theme-based formatting as the primary mechanism.

Changes

Core trait and integration:

  • Added FormatterOverride trait for transforming already-formatted messages
  • Extended OutputMessage trait with type_name() method for metadata extraction
  • Added optional formatter_override field to UserOutput (defaults to None for backward compatibility)
  • Updated write() to apply override after theme formatting when present

Example implementation:

  • Implemented JsonFormatter producing JSON with type, channel, content, and ISO 8601 timestamp
  • Added constructors: with_formatter_override() and with_theme_and_formatter()

Testing:

  • Added 11 unit tests covering override application, JSON structure, theme preservation, verbosity filtering, and backward compatibility

Usage

use torrust_tracker_deployer_lib::presentation::user_output::{
    UserOutput, VerbosityLevel, JsonFormatter
};

// Standard emoji theme output (unchanged)
let mut output = UserOutput::new(VerbosityLevel::Normal);
output.progress("Processing");
// stderr: ⏳ Processing

// JSON output with metadata
let mut json_output = UserOutput::with_formatter_override(
    VerbosityLevel::Normal,
    Box::new(JsonFormatter),
);
json_output.progress("Processing");
// stderr: {"type":"ProgressMessage","channel":"Stderr","content":"⏳ Processing","timestamp":"2025-11-04T12:34:56Z"}

Notes

  • Formatter override transforms post-theme formatting (composition: theme → message → override)
  • Existing code unaffected - all constructors default formatter_override to None
  • Use themes for symbol changes, override for structural transformations

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 192.0.2.1
    • Triggering command: ssh -i /nonexistent/key -p 22 -o StrictHostKeyChecking=no -o ConnectTimeout=5 -o UserKnownHostsFile=/dev/null testuser@192.0.2.1 echo 'SSH connected' (packet block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Add Formatter Override Support for Alternative Output Formats</issue_title>
<issue_description>## Overview

Add optional FormatterOverride trait support to enable alternative output formats (JSON, structured logs, colored output) without modifying individual message types. This enhancement preserves the trait-based message design (Proposal 3) while allowing format transformation for machine-readable outputs.

Note: This is an optional enhancement that builds on the existing trait-based design. The current implementation using Theme and OutputMessage trait already provides good separation and flexibility. This proposal is only needed if we require format overrides beyond what themes provide (e.g., JSON output, ANSI color codes, structured logging).

Specification

See detailed specification: docs/issues/133-add-formatter-override-support.md

🏗️ Architecture Requirements

DDD Layer: Presentation
Module Path: src/presentation/user_output.rs
Pattern: Trait-based Extension (Strategy Pattern)

Key Requirements

  • Must not break existing OutputMessage trait design
  • Must preserve theme-based formatting as primary mechanism
  • Override should be optional (Option<Box<dyn FormatterOverride>>)
  • Maintain backward compatibility with existing code

Implementation Plan

Phase 1: Core Trait and Integration (2-3 hours)

  • Define FormatterOverride trait with comprehensive documentation
  • Add formatter_override field to UserOutput
  • Update write() method to apply override when present
  • Add new constructors for formatter override support

Phase 2: Example Implementation (1-2 hours)

  • Implement JsonFormatter with FormatterOverride trait
  • Add helper function to extract clean type name

Phase 3: Testing (2-3 hours)

  • Add unit tests for FormatterOverride trait behavior
  • Test JsonFormatter output structure
  • Verify backward compatibility

Phase 4: Documentation (1 hour)

  • Document when to use formatter override vs. themes
  • Add examples to module documentation

Acceptance Criteria

Quality Checks:

  • Pre-commit checks pass: ./scripts/pre-commit.sh

Task-Specific Criteria:

  • FormatterOverride trait is properly documented
  • JsonFormatter produces valid JSON with all required fields
  • All existing constructors remain unchanged and working
  • Backward compatibility maintained
  • Comprehensive unit tests added

Related

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits November 4, 2025 11:15
…tion

Co-authored-by: josecelano <58816+josecelano@users.noreply.github.com>
Co-authored-by: josecelano <58816+josecelano@users.noreply.github.com>
Copilot AI changed the title [WIP] Add formatter override support for alternative output formats Add FormatterOverride trait for alternative output formats (JSON, structured logs) Nov 4, 2025
Copilot AI requested a review from josecelano November 4, 2025 11:44
@josecelano josecelano marked this pull request as ready for review November 4, 2025 13:04

@josecelano josecelano left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 2ead405

@josecelano josecelano merged commit 9e08c7b into main Nov 4, 2025
51 checks passed
@josecelano josecelano deleted the copilot/add-formatter-override-support branch April 15, 2026 16:37
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 Formatter Override Support for Alternative Output Formats

2 participants