Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow/python/platform/tf_logging.py: 42%

158 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-10-05 06:32 +0000

1# Copyright 2015 The TensorFlow Authors. All Rights Reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14# ============================================================================== 

15 

16"""Logging utilities.""" 

17# pylint: disable=unused-import 

18# pylint: disable=g-bad-import-order 

19# pylint: disable=invalid-name 

20import logging as _logging 

21import os as _os 

22import sys as _sys 

23import _thread 

24import time as _time 

25import traceback as _traceback 

26from logging import DEBUG 

27from logging import ERROR 

28from logging import FATAL 

29from logging import INFO 

30from logging import WARN 

31import threading 

32 

33from tensorflow.python.util.tf_export import tf_export 

34 

35# Don't use this directly. Use get_logger() instead. 

36_logger = None 

37_logger_lock = threading.Lock() 

38 

39 

40def error_log(error_msg, level=ERROR): 

41 """Empty helper method.""" 

42 del error_msg, level 

43 

44 

45def _get_caller(offset=3): 

46 """Returns a code and frame object for the lowest non-logging stack frame.""" 

47 # Use sys._getframe(). This avoids creating a traceback object. 

48 # pylint: disable=protected-access 

49 f = _sys._getframe(offset) 

50 # pylint: enable=protected-access 

51 our_file = f.f_code.co_filename 

52 f = f.f_back 

53 while f: 

54 code = f.f_code 

55 if code.co_filename != our_file: 

56 return code, f 

57 f = f.f_back 

58 return None, None 

59 

60# The definition of `findCaller` changed in Python 3.2, 

61# and further changed in Python 3.8 

62if _sys.version_info.major >= 3 and _sys.version_info.minor >= 8: 

63 

64 def _logger_find_caller(stack_info=False, stacklevel=1): # pylint: disable=g-wrong-blank-lines 

65 code, frame = _get_caller(4) 

66 sinfo = None 

67 if stack_info: 

68 sinfo = '\n'.join(_traceback.format_stack()) 

69 if code: 

70 return (code.co_filename, frame.f_lineno, code.co_name, sinfo) 

71 else: 

72 return '(unknown file)', 0, '(unknown function)', sinfo 

73elif _sys.version_info.major >= 3 and _sys.version_info.minor >= 2: 

74 

75 def _logger_find_caller(stack_info=False): # pylint: disable=g-wrong-blank-lines 

76 code, frame = _get_caller(4) 

77 sinfo = None 

78 if stack_info: 

79 sinfo = '\n'.join(_traceback.format_stack()) 

80 if code: 

81 return (code.co_filename, frame.f_lineno, code.co_name, sinfo) 

82 else: 

83 return '(unknown file)', 0, '(unknown function)', sinfo 

84else: 

85 def _logger_find_caller(): # pylint: disable=g-wrong-blank-lines 

86 code, frame = _get_caller(4) 

87 if code: 

88 return (code.co_filename, frame.f_lineno, code.co_name) 

89 else: 

90 return '(unknown file)', 0, '(unknown function)' 

91 

92 

93@tf_export('get_logger') 

94def get_logger(): 

95 """Return TF logger instance. 

96 

97 Returns: 

98 An instance of the Python logging library Logger. 

99 

100 See Python documentation (https://docs.python.org/3/library/logging.html) 

101 for detailed API. Below is only a summary. 

102 

103 The logger has 5 levels of logging from the most serious to the least: 

104 

105 1. FATAL 

106 2. ERROR 

107 3. WARN 

108 4. INFO 

109 5. DEBUG 

110 

111 The logger has the following methods, based on these logging levels: 

112 

113 1. fatal(msg, *args, **kwargs) 

114 2. error(msg, *args, **kwargs) 

115 3. warn(msg, *args, **kwargs) 

116 4. info(msg, *args, **kwargs) 

117 5. debug(msg, *args, **kwargs) 

118 

119 The `msg` can contain string formatting. An example of logging at the `ERROR` 

120 level 

121 using string formating is: 

122 

123 >>> tf.get_logger().error("The value %d is invalid.", 3) 

124 

125 You can also specify the logging verbosity. In this case, the 

126 WARN level log will not be emitted: 

127 

128 >>> tf.get_logger().setLevel(ERROR) 

129 >>> tf.get_logger().warn("This is a warning.") 

130 """ 

