# Copyright 2017 The Abseil Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Abseil Python logging module implemented on top of standard logging.

Simple usage:

    from absl import logging

    logging.info('Interesting Stuff')
    logging.info('Interesting Stuff with Arguments: %d', 42)

    logging.set_verbosity(logging.INFO)
    logging.log(logging.DEBUG, 'This will *not* be printed')
    logging.set_verbosity(logging.DEBUG)
    logging.log(logging.DEBUG, 'This will be printed')

    logging.warn('Worrying Stuff')
    logging.error('Alarming Stuff')
    logging.fatal('AAAAHHHHH!!!!')  # Process exits.

Usage note: Do not pre-format the strings in your program code.
Instead, let the logging module perform argument interpolation.
This saves cycles because strings that don't need to be printed
are never formatted.  Note that this module does not attempt to
interpolate arguments when no arguments are given.  In other words

    logging.info('Interesting Stuff: %s')

does not raise an exception because logging.info() has only one
argument, the message string.

"Lazy" evaluation for debugging:

If you do something like this:
    logging.debug('Thing: %s', thing.ExpensiveOp())
then the ExpensiveOp will be evaluated even if nothing
is printed to the log. To avoid this, use the level_debug() function:
  if logging.level_debug():
    logging.debug('Thing: %s', thing.ExpensiveOp())

Notes on Unicode:

The log output is encoded as UTF-8.  Don't pass data in other encodings in
bytes() instances -- instead pass unicode string instances when you need to
(for both the format string and arguments).

Note on critical and fatal:
Standard logging module defines fatal as an alias to critical, but it's not
documented, and it does NOT actually terminate the program.
This module only defines fatal but not critical, and it DOES terminate the
program.

The differences in behavior are historical and unfortunate.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import getpass
import io
import itertools
import logging
import os
import socket
import struct
import sys
import time
import traceback

from absl import flags
from absl.logging import converter
import six

if six.PY2:
  import thread as _thread_lib  # For .get_ident().
else:
  import threading as _thread_lib  # For .get_ident().


FLAGS = flags.FLAGS


# Logging levels.
FATAL = converter.ABSL_FATAL
ERROR = converter.ABSL_ERROR
WARN = converter.ABSL_WARN
WARNING = converter.ABSL_WARN
INFO = converter.ABSL_INFO
DEBUG = converter.ABSL_DEBUG

# Regex to match/parse log line prefixes.
ABSL_LOGGING_PREFIX_REGEX = (
    r'^(?P<severity>[IWEF])'
    r'(?P<month>\d\d)(?P<day>\d\d) '
    r'(?P<hour>\d\d):(?P<minute>\d\d):(?P<second>\d\d)'
    r'\.(?P<microsecond>\d\d\d\d\d\d) +'
    r'(?P<thread_id>-?\d+) '
    r'(?P<filename>[a-zA-Z<][\w._<>-]+):(?P<line>\d+)')


# Mask to convert integer thread ids to unsigned quantities for logging purposes
_THREAD_ID_MASK = 2 ** (struct.calcsize('L') * 8) - 1

# Extra property set on the LogRecord created by ABSLLogger when its level is
# CRITICAL/FATAL.
_ABSL_LOG_FATAL = '_absl_log_fatal'
# Extra prefix added to the log message when a non-absl logger logs a
# CRITICAL/FATAL message.
_CRITICAL_PREFIX = 'CRITICAL - '

# Used by findCaller to skip callers from */logging/__init__.py.
_LOGGING_FILE_PREFIX = os.path.join('logging', '__init__.')

# The ABSL logger instance, initialized in _initialize().
_absl_logger = None
# The ABSL handler instance, initialized in _initialize().
_absl_handler = None



_CPP_NAME_TO_LEVELS = {
    'debug': '0',  # Abseil C++ has no DEBUG level, mapping it to INFO here.
    'info': '0',
    'warning': '1',
    'warn': '1',
    'error': '2',
    'fatal': '3'
}

