3
3
import re
4
4
import sys
5
5
6
+ from logging import FileHandler , StreamHandler
6
7
from logging .handlers import RotatingFileHandler
8
+ from typing import Optional , Union
9
+
7
10
8
11
try :
9
- from colorama import Fore , Style
12
+ from colorama import Fore , Style , init as color_init
10
13
except ImportError :
11
14
Fore = Style = type ("Dummy" , (object ,), {"__getattr__" : lambda self , item : "" })()
15
+ else :
16
+ color_init ()
12
17
13
18
14
19
if ".heroku" in os .environ .get ("PYTHONHOME" , "" ):
@@ -64,18 +69,87 @@ def line(self, level="info"):
64
69
)
65
70
66
71
67
- logging .setLoggerClass (ModmailLogger )
68
- log_level = logging .INFO
69
- loggers = set ()
72
+ class FileFormatter (logging .Formatter ):
73
+ ansi_escape = re .compile (r"\x1B\[[0-?]*[ -/]*[@-~]" )
74
+
75
+ def format (self , record ):
76
+ record .msg = self .ansi_escape .sub ("" , record .msg )
77
+ return super ().format (record )
78
+
70
79
71
- ch = logging .StreamHandler (stream = sys .stdout )
72
- ch .setLevel (log_level )
73
80
log_stream_formatter = logging .Formatter (
74
81
"%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s" , datefmt = "%m/%d/%y %H:%M:%S"
75
82
)
76
- ch .setFormatter (log_stream_formatter )
83
+ log_file_formatter = FileFormatter (
84
+ "%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s" ,
85
+ datefmt = "%Y-%m-%d %H:%M:%S" ,
86
+ )
87
+
88
+
89
+ def create_log_handler (
90
+ filename : Optional [str ] = None ,
91
+ * ,
92
+ rotating : bool = False ,
93
+ level : int = logging .DEBUG ,
94
+ mode : str = "a+" ,
95
+ encoding : str = "utf-8" ,
96
+ maxBytes : int = 48000 ,
97
+ backupCount : int = 1 ,
98
+ ** kwargs ,
99
+ ) -> Union [FileHandler , RotatingFileHandler , StreamHandler ]:
100
+ """
101
+ Return a pre-configured log handler. This function is made for consistency sake with
102
+ pre-defined default values for parameters and formatters to pass to handler class.
103
+ Additional keyword arguments also can be specified, just in case.
104
+
105
+ Plugin developers should not use this and only use the `getLogger` instead to instantiate the ModmailLogger object.
106
+
107
+ Parameters
108
+ -----------
109
+ filename : Optional[Path]
110
+ Specifies that a `FileHandler` or `RotatingFileHandler` be created, using the specified filename,
111
+ rather than a `StreamHandler`. Defaults to `None`.
112
+ rotating : bool
113
+ Whether the file handler should be the `RotatingFileHandler`. Defaults to `False`. Note, this
114
+ argument only compatible if the `filename` is specified, otherwise `ValueError` will be raised.
115
+ level : int
116
+ The root logger level for the handler. Defaults to `logging.DEBUG`.
117
+ mode : str
118
+ If filename is specified, open the file in this mode. Defaults to 'a+'.
119
+ encoding : str
120
+ If this keyword argument is specified along with filename, its value is used when the `FileHandler` is created,
121
+ and thus used when opening the output file. Defaults to 'utf-8'.
122
+ maxBytes : int
123
+ The max file size before the rollover occurs. Defaults to 48000. Rollover occurs whenever the current log file
124
+ is nearly `maxBytes` in length; but if either of `maxBytes` or `backupCount` is zero, rollover never occurs, so you
125
+ generally want to set `backupCount` to at least 1.
126
+ backupCount : int
127
+ Max number of backup files. Defaults to 1. If this is set to zero, rollover will never occur.
128
+ """
129
+ if filename is None and rotating :
130
+ raise ValueError ("`filename` must be set to instantiate a `RotatingFileHandler`." )
131
+
132
+ if filename is None :
133
+ handler = StreamHandler (stream = sys .stdout , ** kwargs )
134
+ handler .setFormatter (log_stream_formatter )
135
+ elif not rotating :
136
+ handler = FileHandler (filename , mode = mode , encoding = encoding , ** kwargs )
137
+ handler .setFormatter (log_file_formatter )
138
+ else :
139
+ handler = RotatingFileHandler (
140
+ filename , mode = mode , encoding = encoding , maxBytes = maxBytes , backupCount = backupCount , ** kwargs
141
+ )
142
+ handler .setFormatter (log_file_formatter )
77
143
78
- ch_debug = None
144
+ handler .setLevel (level )
145
+ return handler
146
+
147
+
148
+ logging .setLoggerClass (ModmailLogger )
149
+ log_level = logging .INFO
150
+ loggers = set ()
151
+ ch : StreamHandler = create_log_handler (level = log_level )
152
+ ch_debug : Optional [RotatingFileHandler ] = None
79
153
80
154
81
155
def getLogger (name = None ) -> ModmailLogger :
@@ -88,25 +162,9 @@ def getLogger(name=None) -> ModmailLogger:
88
162
return logger
89
163
90
164
91
- class FileFormatter (logging .Formatter ):
92
- ansi_escape = re .compile (r"\x1B\[[0-?]*[ -/]*[@-~]" )
93
-
94
- def format (self , record ):
95
- record .msg = self .ansi_escape .sub ("" , record .msg )
96
- return super ().format (record )
97
-
98
-
99
- log_file_formatter = FileFormatter (
100
- "%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s" ,
101
- datefmt = "%Y-%m-%d %H:%M:%S" ,
102
- )
103
-
104
-
105
- def configure_logging (name , level = None , ** handler_params ):
165
+ def configure_logging (name , level : Optional [int ] = None ):
106
166
global ch_debug , log_level
107
- ch_debug = RotatingFileHandler (name , ** handler_params )
108
- ch_debug .setFormatter (log_file_formatter )
109
- ch_debug .setLevel (logging .DEBUG )
167
+ ch_debug = create_log_handler (name , rotating = True )
110
168
111
169
if level is not None :
112
170
log_level = level
0 commit comments