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
« 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# ==============================================================================
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
33from tensorflow.python.util.tf_export import tf_export
35# Don't use this directly. Use get_logger() instead.
36_logger = None
37_logger_lock = threading.Lock()
40def error_log(error_msg, level=ERROR):
41 """Empty helper method."""
42 del error_msg, level
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
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:
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:
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)'
93@tf_export('get_logger')
94def get_logger():
95 """Return TF logger instance.
97 Returns:
98 An instance of the Python logging library Logger.
100 See Python documentation (https://docs.python.org/3/library/logging.html)
101 for detailed API. Below is only a summary.
103 The logger has 5 levels of logging from the most serious to the least:
105 1. FATAL
106 2. ERROR
107 3. WARN
108 4. INFO
109 5. DEBUG
111 The logger has the following methods, based on these logging levels:
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)
119 The `msg` can contain string formatting. An example of logging at the `ERROR`
120 level
121 using string formating is:
123 >>> tf.get_logger().error("The value %d is invalid.", 3)
125 You can also specify the logging verbosity. In this case, the
126 WARN level log will not be emitted:
128 >>> tf.get_logger().setLevel(ERROR)
129 >>> tf.get_logger().warn("This is a warning.")
130 """
131 global _logger
133 # Use double-checked locking to avoid taking lock unnecessarily.
134 if _logger:
135 return _logger
137 _logger_lock.acquire()
139 try:
140 if _logger:
141 return _logger
143 # Scope the TensorFlow logger to not conflict with users' loggers.
144 logger = _logging.getLogger('tensorflow')
146 # Override findCaller on the logger to skip internal helper functions
147 logger.findCaller = _logger_find_caller
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
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
170 # Add the output handler.
171 _handler = _logging.StreamHandler(_logging_target)
172 _handler.setFormatter(_logging.Formatter(_logging.BASIC_FORMAT, None))
173 logger.addHandler(_handler)
175 _logger = logger
176 return _logger
178 finally:
179 _logger_lock.release()
182@tf_export(v1=['logging.log'])
183def log(level, msg, *args, **kwargs):
184 get_logger().log(level, msg, *args, **kwargs)
187@tf_export(v1=['logging.debug'])
188def debug(msg, *args, **kwargs):
189 get_logger().debug(msg, *args, **kwargs)
192@tf_export(v1=['logging.error'])
193def error(msg, *args, **kwargs):
194 get_logger().error(msg, *args, **kwargs)
197@tf_export(v1=['logging.fatal'])
198def fatal(msg, *args, **kwargs):
199 get_logger().fatal(msg, *args, **kwargs)
202@tf_export(v1=['logging.info'])
203def info(msg, *args, **kwargs):
204 get_logger().info(msg, *args, **kwargs)
207@tf_export(v1=['logging.warn'])
208def warn(msg, *args, **kwargs):
209 get_logger().warning(msg, *args, **kwargs)
212@tf_export(v1=['logging.warning'])
213def warning(msg, *args, **kwargs):
214 get_logger().warning(msg, *args, **kwargs)
217_level_names = {
218 FATAL: 'FATAL',
219 ERROR: 'ERROR',
220 WARN: 'WARN',
221 INFO: 'INFO',
222 DEBUG: 'DEBUG',
223}
225# Mask to convert integer thread ids to unsigned quantities for logging
226# purposes
227_THREAD_ID_MASK = 2 * _sys.maxsize + 1
229_log_prefix = None # later set to google2_log_prefix
231# Counter to keep track of number of log entries per token.
232_log_counter_per_token = {}
235@tf_export(v1=['logging.TaskLevelStatusMessage'])
236def TaskLevelStatusMessage(msg):
237 error(msg)
240@tf_export(v1=['logging.flush'])
241def flush():
242 raise NotImplementedError()
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)
251def _GetNextLogCountPerToken(token):
252 """Wrapper for _log_counter_per_token.
254 Args:
255 token: The token for which to look up the count.
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]
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.
270 Logs the 1st call, (N+1)st call, (2N+1)st call, etc.
271 Not threadsafe.
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)
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.
287 Not threadsafe.
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)
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)
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)
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
320 # Record current time
321 now = timestamp or _time.time()
322 now_tuple = _time.localtime(now)
323 now_microsecond = int(1e6 * (now % 1.0))
325 (filename, line) = file_and_line or _GetFileAndLine()
326 basename = _os.path.basename(filename)
328 # Severity string
329 severity = 'I'
330 if level in _level_names:
331 severity = _level_names[level][0]
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)
345 return s
348@tf_export(v1=['logging.get_verbosity'])
349def get_verbosity():
350 """Return how much logging output will be produced."""
351 return get_logger().getEffectiveLevel()
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)
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
366_log_prefix = google2_log_prefix
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')