_CPP_LEVEL_TO_NAMES = {
    '0': 'info',
    '1': 'warn',
    '2': 'error',
    '3': 'fatal',
}


class _VerbosityFlag(flags.Flag):
  """Flag class for -v/--verbosity."""

  def __init__(self, *args, **kwargs):
    super(_VerbosityFlag, self).__init__(
        flags.IntegerParser(),
        flags.ArgumentSerializer(),
        *args, **kwargs)

  @property
  def value(self):
    return self._value

  @value.setter
  def value(self, v):
    self._value = v
    self._update_logging_levels()

  def _update_logging_levels(self):
    """Updates absl logging levels to the current verbosity."""
    if not _absl_logger:
      return

    if self._value <= converter.ABSL_DEBUG:
      standard_verbosity = converter.absl_to_standard(self._value)
    else:
      # --verbosity is set to higher than 1 for vlog.
      standard_verbosity = logging.DEBUG - (self._value - 1)

    # Also update root level when absl_handler is used.
    if _absl_handler in logging.root.handlers:
      logging.root.setLevel(standard_verbosity)


class _StderrthresholdFlag(flags.Flag):
  """Flag class for --stderrthreshold."""

  def __init__(self, *args, **kwargs):
    super(_StderrthresholdFlag, self).__init__(
        flags.ArgumentParser(),
        flags.ArgumentSerializer(),
        *args, **kwargs)

  @property
  def value(self):
    return self._value

  @value.setter
  def value(self, v):
    if v in _CPP_LEVEL_TO_NAMES:
      # --stderrthreshold also accepts numberic strings whose values are
      # Abseil C++ log levels.
      cpp_value = int(v)
      v = _CPP_LEVEL_TO_NAMES[v]  # Normalize to strings.
    elif v.lower() in _CPP_NAME_TO_LEVELS:
      v = v.lower()
      cpp_value = int(_CPP_NAME_TO_LEVELS[v])
    else:
      raise ValueError(
          '--stderrthreshold must be one of (case-insensitive) '
          "'debug', 'info', 'warn', 'warning', 'error', 'fatal', "
          "or '0', '1', '2', '3', not '%s'" % v)

    self._value = v




flags.DEFINE_boolean('logtostderr',
                     False,
                     'Should only log to stderr?', allow_override_cpp=True)
flags.DEFINE_boolean('alsologtostderr',
                     False,
                     'also log to stderr?', allow_override_cpp=True)
flags.DEFINE_string('log_dir',
                    os.getenv('TEST_TMPDIR', ''),
                    'directory to write logfiles into',
                    allow_override_cpp=True)
flags.DEFINE_flag(_VerbosityFlag(
    'verbosity', -1,
    'Logging verbosity level. Messages logged at this level or lower will '
    'be included. Set to 1 for debug logging. If the flag was not set or '
    'supplied, the value will be changed from the default of -1 (warning) to '
    '0 (info) after flags are parsed.',
    short_name='v', allow_hide_cpp=True))
flags.DEFINE_flag(_StderrthresholdFlag(
    'stderrthreshold', 'fatal',
    'log messages at this level, or more severe, to stderr in'
    ' addition to the logfile.  Possible values are '
    "'debug', 'info', 'warn', 'error', and 'fatal'.  "
    'Obsoletes --alsologtostderr. Using --alsologtostderr '
    'cancels the effect of this flag. Please also note that '
    'this flag is subject to --verbosity and requires logfile'
    ' not be stderr.', allow_hide_cpp=True))
flags.DEFINE_boolean('showprefixforinfo', True,
                     'If False, do not prepend prefix to info messages '
                     'when it\'s logged to stderr, '
                     '--verbosity is set to INFO level, '
                     'and python logging is used.')


def get_verbosity():
  """Returns the logging verbosity."""
  return FLAGS['verbosity'].value


