def run_logger(logger, config, stderr_filename=None, stderr_data_server=None, log_level=logging.INFO): """Run a logger, sending its stderr to a cached data server if so indicated logger - Name of logger config - Config dict stderr_filename - If not None, send stderr to this file. stderr_data_server - If not None, host:port of cached data server to send stderr messages to. log_level - Level at which logger should be logging (e.g logging.WARNING, logging.INFO, etc. """ # Reset logging to its freshly-imported state reload(logging) stderr_handler = RotatingFileHandler(stderr_filename, maxBytes=STDERR_MAX_BYTES, backupCount=STDERR_BACKUP_COUNT) logging.basicConfig(handlers=[stderr_handler], level=log_level, format=DEFAULT_LOGGING_FORMAT) if stderr_data_server: field_name = 'stderr:logger:' + logger cds_writer = ComposedWriter( transforms=ToDASRecordTransform(data_id='stderr', field_name=field_name), writers=CachedDataWriter(data_server=stderr_data_server)) logging.getLogger().addHandler(StdErrLoggingHandler(cds_writer)) # Set the name of the process for ps config_name = config.get('name', 'no_name') setproctitle('openrvdas/server/logger_runner.py:' + config_name) logging.info(f'Starting logger {logger} config {config_name}') try: if config_is_runnable(config): listener = ListenerFromLoggerConfig(config=config) try: listener.run() except KeyboardInterrupt: logging.warning(f'Received quit for {config_name}') except Exception as e: logging.fatal(e) # Allow a moment for stderr_writers to finish up time.sleep(0.25)
def _kwargs_from_config(self, config_dict): """Parse a kwargs from a JSON string, making exceptions for keywords 'readers', 'transforms', and 'writers' as internal class references.""" if not config_dict: return {} if not type(config_dict) is dict: raise ValueError( 'Received config dict of type "%s" (instead of dict)' % type(config_dict)) # First we pull out the 'stderr_writers' spec as a special case so # that we can catch and properly route stderr output from # parsing/creation of the other keyword args. kwargs = {} stderr_writers_spec = config_dict.get('stderr_writers', None) if stderr_writers_spec: stderr_writers = self._class_kwargs_from_config( stderr_writers_spec) logging.getLogger().addHandler( StdErrLoggingHandler(stderr_writers)) # We've already initialized the logger for stderr_writers, so # *don't* pass that arg on, or things will get logged twice. del config_dict['stderr_writers'] for key, value in config_dict.items(): # Declaration of readers, transforms and writers. Note that the # singular "reader" is a special case for TimeoutReader that # takes a single reader. if key in ['readers', 'reader', 'transforms', 'writers', 'writer']: if not value: raise ValueError( 'declaration of "%s" in class has no kwargs?!?' % key) kwargs[key] = self._class_kwargs_from_config(value) # If value is a simple float/int/string/etc, just add to keywords elif value is None or type(value) in [ float, bool, int, str, list, dict ]: kwargs[key] = value # Else what do we have? else: raise ValueError('unexpected key:value in configuration: ' '{}: {}'.format(key, str(value))) return kwargs
name='openrvdas_data_server', target=run_data_server, args=(args.data_server_websocket, args.data_server_back_seconds, args.data_server_cleanup_interval, args.data_server_interval), daemon=True) data_server_proc.start() ############################ # If we do have a data server, add a handler that will echo all # logger_manager stderr output to it if args.data_server_websocket: stderr_writer = ComposedWriter( transforms=ToDASRecordTransform(field_name='stderr:logger_manager'), writers=[CachedDataWriter(data_server=args.data_server_websocket)]) logging.getLogger().addHandler(StdErrLoggingHandler(stderr_writer, parse_to_json=True)) ############################ # Instantiate API - a Are we using an in-memory store or Django # database as our backing store? Do our imports conditionally, so # they don't actually have to have Django if they're not using it. if args.database == 'django': from django_gui.django_server_api import DjangoServerAPI api = DjangoServerAPI() elif args.database == 'memory': from server.in_memory_server_api import InMemoryServerAPI api = InMemoryServerAPI() elif args.database == 'hapi': from hapi.hapi_server_api import HapiServerAPI api = HapiServerAPI() else:
action='count', help='Increase output verbosity') args = parser.parse_args() # Set logging verbosity LOGGING_FORMAT = '%(asctime)-15s %(filename)s:%(lineno)d %(message)s' LOG_LEVELS = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG} log_level = LOG_LEVELS[min(args.verbosity, max(LOG_LEVELS))] logging.basicConfig(format=LOGGING_FORMAT) logging.getLogger().setLevel(log_level) if args.stderr_file: stderr_writer = [ TextFileWriter(filename=args.stderr_file, split_by_date=True) ] logging.getLogger().addHandler(StdErrLoggingHandler(stderr_writer)) logging.info('Starting CachedDataServer') server = CachedDataServer(port=args.port, interval=args.interval, back_seconds=args.back_seconds, max_records=args.max_records, cleanup_interval=args.cleanup_interval, disk_cache=args.disk_cache) # Only create reader(s) if they've given us a network to read from; # otherwise, count on data coming from websocket publish # connections. if args.udp: readers = [] # Readers may either be just a port (to listen for broadcast) or
args=(args.data_server_websocket, args.data_server_back_seconds, args.data_server_cleanup_interval, args.data_server_interval), daemon=True) data_server_proc.start() ############################ # If we do have a data server, add a handler that will echo all # logger_manager stderr output to it if args.data_server_websocket: stderr_writer = ComposedWriter( transforms=ToDASRecordTransform( field_name='stderr:logger_manager'), writers=[CachedDataWriter(data_server=args.data_server_websocket)]) logging.getLogger().addHandler( StdErrLoggingHandler(stderr_writer, parse_to_json=True)) ############################ # Instantiate API - a Are we using an in-memory store or Django # database as our backing store? Do our imports conditionally, so # they don't actually have to have Django if they're not using it. if args.database == 'django': from django_gui.django_server_api import DjangoServerAPI api = DjangoServerAPI() elif args.database == 'memory': from server.in_memory_server_api import InMemoryServerAPI api = InMemoryServerAPI() elif args.database == 'hapi': from hapi.hapi_server_api import HapiServerAPI api = HapiServerAPI() else: