r"""
    Overwrites utool print functions to use a logger

    CommandLine:
        python -m utool.util_logging --test-start_logging:0
        python -m utool.util_logging --test-start_logging:1

    Example0:
        >>> # DISABLE_DOCTEST
        >>> import sys
        >>> sys.argv.append('--verb-logging')
        >>> import utool as ut
        >>> ut.start_logging()
        >>> ut.util_logging._utool_print()('hello world')
        >>> ut.util_logging._utool_write()('writing1')
        >>> ut.util_logging._utool_write()('writing2\n')
        >>> ut.util_logging._utool_write()('writing3')
        >>> ut.util_logging._utool_flush()()
        >>> handler = ut.util_logging.__UTOOL_ROOT_LOGGER__.handlers[0]
        >>> current_log_fpath = handler.stream.name
        >>> current_log_text = ut.read_from(current_log_fpath)
        >>> print('current_log_text =\n%s' % (current_log_text,))
        >>> assert current_log_text.find('hello world') > 0, 'cant hello world'
        >>> assert current_log_text.find('writing1writing2') > 0, 'cant find writing1writing2'
        >>> assert current_log_text.find('writing3') > 0, 'cant find writing3'

    Example1:
        >>> # DISABLE_DOCTEST
        >>> # Ensure that progress is logged
        >>> import sys
        >>> sys.argv.append('--verb-logging')
        >>> import utool as ut
        >>> ut.start_logging()
        >>> [x for x in  ut.ProgressIter(range(0, 1000), freq=4)]
        >>> handler = ut.util_logging.__UTOOL_ROOT_LOGGER__.handlers[0]
        >>> current_log_fpath = handler.stream.name
        >>> current_log_text = ut.read_from(current_log_fpath)
        >>> assert current_log_text.find('rate') > 0, 'progress was not logged'
        >>> print(current_log_text)

def start_logging(log_fpath=None, mode='a', appname='default', log_dir=None):
    r"""
    Overwrites utool print functions to use a logger

    CommandLine:
        python -m utool.util_logging --test-start_logging:0
        python -m utool.util_logging --test-start_logging:1

    Example0:
        >>> # DISABLE_DOCTEST
        >>> import sys
        >>> sys.argv.append('--verb-logging')
        >>> import utool as ut
        >>> ut.start_logging()
        >>> ut.util_logging._utool_print()('hello world')
        >>> ut.util_logging._utool_write()('writing1')
        >>> ut.util_logging._utool_write()('writing2\n')
        >>> ut.util_logging._utool_write()('writing3')
        >>> ut.util_logging._utool_flush()()
        >>> handler = ut.util_logging.__UTOOL_ROOT_LOGGER__.handlers[0]
        >>> current_log_fpath = handler.stream.name
        >>> current_log_text = ut.read_from(current_log_fpath)
        >>> print('current_log_text =\n%s' % (current_log_text,))
        >>> assert current_log_text.find('hello world') > 0, 'cant hello world'
        >>> assert current_log_text.find('writing1writing2') > 0, 'cant find writing1writing2'
        >>> assert current_log_text.find('writing3') > 0, 'cant find writing3'

    Example1:
        >>> # DISABLE_DOCTEST
        >>> # Ensure that progress is logged
        >>> import sys
        >>> sys.argv.append('--verb-logging')
        >>> import utool as ut
        >>> ut.start_logging()
        >>> [x for x in  ut.ProgressIter(range(0, 1000), freq=4)]
        >>> handler = ut.util_logging.__UTOOL_ROOT_LOGGER__.handlers[0]
        >>> current_log_fpath = handler.stream.name
        >>> current_log_text = ut.read_from(current_log_fpath)
        >>> assert current_log_text.find('rate') > 0, 'progress was not logged'
        >>> print(current_log_text)
    """
    global __UTOOL_ROOT_LOGGER__
    global __UTOOL_PRINT__
    global __UTOOL_WRITE__
    global __UTOOL_FLUSH__
    global __CURRENT_LOG_FPATH__
    if LOGGING_VERBOSE:
        print('[utool] start_logging()')
    # FIXME: The test for doctest may not work

    if __UTOOL_ROOT_LOGGER__ is None and __IN_MAIN_PROCESS__ and not __inside_doctest():
        if LOGGING_VERBOSE:
            print('[utool] start_logging()... rootcheck OK')
        #logging.config.dictConfig(LOGGING)
        if log_fpath is None:
            log_fpath = get_log_fpath(num='next', appname=appname, log_dir=log_dir)
        __CURRENT_LOG_FPATH__ = log_fpath
        # Print what is about to happen
        if VERBOSE or LOGGING_VERBOSE:
            startmsg = ('logging to log_fpath=%r' % log_fpath)
            _utool_print()(startmsg)
        # Create root logger
        __UTOOL_ROOT_LOGGER__ = logging.getLogger('root')
        __UTOOL_ROOT_LOGGER__.setLevel('DEBUG')
        # create file handler which logs even debug messages
        #fh = logging.handlers.WatchedFileHandler(log_fpath)
        logfile_handler = logging.FileHandler(log_fpath, mode=mode)
        #stdout_handler = logging.StreamHandler(__UTOOL_STDOUT__)
        stdout_handler = CustomStreamHandler(__UTOOL_STDOUT__)
        stdout_handler.terminator = ''
        # http://stackoverflow.com/questions/7168790/suppress-newline-in-python-logging-module
        #stdout_handler.terminator = ''
        add_logging_handler(logfile_handler, format_='file')
        add_logging_handler(stdout_handler, format_='stdout')
        __UTOOL_ROOT_LOGGER__.propagate = False
        __UTOOL_ROOT_LOGGER__.setLevel(logging.DEBUG)
        # Overwrite utool functions with the logging functions

        def utool_flush(*args):
            """ flushes whatever is in the current utool write buffer """
            # Flushes only the stdout handler
            stdout_handler.flush()
            #__UTOOL_ROOT_LOGGER__.flush()
            #global __UTOOL_WRITE_BUFFER__
            #if len(__UTOOL_WRITE_BUFFER__) > 0:
            #    msg = ''.join(__UTOOL_WRITE_BUFFER__)
            #    #sys.stdout.write('FLUSHING %r\n' % (len(__UTOOL_WRITE_BUFFER__)))
            #    __UTOOL_WRITE_BUFFER__ = []
            #    return __UTOOL_ROOT_LOGGER__.info(msg)
            #__PYTHON_FLUSH__()

        def utool_write(*args):
            """ writes to current utool logs and to sys.stdout.write """
            #global __UTOOL_WRITE_BUFFER__
            #sys.stdout.write('WRITEING\n')
            msg = ', '.join(map(six.text_type, args))
            #__UTOOL_WRITE_BUFFER__.append(msg)
            __UTOOL_ROOT_LOGGER__.info(msg)
            #if msg.endswith('\n'):
            #    # Flush on newline, and remove newline
            #    __UTOOL_WRITE_BUFFER__[-1] = __UTOOL_WRITE_BUFFER__[-1][:-1]
            #    utool_flush()
            #elif len(__UTOOL_WRITE_BUFFER__) > 32:
            #    # Flush if buffer is too large
            #    utool_flush()

        if not PRINT_ALL_CALLERS:
            def utool_print(*args):
                """ standard utool print function """
                #sys.stdout.write('PRINT\n')
                endline = '\n'
                try:
                    msg = ', '.join(map(six.text_type, args))
                    return  __UTOOL_ROOT_LOGGER__.info(msg + endline)
                except UnicodeDecodeError:
                    new_msg = ', '.join(map(meta_util_six.ensure_unicode, args))
                    #print(new_msg)
                    return  __UTOOL_ROOT_LOGGER__.info(new_msg + endline)
        else:
            def utool_print(*args):
                """ debugging utool print function """
                import utool as ut
                utool_flush()
                endline = '\n'
                __UTOOL_ROOT_LOGGER__.info('\n\n----------')
                __UTOOL_ROOT_LOGGER__.info(ut.get_caller_name(range(0, 20)))
                return  __UTOOL_ROOT_LOGGER__.info(', '.join(map(six.text_type, args)) + endline)

        def utool_printdbg(*args):
            """ DRPRICATE standard utool print debug function """
            return  __UTOOL_ROOT_LOGGER__.debug(', '.join(map(six.text_type, args)))
        # overwrite the utool printers
        __UTOOL_WRITE__    = utool_write
        __UTOOL_FLUSH__    = utool_flush
        __UTOOL_PRINT__    = utool_print
        # Test out our shiney new logger
        if VERBOSE or LOGGING_VERBOSE:
            __UTOOL_PRINT__('<__LOG_START__>')
            __UTOOL_PRINT__(startmsg)
    else:
        if LOGGING_VERBOSE:
            print('[utool] start_logging()... FAILED TO START')
            print('DEBUG INFO')
            print('__inside_doctest() = %r' % (__inside_doctest(),))
            print('__IN_MAIN_PROCESS__ = %r' % (__IN_MAIN_PROCESS__,))
            print('__UTOOL_ROOT_LOGGER__ = %r' % (__UTOOL_ROOT_LOGGER__,))