def set_verbosity(v):
  """Sets the logging verbosity.

  Causes all messages of level <= v to be logged,
  and all messages of level > v to be silently discarded.

  Args:
    v: int|str, the verbosity level as an integer or string. Legal string values
        are those that can be coerced to an integer as well as case-insensitive
        'debug', 'info', 'warn', 'error', and 'fatal'.
  """
  try:
    new_level = int(v)
  except ValueError:
    new_level = converter.ABSL_NAMES[v.upper()]
  FLAGS.verbosity = new_level


def set_stderrthreshold(s):
  """Sets the stderr threshold to the value passed in.

  Args:
    s: str|int, valid strings values are case-insensitive 'debug',
        'info', 'warn', 'error', and 'fatal'; valid integer values are
        logging.DEBUG|INFO|WARN|ERROR|FATAL.

  Raises:
      ValueError: Raised when s is an invalid value.
  """
  if s in converter.ABSL_LEVELS:
    FLAGS.stderrthreshold = converter.ABSL_LEVELS[s]
  elif isinstance(s, str) and s.upper() in converter.ABSL_NAMES:
    FLAGS.stderrthreshold = s
  else:
    raise ValueError(
        'set_stderrthreshold only accepts integer absl logging level '
        'from -3 to 1, or case-insensitive string values '
        "'debug', 'info', 'warn', 'error', and 'fatal'. "
        'But found "{}" ({}).'.format(s, type(s)))


def fatal(msg, *args, **kwargs):
  """Logs a fatal message."""
  log(FATAL, msg, *args, **kwargs)


def error(msg, *args, **kwargs):
  """Logs an error message."""
  log(ERROR, msg, *args, **kwargs)


def warning(msg, *args, **kwargs):
  """Logs a warning message."""
  log(WARN, msg, *args, **kwargs)


warn = warning


def info(msg, *args, **kwargs):
  """Logs an info message."""
  log(INFO, msg, *args, **kwargs)


def debug(msg, *args, **kwargs):
  """Logs a debug message."""
  log(DEBUG, msg, *args, **kwargs)


def exception(msg, *args):
  """Logs an exception, with traceback and message."""
  error(msg, *args, exc_info=True)


# Counter to keep track of number of log entries per token.
_log_counter_per_token = {}


def _get_next_log_count_per_token(token):
  """Wrapper for _log_counter_per_token. Thread-safe.

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

  Returns:
    The number of times this function has been called with
    *token* as an argument (starting at 0).
  """
  # Can't use a defaultdict because defaultdict isn't atomic, whereas
  # setdefault is.
  return next(_log_counter_per_token.setdefault(token, itertools.count()))


def log_every_n(level, msg, n, *args):
  """Logs 'msg % args' at level 'level' once per 'n' times.

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

  Args:
    level: int, the absl logging level at which to log.
    msg: str, the message to be logged.
    n: int, the number of times this should be called before it is logged.
    *args: The args to be substitued into the msg.
  """
  count = _get_next_log_count_per_token(get_absl_logger().findCaller())
  log_if(level, msg, not (count % n), *args)


def log_first_n(level, msg, n, *args):
  """Logs 'msg % args' at level 'level' only first 'n' times.

  Not threadsafe.

  Args:
    level: int, the absl logging level at which to log.
    msg: str, the message to be logged.
    n: int, the maximal number of times the message is logged.
    *args: The args to be substitued into the msg.
  """
  count = _get_next_log_count_per_token(get_absl_logger().findCaller())
  log_if(level, msg, count < n, *args)


def log_if(level, msg, condition, *args):
  """Logs 'msg % args' at level 'level' only if condition is fulfilled."""
  if condition:
    log(level, msg, *args)


