13
13
from shared_configs .configs import SLACK_CHANNEL_ID
14
14
from shared_configs .configs import TENANT_ID_PREFIX
15
15
from shared_configs .contextvars import CURRENT_TENANT_ID_CONTEXTVAR
16
+ from shared_configs .contextvars import ONYX_REQUEST_ID_CONTEXTVAR
16
17
17
18
18
19
logging .addLevelName (logging .INFO + 5 , "NOTICE" )
@@ -71,6 +72,14 @@ def get_log_level_from_str(log_level_str: str = LOG_LEVEL) -> int:
71
72
return log_level_dict .get (log_level_str .upper (), logging .getLevelName ("NOTICE" ))
72
73
73
74
75
+ class OnyxRequestIDFilter (logging .Filter ):
76
+ def filter (self , record : logging .LogRecord ) -> bool :
77
+ from shared_configs .contextvars import ONYX_REQUEST_ID_CONTEXTVAR
78
+
79
+ record .request_id = ONYX_REQUEST_ID_CONTEXTVAR .get () or "-"
80
+ return True
81
+
82
+
74
83
class OnyxLoggingAdapter (logging .LoggerAdapter ):
75
84
def process (
76
85
self , msg : str , kwargs : MutableMapping [str , Any ]
@@ -103,6 +112,7 @@ def process(
103
112
msg = f"[CC Pair: { cc_pair_id } ] { msg } "
104
113
105
114
break
115
+
106
116
# Add tenant information if it differs from default
107
117
# This will always be the case for authenticated API requests
108
118
if MULTI_TENANT :
@@ -115,6 +125,11 @@ def process(
115
125
)
116
126
msg = f"[t:{ short_tenant } ] { msg } "
117
127
128
+ # request id within a fastapi route
129
+ fastapi_request_id = ONYX_REQUEST_ID_CONTEXTVAR .get ()
130
+ if fastapi_request_id :
131
+ msg = f"[{ fastapi_request_id } ] { msg } "
132
+
118
133
# For Slack Bot, logs the channel relevant to the request
119
134
channel_id = self .extra .get (SLACK_CHANNEL_ID ) if self .extra else None
120
135
if channel_id :
@@ -165,6 +180,14 @@ def format(self, record: logging.LogRecord) -> str:
165
180
return super ().format (record )
166
181
167
182
183
+ def get_uvicorn_standard_formatter () -> ColoredFormatter :
184
+ """Returns a standard colored logging formatter."""
185
+ return ColoredFormatter (
186
+ "%(asctime)s %(filename)30s %(lineno)4s: [%(request_id)s] %(message)s" ,
187
+ datefmt = "%m/%d/%Y %I:%M:%S %p" ,
188
+ )
189
+
190
+
168
191
def get_standard_formatter () -> ColoredFormatter :
169
192
"""Returns a standard colored logging formatter."""
170
193
return ColoredFormatter (
@@ -201,12 +224,6 @@ def setup_logger(
201
224
202
225
logger .addHandler (handler )
203
226
204
- uvicorn_logger = logging .getLogger ("uvicorn.access" )
205
- if uvicorn_logger :
206
- uvicorn_logger .handlers = []
207
- uvicorn_logger .addHandler (handler )
208
- uvicorn_logger .setLevel (log_level )
209
-
210
227
is_containerized = is_running_in_container ()
211
228
if LOG_FILE_NAME and (is_containerized or DEV_LOGGING_ENABLED ):
212
229
log_levels = ["debug" , "info" , "notice" ]
@@ -225,14 +242,37 @@ def setup_logger(
225
242
file_handler .setFormatter (formatter )
226
243
logger .addHandler (file_handler )
227
244
228
- if uvicorn_logger :
229
- uvicorn_logger .addHandler (file_handler )
230
-
231
245
logger .notice = lambda msg , * args , ** kwargs : logger .log (logging .getLevelName ("NOTICE" ), msg , * args , ** kwargs ) # type: ignore
232
246
233
247
return OnyxLoggingAdapter (logger , extra = extra )
234
248
235
249
250
+ def setup_uvicorn_logger (
251
+ log_level : int = get_log_level_from_str (),
252
+ shared_file_handlers : list [logging .FileHandler ] | None = None ,
253
+ ) -> None :
254
+ uvicorn_logger = logging .getLogger ("uvicorn.access" )
255
+ if not uvicorn_logger :
256
+ return
257
+
258
+ formatter = get_uvicorn_standard_formatter ()
259
+
260
+ handler = logging .StreamHandler ()
261
+ handler .setLevel (log_level )
262
+ handler .setFormatter (formatter )
263
+
264
+ uvicorn_logger .handlers = []
265
+ uvicorn_logger .addHandler (handler )
266
+ uvicorn_logger .setLevel (log_level )
267
+ uvicorn_logger .addFilter (OnyxRequestIDFilter ())
268
+
269
+ if shared_file_handlers :
270
+ for fh in shared_file_handlers :
271
+ uvicorn_logger .addHandler (fh )
272
+
273
+ return
274
+
275
+
236
276
def print_loggers () -> None :
237
277
"""Print information about all loggers. Use to debug logging issues."""
238
278
root_logger = logging .getLogger ()
0 commit comments