log_common.py 4.36 KiB
#!/usr/bin/env python
# encoding: utf-8
"""
$Id: adl_common.py 1931 2014-03-17 18:43:26Z kathys $
Purpose: Common routines for ADL XDR handling and ancillary data caching.
Requires: adl_asc
Created Oct 2011 by R.K.Garcia <rayg@ssec.wisc.edu>
Copyright (c) 2011 University of Wisconsin Regents.
Licensed under GNU GPLv3.
"""
import os, sys, logging
import basics
import __main__
# from cffi import FFI
# ffi = FFI()
ffi = None
LOG = logging.getLogger(__name__)
logging_configured = False
# ref: http://stackoverflow.com/questions/1383254/logging-streamhandler-and-standard-streams
class SingleLevelFilter(logging.Filter):
def __init__(self, passlevels, reject):
self.passlevels = set(passlevels)
self.reject = reject
def filter(self, record):
if self.reject:
return (record.levelno not in self.passlevels)
else:
return (record.levelno in self.passlevels)
def configure_logging(level=logging.WARNING, FILE=None):
"""
route logging INFO and DEBUG to stdout instead of stderr, affects entire application
"""
global logging_configured
# create a formatter to be used across everything
# fm = logging.Formatter('%(levelname)s:%(name)s:%(msg)s') # [%(filename)s:%(lineno)d]')
fm = logging.Formatter('(%(levelname)s):%(filename)s:%(funcName)s:%(lineno)d:%(message)s')
rootLogger = logging.getLogger()
# set up the default logging
if logging_configured == False:
logging_configured = True
# create a handler which routes info and debug to stdout with std formatting
h1 = logging.StreamHandler(sys.stdout)
f1 = SingleLevelFilter([logging.INFO, logging.DEBUG], False)
h1.addFilter(f1)
h1.setFormatter(fm)
# create a second stream handler which sends everything else to stderr with std formatting
h2 = logging.StreamHandler(sys.stderr)
f2 = SingleLevelFilter([logging.INFO, logging.DEBUG], True)
h2.addFilter(f2)
h2.setFormatter(fm)
rootLogger.addHandler(h1)
rootLogger.addHandler(h2)
h3 = None
if FILE is not None:
work_dir = os.path.dirname(FILE)
basics.check_and_convert_path("WORKDIR", work_dir, check_write=True)
h3 = logging.FileHandler(filename=FILE)
# f3 = SingleLevelFilter([logging.INFO, logging.DEBUG], False)
# h3.addFilter(f3)
h3.setFormatter(fm)
rootLogger.addHandler(h3)
rootLogger.setLevel(level)
def status_line(status):
"""
Put out a special status line
"""
LOG.info("\n ( " + status + " )\n")
def log_from_C(in_type, in_msg):
type = ffi.string(in_type)
emsg = ffi.string(in_msg)
msg = emsg.decode()
if type == b'INFO':
LOG.info(msg)
elif type == b'WARN':
LOG.warn(msg)
elif type == b'ERROR':
LOG.error(msg)
elif type == b'DEBUG':
LOG.debug(msg)
else:
LOG.error('Bad TYPE %s %s' % (type, msg))
return int(0)
log_callback = None
log_lib = None
def C_log_support(ffi_in):
"""
Initalizer for C callbacks
"""
global ffi
global log_callback
global log_lib
ffi = ffi_in
ffi.cdef("""
void log_from_C(char * type, char * message );
void set_log( int (*callback)(char*,char*) );
int LOG_info( char *message);
int LOG_warn( char *message);
int LOG_debug( char *message);
int LOG_error( char *message);
""")
log_lib = ffi.dlopen("liblog_common_cb.so")
log_callback = ffi.callback("int(char*,char *)", log_from_C)
log_lib.set_log(log_callback)
def _test_logging():
LOG.debug('debug message')
LOG.info('info message')
LOG.warning('warning message')
LOG.error('error message')
LOG.critical('critical message')
def test_C_callbacks():
message = 'error'
arg1 = ffi.new("char[]", message)
log_lib.LOG_error(arg1)
message = 'warn'
arg2 = ffi.new("char[]", message)
log_lib.LOG_warn(arg2)
message = 'info'
arg3 = ffi.new("char[]", message)
log_lib.LOG_info(arg3)
message = 'debug'
arg4 = ffi.new("char[]", message)
log_lib.LOG_debug(arg4)
configure_logging()
if __name__ == '__main__':
# logging.basicConfig(level=logging.DEBUG) we don't want basicConfig anymore
configure_logging(level=logging.DEBUG, FILE="./testlog.log")
_test_logging()
C_log_support()
# test_C_callbacks()