def log(level, msg, *args, **kwargs):
  """Logs 'msg % args' at absl logging level 'level'.

  If no args are given just print msg, ignoring any interpolation specifiers.

  Args:
    level: int, the absl logging level at which to log the message
        (logging.DEBUG|INFO|WARN|ERROR|FATAL). While some C++ verbose logging
        level constants are also supported, callers should prefer explicit
        logging.vlog() calls for such purpose.

    msg: str, the message to be logged.
    *args: The args to be substitued into the msg.
    **kwargs: May contain exc_info to add exception traceback to message.
  """
  if level > converter.ABSL_DEBUG:
    # Even though this function supports level that is greater than 1, users
    # should use logging.vlog instead for such cases.
    # Treat this as vlog, 1 is equivalent to DEBUG.
    standard_level = converter.STANDARD_DEBUG - (level - 1)
  else:
    if level < converter.ABSL_FATAL:
      level = converter.ABSL_FATAL
    standard_level = converter.absl_to_standard(level)

  _absl_logger.log(standard_level, msg, *args, **kwargs)


def vlog(level, msg, *args, **kwargs):
  """Log 'msg % args' at C++ vlog level 'level'.

  Args:
    level: int, the C++ verbose logging level at which to log the message,
        e.g. 1, 2, 3, 4... While absl level constants are also supported,
        callers should prefer logging.log|debug|info|... calls for such purpose.
    msg: str, the message to be logged.
    *args: The args to be substitued into the msg.
    **kwargs: May contain exc_info to add exception traceback to message.
  """
  log(level, msg, *args, **kwargs)


def flush():
  """Flushes all log files."""
  get_absl_handler().flush()


def level_debug():
  """Returns True if debug logging is turned on."""
  return get_verbosity() >= DEBUG


def level_info():
  """Returns True if info logging is turned on."""
  return get_verbosity() >= INFO


def level_warn():
  """Returns True if warning logging is turned on."""
  return get_verbosity() >= WARN


def level_error():
  """Returns True if error logging is turned on."""
  return get_verbosity() >= ERROR


def find_log_dir_and_names(program_name=None, log_dir=None):
  """Computes the directory and filename prefix for log file.

  Args:
    program_name: str|None, the filename part of the path to the program that
        is running without its extension.  e.g: if your program is called
        'usr/bin/foobar.py' this method should probably be called with
        program_name='foobar' However, this is just a convention, you can
        pass in any string you want, and it will be used as part of the
        log filename. If you don't pass in anything, the default behavior
        is as described in the example.  In python standard logging mode,
        the program_name will be prepended with py_ if it is the program_name
        argument is omitted.
    log_dir: str|None, the desired log directory.

  Returns:
    (log_dir, file_prefix, symlink_prefix)
  """
  if not program_name:
    # Strip the extension (foobar.par becomes foobar, and
    # fubar.py becomes fubar). We do this so that the log
    # file names are similar to C++ log file names.
    program_name = os.path.splitext(os.path.basename(sys.argv[0]))[0]

    # Prepend py_ to files so that python code gets a unique file, and
    # so that C++ libraries do not try to write to the same log files as us.
    program_name = 'py_%s' % program_name

  actual_log_dir = find_log_dir(log_dir=log_dir)

  username = getpass.getuser()
  hostname = socket.gethostname()
  file_prefix = '%s.%s.%s.log' % (program_name, hostname, username)

  return actual_log_dir, file_prefix, program_name


def find_log_dir(log_dir=None):
  """Returns the most suitable directory to put log files into.

  Args:
    log_dir: str|None, if specified, the logfile(s) will be created in that
        directory.  Otherwise if the --log_dir command-line flag is provided,
        the logfile will be created in that directory.  Otherwise the logfile
        will be created in a standard location.
  """
  # Get a list of possible log dirs (will try to use them in order).
  if log_dir:
    # log_dir was explicitly specified as an arg, so use it and it alone.
    dirs = [log_dir]
  elif FLAGS['log_dir'].value:
    # log_dir flag was provided, so use it and it alone (this mimics the
    # behavior of the same flag in logging.cc).
    dirs = [FLAGS['log_dir'].value]
  else:
    dirs = ['/tmp/', './']

  # Find the first usable log dir.
  for d in dirs:
    if os.path.isdir(d) and os.access(d, os.W_OK):
      return d
  _absl_logger.fatal("Can't find a writable directory for logs, tried %s", dirs)


