1010
1111from app .utils .singleton import SingletonMetaNoArgs
1212
13+ class RotatingBytesLogger :
14+ """Logger that respects RotatingFileHandler's rotation capabilities."""
1315
14- # TODO: merge this wrapper with the one in structlog under one hood of AppLogger
15- class BytesToTextIOWrapper :
16- def __init__ (self , handler , encoding = "utf-8" ):
16+ def __init__ (self , handler ):
1717 self .handler = handler
18- self .encoding = encoding
1918
20- def write (self , b ):
21- if isinstance (b , bytes ):
22- self .handler .stream .write (b .decode (self .encoding ))
23- else :
24- self .handler .stream .write (b )
25- self .handler .flush ()
19+ def msg (self , message ):
20+ """Process a message and pass it through the handler's emit method."""
21+ if isinstance (message , bytes ):
22+ message = message .decode ("utf-8" )
2623
27- def flush (self ):
28- self .handler .flush ()
24+ # Create a log record that will trigger rotation checks
25+ record = logging .LogRecord (
26+ name = "structlog" ,
27+ level = logging .INFO ,
28+ pathname = "" ,
29+ lineno = 0 ,
30+ msg = message .rstrip ("\n " ),
31+ args = (),
32+ exc_info = None
33+ )
34+
35+ # Check if rotation is needed before emitting
36+ if self .handler .shouldRollover (record ):
37+ self .handler .doRollover ()
38+
39+ # Emit the record through the handler
40+ self .handler .emit (record )
41+
42+ # Required methods to make it compatible with structlog
43+ def debug (self , message ):
44+ self .msg (message )
45+
46+ def info (self , message ):
47+ self .msg (message )
48+
49+ def warning (self , message ):
50+ self .msg (message )
51+
52+ def error (self , message ):
53+ self .msg (message )
54+
55+ def critical (self , message ):
56+ self .msg (message )
57+
58+
59+ class RotatingBytesLoggerFactory :
60+ """Factory that creates loggers that respect file rotation."""
61+
62+ def __init__ (self , handler ):
63+ self .handler = handler
2964
30- def close (self ):
31- self .handler . close ( )
65+ def __call__ (self , * args , ** kwargs ):
66+ return RotatingBytesLogger ( self .handler )
3267
3368
3469@define (slots = True )
@@ -40,8 +75,7 @@ def __attrs_post_init__(self):
4075 _log_path = Path (f"{ _log_date } _{ os .getpid ()} .log" )
4176 _handler = RotatingFileHandler (
4277 filename = _log_path ,
43- mode = "a" ,
44- maxBytes = 10 * 1024 * 1024 ,
78+ maxBytes = 1000 ,
4579 backupCount = 5 ,
4680 encoding = "utf-8"
4781 )
@@ -55,11 +89,9 @@ def __attrs_post_init__(self):
5589 structlog .processors .TimeStamper (fmt = "iso" , utc = True ),
5690 structlog .processors .JSONRenderer (serializer = orjson .dumps ),
5791 ],
58- logger_factory = structlog .BytesLoggerFactory (
59- file = BytesToTextIOWrapper (_handler )
60- )
92+ logger_factory = RotatingBytesLoggerFactory (_handler )
6193 )
6294 self ._logger = structlog .get_logger ()
6395
6496 def get_logger (self ) -> structlog .BoundLogger :
65- return self ._logger
97+ return self ._logger
0 commit comments