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