def get_absl_log_prefix(record):
  """Returns the absl log prefix for the log record.

  Args:
    record: logging.LogRecord, the record to get prefix for.
  """
  created_tuple = time.localtime(record.created)
  created_microsecond = int(record.created % 1.0 * 1e6)

  critical_prefix = ''
  level = record.levelno
  if _is_non_absl_fatal_record(record):
    # When the level is FATAL, but not logged from absl, lower the level so
    # it's treated as ERROR.
    level = logging.ERROR
    critical_prefix = _CRITICAL_PREFIX
  severity = converter.get_initial_for_level(level)

  return '%c%02d%02d %02d:%02d:%02d.%06d %5d %s:%d] %s' % (
      severity,
      created_tuple.tm_mon,
      created_tuple.tm_mday,
      created_tuple.tm_hour,
      created_tuple.tm_min,
      created_tuple.tm_sec,
      created_microsecond,
      _get_thread_id(),
      record.filename,
      record.lineno,
      critical_prefix)


def _is_non_absl_fatal_record(log_record):
  return (log_record.levelno >= logging.FATAL and
          not log_record.__dict__.get(_ABSL_LOG_FATAL, False))


def _is_absl_fatal_record(log_record):
  return (log_record.levelno >= logging.FATAL and
          log_record.__dict__.get(_ABSL_LOG_FATAL, False))


# Indicates if we still need to warn about pre-init logs going to stderr.
_warn_preinit_stderr = True