131 global _logger 

132 

133 # Use double-checked locking to avoid taking lock unnecessarily. 

134 if _logger: 

135 return _logger 

136 

137 _logger_lock.acquire() 

138 

139 try: 

140 if _logger: 

141 return _logger 

142 

143 # Scope the TensorFlow logger to not conflict with users' loggers. 

144 logger = _logging.getLogger('tensorflow') 

145 

146 # Override findCaller on the logger to skip internal helper functions 

147 logger.findCaller = _logger_find_caller 

148 

149 # Don't further configure the TensorFlow logger if the root logger is 

150 # already configured. This prevents double logging in those cases. 

151 if not _logging.getLogger().handlers: 

152 # Determine whether we are in an interactive environment 

153 _interactive = False 

154 try: 

155 # This is only defined in interactive shells. 

156 if _sys.ps1: 

157 _interactive = True 

158 except AttributeError: 

159 # Even now, we may be in an interactive shell with `python -i`. 

160 _interactive = _sys.flags.interactive 

161 

162 # If we are in an interactive environment (like Jupyter), set loglevel 

163 # to INFO and pipe the output to stdout. 

164 if _interactive: 

165 logger.setLevel(INFO) 

166 _logging_target = _sys.stdout 

167 else: 

168 _logging_target = _sys.stderr 

169 

170 # Add the output handler. 

171 _handler = _logging.StreamHandler(_logging_target) 

172 _handler.setFormatter(_logging.Formatter(_logging.BASIC_FORMAT, None)) 

173 logger.addHandler(_handler) 

174 

175 _logger = logger 

176 return _logger 

177 

178 finally: 

179 _logger_lock.release() 

180 

181 

182@tf_export(v1=['logging.log']) 

183def log(level, msg, *args, **kwargs): 

184 get_logger().log(level, msg, *args, **kwargs) 

185 

186 

187@tf_export(v1=['logging.debug']) 

188def debug(msg, *args, **kwargs): 

189 get_logger().debug(msg, *args, **kwargs) 

190 

191 

192@tf_export(v1=['logging.error']) 

193def error(msg, *args, **kwargs): 

194 get_logger().error(msg, *args, **kwargs) 

195 

196 

197@tf_export(v1=['logging.fatal']) 

198def fatal(msg, *args, **kwargs): 

199 get_logger().fatal(msg, *args, **kwargs) 

200 

201 

202@tf_export(v1=['logging.info']) 

203def info(msg, *args, **kwargs): 

204 get_logger().info(msg, *args, **kwargs) 

205 

206 

207@tf_export(v1=['logging.warn']) 

208def warn(msg, *args, **kwargs): 

209 get_logger().warning(msg, *args, **kwargs) 

210 

211 

212@tf_export(v1=['logging.warning']) 

213def warning(msg, *args, **kwargs): 

214 get_logger().warning(msg, *args, **kwargs) 

215 

216 

217_level_names = { 

218 FATAL: 'FATAL', 

219 ERROR: 'ERROR', 

220 WARN: 'WARN', 

221 INFO: 'INFO', 

222 DEBUG: 'DEBUG', 

223} 

224 

225# Mask to convert integer thread ids to unsigned quantities for logging 

226# purposes 

227_THREAD_ID_MASK = 2 * _sys.maxsize + 1 

228 

229_log_prefix = None # later set to google2_log_prefix 

230 

231# Counter to keep track of number of log entries per token. 

232_log_counter_per_token = {} 

233 

234 

235@tf_export(v1=['logging.TaskLevelStatusMessage']) 

236def TaskLevelStatusMessage(msg): 

237 error(msg) 

238 

239 

240@tf_export(v1=['logging.flush']) 

241def flush(): 

242 raise NotImplementedError() 

243 

244 

245# Code below is taken from pyglib/logging 

246@tf_export(v1=['logging.vlog']) 

247def vlog(level, msg, *args, **kwargs): 

248 get_logger().log(level, msg, *args, **kwargs) 

249 

250 

251def _GetNextLogCountPerToken(token): 

252 """Wrapper for _log_counter_per_token. 

253 

254 Args: 

255 token: The token for which to look up the count. 

256 

257 Returns: 

258 The number of times this function has been called with 

259 *token* as an argument (starting at 0) 

260 """ 

