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