class PythonHandler(logging.StreamHandler):
  """The handler class used by Abseil Python logging implementation."""

  def __init__(self, stream=None, formatter=None):
    super(PythonHandler, self).__init__(stream)
    self.setFormatter(formatter or PythonFormatter())

  def start_logging_to_file(self, program_name=None, log_dir=None):
    """Starts logging messages to files instead of standard error."""
    FLAGS.logtostderr = 0

    actual_log_dir, file_prefix, symlink_prefix = find_log_dir_and_names(
        program_name=program_name, log_dir=log_dir)

    basename = '%s.INFO.%s.%d' % (
        file_prefix,
        time.strftime('%Y%m%d-%H%M%S', time.localtime(time.time())),
        os.getpid())
    filename = os.path.join(actual_log_dir, basename)

    if six.PY2:
      self.stream = open(filename, 'a')
    else:
      self.stream = open(filename, 'a', encoding='utf-8')

    # os.symlink is not available on Windows Python 2.
    if getattr(os, 'symlink', None):
      # Create a symlink to the log file with a canonical name.
      symlink = os.path.join(actual_log_dir, symlink_prefix + '.INFO')
      try:
        if os.path.islink(symlink):
          os.unlink(symlink)
        os.symlink(os.path.basename(filename), symlink)
      except EnvironmentError:
        # If it fails, we're sad but it's no error.  Commonly, this
        # fails because the symlink was created by another user and so
        # we can't modify it
        pass

  def use_absl_log_file(self, program_name=None, log_dir=None):
    """Conditionally logs to files, based on --logtostderr."""
    if FLAGS['logtostderr'].value:
      self.stream = sys.stderr
    else:
      self.start_logging_to_file(program_name=program_name, log_dir=log_dir)

  def flush(self):
    """Flushes all log files."""
    self.acquire()
    try:
      self.stream.flush()
    except (EnvironmentError, ValueError):
      # A ValueError is thrown if we try to flush a closed file.
      pass
    finally:
      self.release()

  def _log_to_stderr(self, record):
    """Emits the record to stderr.

    This temporarily sets the handler stream to stderr, calls
    StreamHandler.emit, then reverts the stream back.

    Args:
      record: logging.LogRecord, the record to log.
    """
    # emit() is protected by a lock in logging.Handler, so we don't need to
    # protect here again.
    old_stream = self.stream
    self.stream = sys.stderr
    try:
      super(PythonHandler, self).emit(record)
    finally:
      self.stream = old_stream

  def emit(self, record):
    """Prints a record out to some streams.

    If FLAGS.logtostderr is set, it will print to sys.stderr ONLY.
    If FLAGS.alsologtostderr is set, it will print to sys.stderr.
    If FLAGS.logtostderr is not set, it will log to the stream
      associated with the current thread.

    Args:
      record: logging.LogRecord, the record to emit.
    """
    # People occasionally call logging functions at import time before
    # our flags may have even been defined yet, let alone even parsed, as we
    # rely on the C++ side to define some flags for us and app init to
    # deal with parsing.  Match the C++ library behavior of notify and emit
    # such messages to stderr.  It encourages people to clean-up and does
    # not hide the message.
    level = record.levelno
    if not FLAGS.is_parsed():  # Also implies "before flag has been defined".
      global _warn_preinit_stderr
      if _warn_preinit_stderr:
        sys.stderr.write(
            'WARNING: Logging before flag parsing goes to stderr.\n')
        _warn_preinit_stderr = False
      self._log_to_stderr(record)
    elif FLAGS['logtostderr'].value:
      self._log_to_stderr(record)
    else:
      super(PythonHandler, self).emit(record)
      stderr_threshold = converter.string_to_standard(
          FLAGS['stderrthreshold'].value)
      if ((FLAGS['alsologtostderr'].value or level >= stderr_threshold) and
          self.stream != sys.stderr):
        self._log_to_stderr(record)
    # Die when the record is created from ABSLLogger and level is FATAL.
    if _is_absl_fatal_record(record):
      self.flush()  # Flush the log before dying.

      # In threaded python, sys.exit() from a non-main thread only
      # exits the thread in question.
      os.abort()

  def close(self):
    """Closes the stream to which we are writing."""
    self.acquire()
    try:
      self.flush()
      try:
        # Do not close the stream if it's sys.stderr|stdout. They may be
        # redirected or overridden to files, which should be managed by users
        # explicitly.
        if self.stream not in (sys.stderr, sys.stdout) and (
            not hasattr(self.stream, 'isatty') or not self.stream.isatty()):
          self.stream.close()
      except ValueError:
        # A ValueError is thrown if we try to run isatty() on a closed file.
        pass
      super(PythonHandler, self).close()
    finally:
      self.release()


class ABSLHandler(logging.Handler):
  """Abseil Python logging module's log handler."""

  def __init__(self, python_logging_formatter):
    super(ABSLHandler, self).__init__()

    self._python_handler = PythonHandler(formatter=python_logging_formatter)
    self.activate_python_handler()

  def format(self, record):
    return self._current_handler.format(record)

  def setFormatter(self, fmt):
    self._current_handler.setFormatter(fmt)

  def emit(self, record):
    self._current_handler.emit(record)

  def flush(self):
    self._current_handler.flush()

  def close(self):
    super(ABSLHandler, self).close()
    self._current_handler.close()

  @property
  def python_handler(self):
    return self._python_handler

  def activate_python_handler(self):
    """Uses the Python logging handler as the current logging handler."""
    self._current_handler = self._python_handler

  def use_absl_log_file(self, program_name=None, log_dir=None):
    self._current_handler.use_absl_log_file(program_name, log_dir)

  def start_logging_to_file(self, program_name=None, log_dir=None):
    self._current_handler.start_logging_to_file(program_name, log_dir)


