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