Source code for neurokernel.tools.logging

#!/usr/bin/env python

"""
Logging tools.
"""

import copy
import sys
import traceback

import twiggy

# Try to import various dependencies here so that they can be serialized
# and transmitted to mpi_backend during model execution:
try:
    import mpi4py.MPI
except ImportError:
    pass
try:
    import neurokernel.tools.zmq
except ImportError:
    pass
try:
    import neurokernel.tools.mpi
except ImportError:
    pass

[docs]def log_exception(type, value, tb, logger=twiggy.log, multiline=False): """ Log the specified exception data using twiggy. Parameters ---------- value, tb : object Parameters expected by traceback.print_exception. logger : twiggy.logger.Logger Logger to use. twiggy.log is assumed by default. multiline : bool If True, print exception using multiple log lines. """ if multiline: for x in traceback.format_exception(type, value, tb)[1:]: for y in x.strip('\n ').split('\n'): logger.error(y) else: msg = '|'.join([': '.join([y.strip() for y in x.strip('\n ').split('\n')]) for x in \ traceback.format_exception(type, value, tb)[1:]]) logger.error('Uncaught exception: %s' % str(msg))
[docs]def set_excepthook(logger, multiline=False): """ Set the exception hook to use the specified logger. Parameters ---------- logger : twiggy.logger.Logger Configured logger. multiline : bool If True, log exception messages on multiple lines. """ sys.excepthook = \ lambda type, value, tb: log_exception(type, value, tb, logger, multiline)
[docs]def setup_logger(name='', level=twiggy.levels.DEBUG, fmt=twiggy.formats.line_format, fmt_name=('{0:%s}' % 10).format, screen=None, file_name=None, mpi_comm=None, zmq_addr=None, log_exceptions=True, multiline=False): """ Setup a twiggy logger. Parameters ---------- name : str Logger name. level : twiggy.levels.LogLevel Logging level. fmt : twiggy.formats.LineFormat Logging formatter class instance. fmt_name : function Function with one parameter that formats the message name. screen : bool Create output stream handler to the screen if True. file_name : str Create output handler to specified file. mpi_comm : mpi4py.MPI.Intracomm If not None, use MPI I/O with the specified communicator for output file handler. Ignored if the `file_name` parameter is not specified. zmq_addr : str ZeroMQ socket address. log_exceptions : bool If True, exception messages are written to the logger. multiline : bool If True, log exception messages on multiple lines. Returns ------- logger : twiggy.logger.Logger Configured logger. Bug --- To use the ZeroMQ output class with multiprocessing, it must be added as an emitter within each process. """ fmt = copy.copy(fmt) fmt.conversion.delete('name') # Apply name format to the value (i.e., the name), not the key (i.e., the # field name "name"): fmt.conversion.add('name', str, lambda k, v: fmt_name(v)) if file_name: if mpi_comm: if 'mpi4py.MPI' not in sys.modules: raise ValueError('mpi4py not available') if not isinstance(mpi_comm, mpi4py.MPI.Intracomm): raise ValueError('mpi_comm must be an instance of ' 'mpi4py.MPI.Intracomm') if 'neurokernel.tools.mpi' not in sys.modules: raise ValueError('neurokernel.tools.mpi not available') file_output = \ neurokernel.tools.mpi.MPIOutput(file_name, fmt, mpi_comm) else: file_output = \ twiggy.outputs.FileOutput(file_name, fmt, 'w') twiggy.add_emitters(('file', level, None, file_output)) if screen: screen_output = \ twiggy.outputs.StreamOutput(fmt, stream=sys.stdout) twiggy.add_emitters(('screen', level, None, screen_output)) if zmq_addr: if 'neurokernel.tools.zmq' not in sys.modules: raise ValueError('neurokernel.tools.zmq not available') zmq_output = neurokernel.tools.zmq.ZMQOutput(zmq_addr, fmt) twiggy.add_emitters(('zmq', level, None, zmq_output)) logger = twiggy.log.name(fmt_name(name)) if log_exceptions: set_excepthook(logger, multiline) return logger