class PythonFormatter(logging.Formatter):
  """Formatter class used by PythonHandler."""

  def format(self, record):
    """Appends the message from the record to the results of the prefix.

    Args:
      record: logging.LogRecord, the record to be formatted.

    Returns:
      The formatted string representing the record.
    """
    if (not FLAGS['showprefixforinfo'].value and
        FLAGS['verbosity'].value == converter.ABSL_INFO and
        record.levelno == logging.INFO and
        _absl_handler.python_handler.stream == sys.stderr):
      prefix = ''
    else:
      prefix = get_absl_log_prefix(record)
    return prefix + super(PythonFormatter, self).format(record)


class ABSLLogger(logging.getLoggerClass()):
  """A logger that will create LogRecords while skipping some stack frames.

  This class maintains an internal list of filenames and method names
  for use when determining who called the currently execuing stack
  frame.  Any method names from specific source files are skipped when
  walking backwards through the stack.

  Client code should use the register_frame_to_skip method to let the
  ABSLLogger know which method from which file should be
  excluded from the walk backwards through the stack.
  """
  _frames_to_skip = set()

  def findCaller(self, stack_info=False):
    """Finds the frame of the calling method on the stack.

    This method skips any frames registered with the
    ABSLLogger and any methods from this file, and whatever
    method is currently being used to generate the prefix for the log
    line.  Then it returns the file name, line nubmer, and method name
    of the calling method.

    Args:
      stack_info: bool, when using Python 3 and True, include the stack trace as
          the fourth item returned instead of None.

    Returns:
      (filename, lineno, methodname[, sinfo]) of the calling method.
    """
    f_to_skip = ABSLLogger._frames_to_skip
    frame = logging.currentframe()

    while frame:
      code = frame.f_code
      if (_LOGGING_FILE_PREFIX not in code.co_filename and
          (code.co_filename, code.co_name) not in f_to_skip):
        if six.PY2:
          return (code.co_filename, frame.f_lineno, code.co_name)
        else:
          sinfo = None
          if stack_info:
            out = io.StringIO()
            out.write('Stack (most recent call last):\n')
            traceback.print_stack(frame, file=out)
            sinfo = out.getvalue().rstrip('\n')
            out.close()
          return (code.co_filename, frame.f_lineno, code.co_name, sinfo)
      frame = frame.f_back

  def critical(self, msg, *args, **kwargs):
    """Logs 'msg % args' with severity 'CRITICAL'."""
    self.log(logging.CRITICAL, msg, *args, **kwargs)

  def fatal(self, msg, *args, **kwargs):
    """Logs 'msg % args' with severity 'FATAL'."""
    self.log(logging.FATAL, msg, *args, **kwargs)

  def error(self, msg, *args, **kwargs):
    """Logs 'msg % args' with severity 'ERROR'."""
    self.log(logging.ERROR, msg, *args, **kwargs)

  def warn(self, msg, *args, **kwargs):
    """Logs 'msg % args' with severity 'WARN'."""
    self.log(logging.WARN, msg, *args, **kwargs)

  def warning(self, msg, *args, **kwargs):
    """Logs 'msg % args' with severity 'WARNING'."""
    self.log(logging.WARNING, msg, *args, **kwargs)

  def info(self, msg, *args, **kwargs):
    """Logs 'msg % args' with severity 'INFO'."""
    self.log(logging.INFO, msg, *args, **kwargs)

  def debug(self, msg, *args, **kwargs):
    """Logs 'msg % args' with severity 'DEBUG'."""
    self.log(logging.DEBUG, msg, *args, **kwargs)

  def log(self, level, msg, *args, **kwargs):
    """Logs a message at a cetain level substituting in the supplied arguments.

    This method behaves differently in python and c++ modes.

    Args:
      level: int, the standard logging level at which to log the message.
      msg: str, the text of the message to log.
      *args: The arguments to substitute in the message.
      **kwargs: The keyword arguments to substitute in the message.
    """
    if level >= logging.FATAL:
      # Add property to the LogRecord created by this logger.
      # This will be used by the ABSLHandler to determine whether it should
      # treat CRITICAL/FATAL logs as really FATAL.
      extra = kwargs.setdefault('extra', {})
      extra[_ABSL_LOG_FATAL] = True
    super(ABSLLogger, self).log(level, msg, *args, **kwargs)

  def handle(self, record):
    """Calls handlers without checking Logger.disabled.

    Non-root loggers are set to disabled after setup with logging.config if
    it's not explicitly specified. Historically, absl logging will not be
    disabled by that. To maintaining this behavior, this function skips
    checking the Logger.disabled bit.

    This logger can still be disabled by adding a filter that filters out
    everything.

    Args:
      record: logging.LogRecord, the record to handle.
    """
    if self.filter(record):
      self.callHandlers(record)

  @classmethod
  def register_frame_to_skip(cls, file_name, function_name):
    """Registers a function name to skip when walking the stack.

    The ABSLLogger sometimes skips method calls on the stack
    to make the log messages meaningful in their appropriate context.
    This method registers a function from a particluar file as one
    which should be skipped.

    Args:
      file_name: str, the name of the file that contains the function.
      function_name: str, the name of the function to skip.
    """
    cls._frames_to_skip.add((file_name, function_name))


