@@ -62,14 +62,23 @@ def _pre_chain() -> list:
6262 structlog .processors .TimeStamper (fmt = "ISO" , key = TIME_KEY ),
6363 ]
6464
65- def _build_console_handler (level : int ) -> logging .Handler :
66- formatter = structlog .stdlib .ProcessorFormatter (
67- foreign_pre_chain = _pre_chain (),
68- processors = [
65+ def _build_console_handler (level : int , renderer : str ) -> logging .Handler :
66+ """Build a console handler with either pretty or JSON rendering."""
67+
68+ processors : list [Any ]
69+ if renderer == "json" :
70+ processors = [
71+ structlog .stdlib .ProcessorFormatter .remove_processors_meta ,
72+ structlog .processors .EventRenamer (to = "message" ),
73+ structlog .processors .JSONRenderer (),
74+ ]
75+ else : # pretty (default)
76+ processors = [
6977 structlog .stdlib .ProcessorFormatter .remove_processors_meta ,
7078 structlog .dev .ConsoleRenderer (colors = _supports_colour (), timestamp_key = TIME_KEY ),
71- ],
72- )
79+ ]
80+
81+ formatter = structlog .stdlib .ProcessorFormatter (foreign_pre_chain = _pre_chain (), processors = processors ,)
7382 handler = logging .StreamHandler (sys .stdout )
7483 handler .setLevel (level )
7584 handler .setFormatter (formatter )
@@ -103,10 +112,13 @@ def _build_file_handler(file_cfg: Dict[str, Any]) -> logging.Handler:
103112
104113
105114def init_logger (config_path : str | Path | None = None ) -> None :
106- """Structured setup for hosted agents: JSON for files and non-TTY stdout.
115+ """Structured logging setup.
116+
117+ Console renderer is configurable via config, with env override support when needed:
118+ - Config: logging.console.renderer = "json" | "pretty" (default: pretty)
119+ - Env (optional): LOG_CONSOLE_RENDERER=pretty|json (wins over config)
107120
108- - Local TTY console: coloured ConsoleRenderer for readability
109- - Non-TTY stdout and files: JSON for ingestion by log frameworks
121+ Files always use JSON with optional rotation.
110122 """
111123 cfg = _read_cfg (config_path )
112124
@@ -125,7 +137,10 @@ def init_logger(config_path: str | Path | None = None) -> None:
125137 # Console handler enabled by default
126138 console_enabled = cfg .get ("console" , {}).get ("enabled" , True )
127139 if console_enabled :
128- handlers .append (_build_console_handler (root_level ))
140+ renderer = os .getenv ("LOG_CONSOLE_RENDERER" ) or cfg .get ("console" , {}).get ("renderer" , "pretty" ).strip ().lower ()
141+ if renderer not in {"json" , "pretty" }:
142+ raise ValueError (f"Invalid console logging renderer option: { renderer !r} . Allowed: json, pretty" )
143+ handlers .append (_build_console_handler (root_level , renderer ))
129144
130145 # File handler (JSON) if enabled
131146 file_cfg = cfg .get ("file" , {})
0 commit comments