Source code for pisa.utils.log

"""
This module sets up the logging system by looking for a "logging.json"
configuration file. It will search (in this order) the local directory, $PISA
and finally the package resources. The loggers found in there will be lifted
to the module namespace.

Currently, we have three loggers
* logging: generic for what is going on  (typically: `opening file x` or
  `doing this now` messages)
* physics: for any physics output that might be interesting
  (`have x many events`, `the flux is ...`)
* tprofile: for how much time it takes to run some step (in the format of
  `time : start bla`, `time : stop bla`)
"""


from __future__ import absolute_import

import enum
import json
import logging as logging_module
import logging.config as logging_config
from os import environ
from os.path import expanduser, expandvars, isfile, join
from pkg_resources import resource_stream


__all__ = ['Levels', 'logging', 'physics', 'tprofile', 'set_verbosity']

__author__ = 'S. Boeser'

__license__ = '''Copyright (c) 2014-2017, The IceCube Collaboration

 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.'''


[docs] class Levels(enum.IntEnum): """ Logging levels / int values we use in PISA in `set_verbosity` (and typically from the command line, where -v/-vv/-vvv/etc. are used) """ FATAL = -2 ERROR = -1 WARN = 0 # default if NO "-v(vvv...)" are passed at command line INFO = 1 # pass "-v" at command line DEBUG = 2 # pass "-vv" at command line TRACE = 3 # pass "-vvv" at command line
def initialize_logging(): """Intializing PISA logging""" # Add a trace level logging_module.TRACE = 5 logging_module.addLevelName(logging_module.TRACE, 'TRACE') def trace(self, message, *args, **kws): """Trace-level logging""" self.log(logging_module.TRACE, message, *args, **kws) logging_module.Logger.trace = trace logging_module.RootLogger.trace = trace logging_module.trace = logging_module.root.trace # Get the logging configuration logf = None try: if 'PISA_RESOURCES' in environ: for path in environ['PISA_RESOURCES'].split(':'): fpath = join(expanduser(expandvars(path)), 'settings/logging/logging.json') if isfile(fpath): logf = open(fpath, 'r') break if logf is None: resource_spec = ('pisa_examples', 'resources/settings/logging/logging.json') logf = resource_stream(*resource_spec) if logf is None: raise ValueError('Could not find "logging.json" in PISA_RESOURCES' ' or in pisa_examples/resources.') logconfig = json.load(logf) finally: if logf is not None: logf.close() # Setup the logging system with this config logging_config.dictConfig(logconfig) thandler = logging_module.StreamHandler() tformatter = logging_module.Formatter( fmt=logconfig['formatters']['profile']['format'] ) thandler.setFormatter(tformatter) # Capture warnings logging_module.captureWarnings(True) _logging = logging_module.getLogger('pisa') _physics = logging_module.getLogger('pisa.physics') _tprofile = logging_module.getLogger('pisa.tprofile') # TODO: removed following line due to duplicate logging messages. Probably # should fix this in a better manner... #_tprofile.handlers = [thandler] return _logging, _physics, _tprofile
[docs] def set_verbosity(verbosity): """Set the verbosity level for the root logger Verbosity should be an integer with the levels defined by `pisa.utils.log.Levels` enum.""" # Ignore if no verbosity is given if verbosity is None: return # mapping from our verbisoity int Levels to those of logging module levels_mapping = { int(Levels[n]): getattr(logging_module, n) for n in [l.name for l in Levels] } if verbosity not in levels_mapping: raise ValueError( '`verbosity` specified is %s but must be one of %s.' %(verbosity, list(levels_mapping.keys())) ) # Overwrite the root logger with the verbosity level logging.setLevel(levels_mapping[verbosity]) tprofile.setLevel(levels_mapping[verbosity])
# Make the loggers public logging, physics, tprofile = initialize_logging() # pylint: disable=invalid-name