def _get_thread_id():
  """Gets id of current thread, suitable for logging as an unsigned quantity.

  If pywrapbase is linked, returns GetTID() for the thread ID to be
  consistent with C++ logging.  Otherwise, returns the numeric thread id.
  The quantities are made unsigned by masking with 2*sys.maxint + 1.

  Returns:
    Thread ID unique to this process (unsigned)
  """
  thread_id = _thread_lib.get_ident()
  return thread_id & _THREAD_ID_MASK


def get_absl_logger():
  """Returns the absl logger instance."""
  return _absl_logger


def get_absl_handler():
  """Returns the absl handler instance."""
  return _absl_handler


def use_python_logging(quiet=False):
  """Uses the python implementation of the logging code.

  Args:
    quiet: No logging message about switching logging type.
  """
  get_absl_handler().activate_python_handler()
  if not quiet:
    info('Restoring pure python logging')


def use_absl_handler():
  """Uses the ABSL logging handler for logging if not yet configured.

  The absl handler is already attached to root if there are no other handlers
  attached when importing this module.

  Otherwise, this method is called in app.run() so absl handler is used.
  """
  absl_handler = get_absl_handler()
  if absl_handler not in logging.root.handlers:
    logging.root.addHandler(absl_handler)
    FLAGS['verbosity']._update_logging_levels()  # pylint: disable=protected-access


def _initialize():
  """Initializes loggers and handlers."""
  global _absl_logger, _absl_handler

  if _absl_logger:
    return

  original_logger_class = logging.getLoggerClass()
  logging.setLoggerClass(ABSLLogger)
  _absl_logger = logging.getLogger('absl')
  logging.setLoggerClass(original_logger_class)

  python_logging_formatter = PythonFormatter()
  _absl_handler = ABSLHandler(python_logging_formatter)

  # The absl handler logs to stderr by default. To prevent double logging to
  # stderr, the following code tries its best to remove other handlers that emit
  # to stderr. Those handlers are most commonly added when logging.info/debug is
  # called before importing this module.
  handlers = [
      h for h in logging.root.handlers
      if isinstance(h, logging.StreamHandler) and h.stream == sys.stderr]
  for h in handlers:
    logging.root.removeHandler(h)

  # The absl handler will always be attached to root, not the absl logger.
  if not logging.root.handlers:
    # Attach the absl handler at import time when there are no other handlers.
    # Otherwise it means users have explicitly configured logging, and the absl
    # handler will only be attached later in app.run(). For App Engine apps,
    # the absl handler is not used.
    logging.root.addHandler(_absl_handler)


# Initialize absl logger.
# Must be called after logging flags in this module are defined.
_initialize()
