66- Redaction of sensitive information
77- Consistent log level usage
88- Enhanced context information
9- - Test /production environment tagging
9+ - Optional test /production ``env_tag`` on records (for filters and custom formats)
1010"""
1111
1212from __future__ import annotations
@@ -86,6 +86,21 @@ def get_environment_tag() -> str:
8686 return _get_environment_tag ()
8787
8888
89+ def format_log_pid_short (process : int | None ) -> str :
90+ """Format a process id for log lines: asterisk plus last four decimal digits.
91+
92+ Used inside ``[pid=...]``, e.g. process ``440852`` -> ``*0852`` so the tag reads
93+ ``[pid=*0852]``.
94+ """
95+ if process is None :
96+ return "*----"
97+ try :
98+ pid_int = int (process )
99+ except (TypeError , ValueError ):
100+ return "*----"
101+ return f"*{ pid_int % 10000 :04d} "
102+
103+
89104class EnvironmentTaggingFilter (logging .Filter ):
90105 """Logging filter that adds environment tags to log records."""
91106
@@ -107,9 +122,10 @@ def filter(self, record: logging.LogRecord) -> bool: # type: ignore[override]
107122
108123
109124class EnvironmentTaggingFormatter (logging .Formatter ):
110- """Logging formatter that includes environment tags and PID .
125+ """Logging formatter with shortened ``pid`` placeholder for log lines .
111126
112- Format: YYYY-MM-DD HH:MM:SS,mmm [LEVEL] [env] [pid=XXX] name:lineno message
127+ Default format: ``YYYY-MM-DD HH:MM:SS,mmm [LEVEL] [pid=*XXXX] name:lineno message``
128+ where ``*XXXX`` is an asterisk plus the process id modulo 10000 (four digits).
113129 """
114130
115131 def __init__ (
@@ -118,15 +134,13 @@ def __init__(
118134 datefmt : str | None = None ,
119135 style : Literal ["%" , "{" , "$" ] = "%" ,
120136 ) -> None :
121- # Set default format if none provided - compact level, env tag, and PID
122137 if fmt is None :
123- fmt = "%(asctime)s [%(levelname)s] [%(env_tag)s] [ pid=%(process)d] [stream_id=%(stream_id )s] %(name)s:%(lineno)d %(message)s"
138+ fmt = "%(asctime)s [%(levelname)s] [pid=%(pid_short )s] %(name)s:%(lineno)d %(message)s"
124139 super ().__init__ (fmt , datefmt , style = style )
125140
126141 def format (self , record : logging .LogRecord ) -> str :
127- """Populate optional logging fields used by the global format."""
128- if not hasattr (record , "stream_id" ):
129- record .stream_id = "-"
142+ """Set ``pid_short`` on the record for the format string."""
143+ record .pid_short = format_log_pid_short (getattr (record , "process" , None ))
130144 return super ().format (record )
131145
132146
@@ -533,9 +547,8 @@ def install_environment_tagging() -> None:
533547 for handler in list (root .handlers ):
534548 try :
535549 handler .addFilter (filter_instance )
536- # Update formatter to include environment tag
550+ # Normalize formatter to EnvironmentTaggingFormatter (pid_short, etc.)
537551 if isinstance (handler .formatter , logging .Formatter ):
538- # Use the environment tagging formatter
539552 new_formatter = EnvironmentTaggingFormatter (
540553 fmt = handler .formatter ._fmt , datefmt = handler .formatter .datefmt
541554 )
@@ -560,19 +573,17 @@ def configure_logging_with_environment_tagging(
560573 use_colors : bool = False ,
561574 console_stream : str = "stderr" ,
562575) -> None :
563- """Configure logging with environment tagging .
576+ """Configure root logging, structlog, env-tag filter, and standard formatters .
564577
565578 Args:
566579 level: Logging level
567580 log_format: Optional log format string
568581 log_file: Optional log file path
569582 use_colors: Whether to enable colored output
570583 """
571- # Use default format with environment tag if none provided - compact level, env tag, and PID
572584 if log_format is None :
573- log_format = "%(asctime)s [%(levelname)s] [%(env_tag)s] [ pid=%(process)d] [stream_id=%(stream_id )s] %(name)s:%(lineno)d %(message)s"
585+ log_format = "%(asctime)s [%(levelname)s] [pid=%(pid_short )s] %(name)s:%(lineno)d %(message)s"
574586
575- # Create formatter with environment tag support
576587 formatter = EnvironmentTaggingFormatter (fmt = log_format )
577588
578589 # Create handlers
@@ -588,9 +599,8 @@ def configure_logging_with_environment_tagging(
588599 from rich .logging import RichHandler
589600
590601 # Use RichHandler for colored output
591- # Define a simplified format for Rich that excludes time/level (Rich handles them)
592- # but includes the environment tag and location info
593- rich_fmt = "[%(env_tag)s] %(name)s:%(lineno)d %(message)s"
602+ # Simplified format for Rich (time/level come from Rich); keep pid + location
603+ rich_fmt = "[pid=%(pid_short)s] %(name)s:%(lineno)d %(message)s"
594604 rich_formatter = EnvironmentTaggingFormatter (fmt = rich_fmt )
595605
596606 console_handler = RichHandler (
0 commit comments