11import logging
22import logging .config
3- import os
43from datetime import UTC , datetime
54from pathlib import Path
65from typing import Any
76
87from pythonjsonlogger .json import JsonFormatter
98
10- from .config import EnvironmentOption , settings
9+ from .config import settings
1110
1211
1312class ColoredFormatter (logging .Formatter ):
@@ -30,17 +29,6 @@ def format(self, record: logging.LogRecord) -> str:
3029 return super ().format (record_copy )
3130
3231
33- def get_log_level () -> int :
34- """Get log level from environment with validation."""
35- log_level_name = os .getenv ("LOG_LEVEL" , "INFO" ).upper ()
36-
37- level = logging .getLevelNamesMapping ().get (log_level_name )
38- if level is None :
39- raise ValueError (f"Invalid log level '{ log_level_name } '" )
40-
41- return level
42-
43-
4432def log_directory () -> Path :
4533 """Ensure log directory exists and return the path."""
4634 log_dir = Path (__file__ ).parent .parent .parent / "logs"
@@ -50,19 +38,18 @@ def log_directory() -> Path:
5038
5139def get_logging_config () -> dict [str , Any ]:
5240 """Get logging configuration based on environment."""
53- log_level = get_log_level ()
54-
41+ log_level = settings .LOG_LEVEL .value
5542 # Base configuration
5643 config : dict [str , Any ] = {
5744 "version" : 1 ,
5845 "disable_existing_loggers" : False ,
5946 "formatters" : {
60- "development " : {
47+ "colored_text " : {
6148 "()" : ColoredFormatter ,
6249 "format" : "%(asctime)s- %(levelname)s - %(name)s - %(message)s" ,
6350 "datefmt" : "%Y-%m-%d %H:%M:%S" ,
6451 },
65- "file " : {
52+ "plain_text " : {
6653 "format" : "%(asctime)s- %(levelname)s - %(name)s - %(message)s" ,
6754 "datefmt" : "%Y-%m-%d %H:%M:%S" ,
6855 },
@@ -72,13 +59,17 @@ def get_logging_config() -> dict[str, Any]:
7259 },
7360 },
7461 "handlers" : {
75- "console" : {"class" : "logging.StreamHandler" , "level" : log_level , "stream" : "ext://sys.stdout" },
62+ "console" : {
63+ "class" : "logging.StreamHandler" ,
64+ "level" : log_level ,
65+ "stream" : "ext://sys.stdout" ,
66+ },
7667 },
77- "root" : {"level" : log_level , "handlers" : []},
68+ "root" : {"level" : log_level , "handlers" : ["console" ]},
7869 "loggers" : {
7970 "uvicorn.access" : {
8071 "level" : "INFO" ,
81- "handlers" : [],
72+ "handlers" : ["console" ],
8273 "propagate" : False , # Don't propagate to root logger to avoid double logging
8374 },
8475 "uvicorn.error" : {"level" : "INFO" },
@@ -89,8 +80,7 @@ def get_logging_config() -> dict[str, Any]:
8980 },
9081 }
9182
92- # Environment-specific configuration
93- if settings .ENVIRONMENT == EnvironmentOption .LOCAL :
83+ if settings .LOG_TO_FILE :
9484 # Create file handler only when needed
9585 log_dir = log_directory ()
9686 # Keeping filename timestamp granularity to minutes to avoid too
@@ -108,16 +98,17 @@ def get_logging_config() -> dict[str, Any]:
10898 "backupCount" : 5 ,
10999 "formatter" : "file" ,
110100 }
101+ config ["root" ]["handlers" ].append ("file" )
102+ config ["loggers" ]["uvicorn.access" ]["handlers" ].append ("file" )
111103
112- # Plain colored text + file logging
113- config ["handlers" ]["console" ]["formatter" ] = "development"
114- config ["root" ]["handlers" ] = ["console" , "file" ]
115- config ["loggers" ]["uvicorn.access" ]["handlers" ] = ["console" , "file" ]
116- else :
117- # As JSON messages to console
104+ if settings .LOG_FORMAT_AS_JSON :
105+ # As JSON messages
118106 config ["handlers" ]["console" ]["formatter" ] = "json"
119- config ["root" ]["handlers" ] = ["console" ]
120- config ["loggers" ]["uvicorn.access" ]["handlers" ] = ["console" ]
107+ config ["handlers" ]["file" ]["formatter" ] = "json"
108+ else :
109+ # Colored text depending on the logging level
110+ config ["handlers" ]["console" ]["formatter" ] = "colored_text"
111+ config ["handlers" ]["file" ]["formatter" ] = "plain_text"
121112
122113 return config
123114
@@ -129,12 +120,10 @@ def setup_logging() -> None:
129120
130121 # Log startup information
131122 logger = logging .getLogger (__name__ )
132- logger .info (f"Logging configured for { settings .ENVIRONMENT .value } environment" )
133- logger .info (f"Log level set to { logging .getLevelName (get_log_level ())} " )
123+ logger .info (f"Log level set to { settings .LOG_LEVEL .value } " )
124+ if config ["handlers" ]["console" ]["formatter" ] == "json" :
125+ logger .info ("Logs will be written in JSON format" )
126+ if "console" in config ["root" ]["handlers" ]:
127+ logger .info ("Logs will be written to the console" )
134128 if "file" in config ["root" ]["handlers" ]:
135129 logger .info (f"Logs will be written to the file { config ['handlers' ]['file' ]['filename' ]} " )
136- if "console" in config ["root" ]["handlers" ]:
137- extra = ""
138- if config ["handlers" ]["console" ]["formatter" ] == "json" :
139- extra = " in JSON format"
140- logger .info (f"Logs will be written to the console{ extra } " )
0 commit comments