]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Logger/Log.py
BaseTools: Clean up source files
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Logger / Log.py
1 ## @file
2 # This file implements the log mechanism for Python tools.
3 #
4 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 #
6 # This program and the accompanying materials are licensed and made available
7 # under the terms and conditions of the BSD License which accompanies this
8 # distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
10 #
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 #
14
15 '''
16 Logger
17 '''
18
19 ## Import modules
20 from sys import argv
21 from sys import stdout
22 from sys import stderr
23 import os.path
24 from os import remove
25 from logging import getLogger
26 from logging import Formatter
27 from logging import StreamHandler
28 from logging import FileHandler
29 from traceback import extract_stack
30
31 from Logger.ToolError import FatalError
32 from Logger.ToolError import WARNING_AS_ERROR
33 from Logger.ToolError import gERROR_MESSAGE
34 from Logger.ToolError import UNKNOWN_ERROR
35 from Library import GlobalData
36
37 #
38 # Log level constants
39 #
40 DEBUG_0 = 1
41 DEBUG_1 = 2
42 DEBUG_2 = 3
43 DEBUG_3 = 4
44 DEBUG_4 = 5
45 DEBUG_5 = 6
46 DEBUG_6 = 7
47 DEBUG_7 = 8
48 DEBUG_8 = 9
49 DEBUG_9 = 10
50 VERBOSE = 15
51 INFO = 20
52 WARN = 30
53 QUIET = 40
54 QUIET_1 = 41
55 ERROR = 50
56 SILENT = 60
57
58 IS_RAISE_ERROR = True
59 SUPRESS_ERROR = False
60
61 #
62 # Tool name
63 #
64 _TOOL_NAME = os.path.basename(argv[0])
65 #
66 # For validation purpose
67 #
68 _LOG_LEVELS = [DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, \
69 DEBUG_7, DEBUG_8, DEBUG_9, VERBOSE, WARN, INFO, ERROR, QUIET, \
70 QUIET_1, SILENT]
71 #
72 # For DEBUG level (All DEBUG_0~9 are applicable)
73 #
74 _DEBUG_LOGGER = getLogger("tool_debug")
75 _DEBUG_FORMATTER = Formatter("[%(asctime)s.%(msecs)d]: %(message)s", \
76 datefmt="%H:%M:%S")
77 #
78 # For VERBOSE, INFO, WARN level
79 #
80 _INFO_LOGGER = getLogger("tool_info")
81 _INFO_FORMATTER = Formatter("%(message)s")
82 #
83 # For ERROR level
84 #
85 _ERROR_LOGGER = getLogger("tool_error")
86 _ERROR_FORMATTER = Formatter("%(message)s")
87
88 #
89 # String templates for ERROR/WARN/DEBUG log message
90 #
91 _ERROR_MESSAGE_TEMPLATE = \
92 ('\n\n%(tool)s...\n%(file)s(%(line)s): error %(errorcode)04X: %(msg)s\n\t%(extra)s')
93
94 __ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE = \
95 '\n\n%(tool)s...\n : error %(errorcode)04X: %(msg)s\n\t%(extra)s'
96
97 _WARNING_MESSAGE_TEMPLATE = '%(tool)s...\n%(file)s(%(line)s): warning: %(msg)s'
98 _WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE = '%(tool)s: : warning: %(msg)s'
99 _DEBUG_MESSAGE_TEMPLATE = '%(file)s(%(line)s): debug: \n %(msg)s'
100
101
102 #
103 # Log INFO message
104 #
105 #Info = _INFO_LOGGER.info
106
107 def Info(msg, *args, **kwargs):
108 _INFO_LOGGER.info(msg, *args, **kwargs)
109
110 #
111 # Log information which should be always put out
112 #
113 def Quiet(msg, *args, **kwargs):
114 _ERROR_LOGGER.error(msg, *args, **kwargs)
115
116 ## Log debug message
117 #
118 # @param Level DEBUG level (DEBUG0~9)
119 # @param Message Debug information
120 # @param ExtraData More information associated with "Message"
121 #
122 def Debug(Level, Message, ExtraData=None):
123 if _DEBUG_LOGGER.level > Level:
124 return
125 if Level > DEBUG_9:
126 return
127 #
128 # Find out the caller method information
129 #
130 CallerStack = extract_stack()[-2]
131 TemplateDict = {
132 "file" : CallerStack[0],
133 "line" : CallerStack[1],
134 "msg" : Message,
135 }
136
137 if ExtraData is not None:
138 LogText = _DEBUG_MESSAGE_TEMPLATE % TemplateDict + "\n %s" % ExtraData
139 else:
140 LogText = _DEBUG_MESSAGE_TEMPLATE % TemplateDict
141
142 _DEBUG_LOGGER.log(Level, LogText)
143
144 ## Log verbose message
145 #
146 # @param Message Verbose information
147 #
148 def Verbose(Message):
149 return _INFO_LOGGER.log(VERBOSE, Message)
150
151 ## Log warning message
152 #
153 # Warning messages are those which might be wrong but won't fail the tool.
154 #
155 # @param ToolName The name of the tool. If not given, the name of caller
156 # method will be used.
157 # @param Message Warning information
158 # @param File The name of file which caused the warning.
159 # @param Line The line number in the "File" which caused the warning.
160 # @param ExtraData More information associated with "Message"
161 #
162 def Warn(ToolName, Message, File=None, Line=None, ExtraData=None):
163 if _INFO_LOGGER.level > WARN:
164 return
165 #
166 # if no tool name given, use caller's source file name as tool name
167 #
168 if ToolName is None or ToolName == "":
169 ToolName = os.path.basename(extract_stack()[-2][0])
170
171 if Line is None:
172 Line = "..."
173 else:
174 Line = "%d" % Line
175
176 TemplateDict = {
177 "tool" : ToolName,
178 "file" : File,
179 "line" : Line,
180 "msg" : Message,
181 }
182
183 if File is not None:
184 LogText = _WARNING_MESSAGE_TEMPLATE % TemplateDict
185 else:
186 LogText = _WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE % TemplateDict
187
188 if ExtraData is not None:
189 LogText += "\n %s" % ExtraData
190
191 _INFO_LOGGER.log(WARN, LogText)
192 #
193 # Raise an execption if indicated
194 #
195 if GlobalData.gWARNING_AS_ERROR == True:
196 raise FatalError(WARNING_AS_ERROR)
197
198 ## Log ERROR message
199 #
200 # Once an error messages is logged, the tool's execution will be broken by
201 # raising an execption. If you don't want to break the execution later, you
202 # can give "RaiseError" with "False" value.
203 #
204 # @param ToolName The name of the tool. If not given, the name of caller
205 # method will be used.
206 # @param ErrorCode The error code
207 # @param Message Warning information
208 # @param File The name of file which caused the error.
209 # @param Line The line number in the "File" which caused the warning.
210 # @param ExtraData More information associated with "Message"
211 # @param RaiseError Raise an exception to break the tool's executuion if
212 # it's True. This is the default behavior.
213 #
214 def Error(ToolName, ErrorCode, Message=None, File=None, Line=None, \
215 ExtraData=None, RaiseError=IS_RAISE_ERROR):
216 if ToolName:
217 pass
218 if Line is None:
219 Line = "..."
220 else:
221 Line = "%d" % Line
222
223 if Message is None:
224 if ErrorCode in gERROR_MESSAGE:
225 Message = gERROR_MESSAGE[ErrorCode]
226 else:
227 Message = gERROR_MESSAGE[UNKNOWN_ERROR]
228
229 if ExtraData is None:
230 ExtraData = ""
231
232 TemplateDict = {
233 "tool" : _TOOL_NAME,
234 "file" : File,
235 "line" : Line,
236 "errorcode" : ErrorCode,
237 "msg" : Message,
238 "extra" : ExtraData
239 }
240
241 if File is not None:
242 LogText = _ERROR_MESSAGE_TEMPLATE % TemplateDict
243 else:
244 LogText = __ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE % TemplateDict
245
246 if not SUPRESS_ERROR:
247 _ERROR_LOGGER.log(ERROR, LogText)
248 if RaiseError:
249 raise FatalError(ErrorCode)
250
251
252 ## Initialize log system
253 #
254 def Initialize():
255 #
256 # Since we use different format to log different levels of message into
257 # different place (stdout or stderr), we have to use different "Logger"
258 # objects to do this.
259 #
260 # For DEBUG level (All DEBUG_0~9 are applicable)
261 _DEBUG_LOGGER.setLevel(INFO)
262 _DebugChannel = StreamHandler(stdout)
263 _DebugChannel.setFormatter(_DEBUG_FORMATTER)
264 _DEBUG_LOGGER.addHandler(_DebugChannel)
265 #
266 # For VERBOSE, INFO, WARN level
267 #
268 _INFO_LOGGER.setLevel(INFO)
269 _InfoChannel = StreamHandler(stdout)
270 _InfoChannel.setFormatter(_INFO_FORMATTER)
271 _INFO_LOGGER.addHandler(_InfoChannel)
272 #
273 # For ERROR level
274 #
275 _ERROR_LOGGER.setLevel(INFO)
276 _ErrorCh = StreamHandler(stderr)
277 _ErrorCh.setFormatter(_ERROR_FORMATTER)
278 _ERROR_LOGGER.addHandler(_ErrorCh)
279
280
281 ## Set log level
282 #
283 # @param Level One of log level in _LogLevel
284 #
285 def SetLevel(Level):
286 if Level not in _LOG_LEVELS:
287 Info("Not supported log level (%d). Use default level instead." % \
288 Level)
289 Level = INFO
290 _DEBUG_LOGGER.setLevel(Level)
291 _INFO_LOGGER.setLevel(Level)
292 _ERROR_LOGGER.setLevel(Level)
293
294 ## Get current log level
295 #
296 def GetLevel():
297 return _INFO_LOGGER.getEffectiveLevel()
298
299 ## Raise up warning as error
300 #
301 def SetWarningAsError():
302 GlobalData.gWARNING_AS_ERROR = True
303
304 ## Specify a file to store the log message as well as put on console
305 #
306 # @param LogFile The file path used to store the log message
307 #
308 def SetLogFile(LogFile):
309 if os.path.exists(LogFile):
310 remove(LogFile)
311
312 _Ch = FileHandler(LogFile)
313 _Ch.setFormatter(_DEBUG_FORMATTER)
314 _DEBUG_LOGGER.addHandler(_Ch)
315
316 _Ch = FileHandler(LogFile)
317 _Ch.setFormatter(_INFO_FORMATTER)
318 _INFO_LOGGER.addHandler(_Ch)
319
320 _Ch = FileHandler(LogFile)
321 _Ch.setFormatter(_ERROR_FORMATTER)
322 _ERROR_LOGGER.addHandler(_Ch)
323
324
325