261 global _log_counter_per_token # pylint: disable=global-variable-not-assigned 

262 _log_counter_per_token[token] = 1 + _log_counter_per_token.get(token, -1) 

263 return _log_counter_per_token[token] 

264 

265 

266@tf_export(v1=['logging.log_every_n']) 

267def log_every_n(level, msg, n, *args): 

268 """Log 'msg % args' at level 'level' once per 'n' times. 

269 

270 Logs the 1st call, (N+1)st call, (2N+1)st call, etc. 

271 Not threadsafe. 

272 

273 Args: 

274 level: The level at which to log. 

275 msg: The message to be logged. 

276 n: The number of times this should be called before it is logged. 

277 *args: The args to be substituted into the msg. 

278 """ 

279 count = _GetNextLogCountPerToken(_GetFileAndLine()) 

280 log_if(level, msg, not (count % n), *args) 

281 

282 

283@tf_export(v1=['logging.log_first_n']) 

284def log_first_n(level, msg, n, *args): # pylint: disable=g-bad-name 

285 """Log 'msg % args' at level 'level' only first 'n' times. 

286 

287 Not threadsafe. 

288 

289 Args: 

290 level: The level at which to log. 

291 msg: The message to be logged. 

292 n: The number of times this should be called before it is logged. 

293 *args: The args to be substituted into the msg. 

294 """ 

295 count = _GetNextLogCountPerToken(_GetFileAndLine()) 

296 log_if(level, msg, count < n, *args) 

297 

298 

299@tf_export(v1=['logging.log_if']) 

300def log_if(level, msg, condition, *args): 

301 """Log 'msg % args' at level 'level' only if condition is fulfilled.""" 

302 if condition: 

303 vlog(level, msg, *args) 

304 

305 

306def _GetFileAndLine(): 

307 """Returns (filename, linenumber) for the stack frame.""" 

308 code, f = _get_caller() 

309 if not code: 

310 return ('<unknown>', 0) 

311 return (code.co_filename, f.f_lineno) 

312 

313 

314def google2_log_prefix(level, timestamp=None, file_and_line=None): 

315 """Assemble a logline prefix using the google2 format.""" 

316 # pylint: disable=global-variable-not-assigned 

317 global _level_names 

318 # pylint: enable=global-variable-not-assigned 

319 

320 # Record current time 

321 now = timestamp or _time.time() 

322 now_tuple = _time.localtime(now) 

323 now_microsecond = int(1e6 * (now % 1.0)) 

324 

325 (filename, line) = file_and_line or _GetFileAndLine() 

326 basename = _os.path.basename(filename) 

327 

328 # Severity string 

329 severity = 'I' 

330 if level in _level_names: 

331 severity = _level_names[level][0] 

332 

333 s = '%c%02d%02d %02d:%02d:%02d.%06d %5d %s:%d] ' % ( 

334 severity, 

335 now_tuple[1], # month 

336 now_tuple[2], # day 

337 now_tuple[3], # hour 

338 now_tuple[4], # min 

339 now_tuple[5], # sec 

340 now_microsecond, 

341 _get_thread_id(), 

342 basename, 

343 line) 

344 

345 return s 

346 

347 

348@tf_export(v1=['logging.get_verbosity']) 

349def get_verbosity(): 

350 """Return how much logging output will be produced.""" 

351 return get_logger().getEffectiveLevel() 

352 

353 

354@tf_export(v1=['logging.set_verbosity']) 

355def set_verbosity(v): 

356 """Sets the threshold for what messages will be logged.""" 

357 get_logger().setLevel(v) 

358 

359 

360def _get_thread_id(): 

361 """Get id of current thread, suitable for logging as an unsigned quantity.""" 

362 thread_id = _thread.get_ident() 

363 return thread_id & _THREAD_ID_MASK 

364 

365 

366_log_prefix = google2_log_prefix 

367 

368tf_export(v1=['logging.DEBUG']).export_constant(__name__, 'DEBUG') 

369tf_export(v1=['logging.ERROR']).export_constant(__name__, 'ERROR') 

370tf_export(v1=['logging.FATAL']).export_constant(__name__, 'FATAL') 

371tf_export(v1=['logging.INFO']).export_constant(__name__, 'INFO') 

372tf_export(v1=['logging.WARN']).export_constant(__name__, 'WARN')