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