ConsoleLogObserver ShellObserver

Real-time console observer for command execution events

📋 Overview

ConsoleLogObserver is a concrete implementation of the ShellObserver abstract base class. It provides live feedback directly to the terminal by printing detailed information about command execution lifecycle events. This observer is ideal for CLI tools, automation scripts, or any application where operators need real-time visibility into what commands are being executed and their outcomes.

💡 Purpose: Displays in the console what is happening in real time — from command start to final result with success/failure indicators and timing details.

🏗️ Class Hierarchy & Definition

class ConsoleLogObserver(ShellObserver)

Inheritance: ConsoleLogObserver extends the abstract observer ShellObserver. It overrides two key lifecycle methods to provide console logging behavior.

🔰 Observer Methods Overridden

Method Trigger Description
on_command_start Before command execution Notifies that a command is about to run, displaying the full command line.
on_command_result After command finishes Processes the result: prints success with execution time or failure with return code and error details.

⚙️ Method Documentation

🔹 on_command_start(executable, final_args)

Description: Called immediately before a shell command is executed. Outputs a user-friendly message indicating which command is being run. The method reconstructs the full command string from the executable and its arguments.

📌 Parameters:
   • executable (str) – The executable name or path.
   • final_args (List[str]) – List of arguments passed to the executable.
📤 Returns: None
🖨️ Output example: 🛠️ Executing: git commit -m "initial commit"
🧠 Implementation note: Joins final_args with spaces and prepends the emoji "🛠️" for visual clarity.

🔹 on_command_result(result: CommandResult)

Description: Handles the command result after execution finishes. Distinguishes between success and failure cases, providing formatted output with timing or error information.

📌 Parameter:
   • result (CommandResult) – Object containing execution status, return code, execution time, standard error, and other metadata.
📤 Returns: None

✅ Success branch

If result.is_success() is True, prints: ✅ OK (X.XXXs) where X.XXX is the execution time in seconds (formatted to 3 decimal places).

❌ Failure branch

If the command fails, prints: ❌ FAIL (Code: {return_code}). Additionally, if result.standard_error contains any content, it prints the stripped error message on a new line indented with " Error: " prefix.

⏱️ Execution time: The execution_time attribute (float) represents the total duration of the command in seconds.

💻 Usage Example

Below is a practical demonstration of how ConsoleLogObserver integrates with a command executor. The observer subscribes to shell events and prints real-time logs to the console.

# Assume existence of a ShellRunner or Subject that notifies observers
from shell_observer import ShellObserver, CommandResult
from console_log_observer import ConsoleLogObserver

# Instantiate observer
observer = ConsoleLogObserver()

# Attach to a command executor (pseudocode)
executor.attach(observer)

# When executor runs a command like 'ls -la'
executor.run("ls", ["-la"])

# Console output would be:
# 🛠️  Executing: ls -la
# ✅ OK (0.023s)

# In case of error (e.g., command not found):
executor.run("invalid_cmd", [])

# Output:
# 🛠️  Executing: invalid_cmd
# ❌ FAIL (Code: 127)
#    Error: command not found: invalid_cmd
                
🔍 Note: The observer does not modify command execution — it only logs events. The CommandResult object must be provided by the shell execution engine.

🎯 Real-time Behavior & Console Output

The ConsoleLogObserver ensures that users are never left wondering about the progress of long-running or critical shell commands. Its behavior includes:

📊 Example Output Scenarios

Scenario Console Output
Successful command (echo "Hello") 🛠️ Executing: echo Hello
✅ OK (0.001s)
Failed command (missing file) 🛠️ Executing: cat missing.txt
❌ FAIL (Code: 1)
Error: cat: missing.txt: No such file or directory
Long-running process 🛠️ Executing: sleep 2
✅ OK (2.004s)
📌 Integration with ShellObserver Protocol
ConsoleLogObserver fulfills the observer contract by implementing required methods. It does not rely on any shared state, making it thread-safe for concurrent command executions (if the underlying executor supports it).

🔧 Technical Notes

Dependencies: This class expects a CommandResult object with at least the following attributes/methods:

Inherited from ShellObserver: The base class may define additional hooks (e.g., on_command_end), but ConsoleLogObserver only overrides the two methods relevant to its purpose. It can be extended further if needed.


✨ Design Philosophy: Minimal, non-intrusive logging. Each log entry is self-contained and uses common Unicode symbols for improved scannability. The observer does not raise exceptions and gracefully handles missing attributes (as per Python's duck typing).