66import google .cloud .logging
77from google .cloud .logging_v2 import Client
88
9+ from middleware .request_context import get_request_context
10+ from utils .config import get_config , PROJECT_ID
11+
12+
913def get_env_logging_level ():
1014 """
1115 Get the logging level from the environment via OS variable LOGGING_LEVEL. Returns INFO if not set.
@@ -60,12 +64,12 @@ def init_logger():
6064 if hasattr (Logger , "initialized" ):
6165 return
6266 logging .basicConfig (level = get_env_logging_level ())
63- if not is_local_env ():
67+ if is_local_env ():
6468 # Use the default logging handler
6569 logging .info ("Using default logging handler" )
6670 return
6771 try :
68- client = google .cloud .logging .Client ()
72+ client = google .cloud .logging_v2 .Client ()
6973 client .get_default_handler ()
7074 client .setup_logging ()
7175 logging .info ("GCP logging client initialized" )
@@ -78,10 +82,69 @@ def init_logger():
7882 def get_logger (self ):
7983 return self .logger
8084
85+
86+ class TraceLogger :
87+ def __init__ (self , logger : logging .Logger , project_id : str , trace_id : str , span_id : str ):
88+ self ._logger = logger
89+ self ._trace_id = None
90+ self ._span_id = None
91+ self ._project_id = project_id
92+ self ._trace_id = trace_id
93+ self ._span_id = span_id
94+
95+ def _inject_trace (self , extra ):
96+ if not self ._trace_id or not self ._span_id :
97+ return extra or {}
98+
99+ trace_fields = {
100+ "logging.googleapis.com/trace" : f"projects/{ self ._project_id } /traces/{ self ._trace_id } " ,
101+ "logging.googleapis.com/spanId" : self ._span_id ,
102+ "logging.googleapis.com/trace_sampled" : True ,
103+ }
104+ if extra :
105+ trace_fields .update (extra )
106+ return trace_fields
107+
108+ def info (self , msg , * args , extra = None , ** kwargs ):
109+ return self ._logger .info (msg , * args , extra = self ._inject_trace (extra ), ** kwargs )
110+
111+ def error (self , msg , * args , extra = None , ** kwargs ):
112+ return self ._logger .error (msg , * args , extra = self ._inject_trace (extra ), ** kwargs )
113+
114+ def warning (self , msg , * args , extra = None , ** kwargs ):
115+ return self ._logger .warning (msg , * args , extra = self ._inject_trace (extra ), ** kwargs )
116+
117+ def debug (self , msg , * args , extra = None , ** kwargs ):
118+ return self ._logger .debug (msg , * args , extra = self ._inject_trace (extra ), ** kwargs )
119+
120+ def exception (self , msg , * args , extra = None , ** kwargs ):
121+ return self ._logger .exception (msg , * args , extra = self ._inject_trace (extra ), ** kwargs )
122+
123+
81124def new_logger (name : str ):
82125 """
83126 Create a new logger with the given name.
84127 """
85- Logger .init_logger ()
86- return logging .getLogger (name )
128+ logger = logging .getLogger (name )
129+ logger .setLevel (get_env_logging_level ())
130+ if not logger .handlers :
131+ if is_local_env ():
132+ handler = logging .StreamHandler ()
133+ else :
134+ from google .cloud .logging import Client
135+ from google .cloud .logging .handlers import CloudLoggingHandler
136+ client = Client ()
137+ handler = CloudLoggingHandler (client )
138+
139+ formatter = logging .Formatter (
140+ '%(asctime)s %(levelname)s %(name)s %(message)s'
141+ )
142+ handler .setFormatter (formatter )
143+ logger .addHandler (handler )
144+
145+ request_context = get_request_context ()
146+ if not request_context :
147+ return logger
148+ return TraceLogger (logger , get_config (PROJECT_ID ), request_context .get ("trace_id" ), request_context .get ("span_id" ))
149+
87150
0 commit comments