44from collections .abc import Generator
55from datetime import datetime
66from pathlib import Path
7- from typing import Annotated , Any , Optional
7+ from typing import Annotated , Optional
88
99import typer
1010from httpx import HTTPError , HTTPStatusError , ReadTimeout
1111from pydantic import BaseModel , ValidationError
12+ from rich .markup import escape
1213from rich_toolkit import RichToolkit
1314
1415from fastapi_cloud_cli .utils .api import APIClient
@@ -43,32 +44,34 @@ def _stream_logs(
4344 since : str ,
4445 follow : bool ,
4546) -> Generator [str , None , None ]:
46- """Stream logs from the API."""
47- params : dict [str , Any ] = {
48- "tail" : tail ,
49- "since" : since ,
50- "follow" : follow ,
51- }
52-
5347 with APIClient () as client :
5448 timeout = 120 if follow else 30
5549 with client .stream (
5650 "GET" ,
5751 f"/apps/{ app_id } /logs/stream" ,
58- params = params ,
52+ params = {
53+ "tail" : tail ,
54+ "since" : since ,
55+ "follow" : follow ,
56+ },
5957 timeout = timeout ,
6058 ) as response :
6159 response .raise_for_status ()
60+
6261 yield from response .iter_lines ()
6362
6463
6564def _format_log_line (log : LogEntry ) -> str :
66- """Format a log entry for display with a colored indicator matching the UI. """
65+ """Format a log entry for display with a colored indicator"""
6766 timestamp_str = log .timestamp .strftime ("%Y-%m-%dT%H:%M:%S.%f" )[:- 3 ] + "Z"
6867 color = LOG_LEVEL_COLORS .get (log .level .lower ())
68+
69+ message = escape (log .message )
70+
6971 if color :
70- return f"[{ color } ]┃[/{ color } ] [dim]{ timestamp_str } [/dim] { log .message } "
71- return f"[dim]┃[/dim] [dim]{ timestamp_str } [/dim] { log .message } "
72+ return f"[{ color } ]┃[/{ color } ] [dim]{ timestamp_str } [/dim] { message } "
73+
74+ return f"[dim]┃[/dim] [dim]{ timestamp_str } [/dim] { message } "
7275
7376
7477def _process_log_stream (
@@ -78,7 +81,6 @@ def _process_log_stream(
7881 since : str ,
7982 follow : bool ,
8083) -> None :
81- """Process the log stream with reconnection logic for follow mode."""
8284 log_count = 0
8385 last_timestamp : datetime | None = None
8486 current_since = since
0 commit comments