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