Support disabling log colours and dates

For usecases such as a pure-syslog, allow disabling of dates or colours
in the log messages (separately).
This commit is contained in:
Joshua Boniface 2019-07-10 21:39:25 -04:00
parent 0d513fea4d
commit 58f4222ee7
3 changed files with 104 additions and 57 deletions

View File

@ -122,6 +122,10 @@ pvc:
file_logging: True
# stdout_logging: Enable or disable logging to stdout (i.e. journald)
stdout_logging: True
# log_colours: Enable or disable ANSI colours in log output
log_colours: True
# log_dates: Enable or disable date strings in log output
log_dates: True
# log_keepalives: Enable or disable keepalive logging
log_keepalives: True
# log_keepalive_cluster_details: Enable or disable node status logging during keepalive

View File

@ -143,6 +143,8 @@ def readConfig(pvcd_config_file, myhostname):
'console_log_directory': o_config['pvc']['system']['configuration']['directories']['console_log_directory'],
'file_logging': o_config['pvc']['system']['configuration']['logging']['file_logging'],
'stdout_logging': o_config['pvc']['system']['configuration']['logging']['stdout_logging'],
'log_colours': o_config['pvc']['system']['configuration']['logging']['log_colours'],
'log_dates': o_config['pvc']['system']['configuration']['logging']['log_dates'],
'log_keepalives': o_config['pvc']['system']['configuration']['logging']['log_keepalives'],
'log_keepalive_cluster_details': o_config['pvc']['system']['configuration']['logging']['log_keepalive_cluster_details'],
'log_keepalive_storage_details': o_config['pvc']['system']['configuration']['logging']['log_keepalive_storage_details'],
@ -323,6 +325,24 @@ logger.out(' OS: {}'.format(staticdata[2]))
logger.out(' Kernel: {}'.format(staticdata[1]))
logger.out('Starting pvcd on host {}'.format(myfqdn), state='s')
# Define some colours for future messages if applicable
if config['log_colours']:
fmt_end = logger.fmt_end
fmt_bold = logger.fmt_bold
fmt_blue = logger.fmt_blue
fmt_green = logger.fmt_green
fmt_yellow = logger.fmt_yellow
fmt_red = logger.fmt_red
fmt_purple = logger.fmt_purple
else:
fmt_end = ''
fmt_bold = ''
fmt_blue = ''
fmt_green = ''
fmt_yellow = ''
fmt_red = ''
fmt_purple = ''
###############################################################################
# PHASE 2a - Create local IP addresses for static networks
###############################################################################
@ -405,7 +425,7 @@ if myhostname in coordinator_nodes:
# We are indeed a coordinator host
config['daemon_mode'] = 'coordinator'
# Start the zookeeper service using systemctl
logger.out('Node is a ' + logger.fmt_blue + 'coordinator' + logger.fmt_end, state='i')
logger.out('Node is a ' + fmt_blue + 'coordinator' + fmt_end, state='i')
else:
config['daemon_mode'] = 'hypervisor'
@ -558,7 +578,7 @@ signal.signal(signal.SIGQUIT, term)
# Check if our node exists in Zookeeper, and create it if not
if zk_conn.exists('/nodes/{}'.format(myhostname)):
logger.out("Node is " + logger.fmt_green + "present" + logger.fmt_end + " in Zookeeper", state='i')
logger.out("Node is " + fmt_green + "present" + fmt_end + " in Zookeeper", state='i')
# Update static data just in case it's changed
zkhandler.writedata(zk_conn, {
'/nodes/{}/daemonstate'.format(myhostname): 'init',
@ -569,7 +589,7 @@ if zk_conn.exists('/nodes/{}'.format(myhostname)):
'/nodes/{}/ipmipassword'.format(myhostname): config['ipmi_password']
})
else:
logger.out("Node is " + logger.fmt_red + "absent" + logger.fmt_end + " in Zookeeper; adding new node", state='i')
logger.out("Node is " + fmt_red + "absent" + fmt_end + " in Zookeeper; adding new node", state='i')
keepalive_time = int(time.time())
zkhandler.writedata(zk_conn, {
'/nodes/{}'.format(myhostname): config['daemon_mode'],
@ -602,7 +622,7 @@ except kazoo.exceptions.NoNodeError:
current_primary = 'none'
if current_primary and current_primary != 'none':
logger.out('Current primary node is {}{}{}.'.format(logger.fmt_blue, current_primary, logger.fmt_end), state='i')
logger.out('Current primary node is {}{}{}.'.format(fmt_blue, current_primary, fmt_end), state='i')
else:
if config['daemon_mode'] == 'coordinator':
logger.out('No primary node found; creating with us as primary.', state='i')
@ -719,7 +739,7 @@ def update_nodes(new_node_list):
# Update and print new list
node_list = new_node_list
logger.out('{}Node list:{} {}'.format(logger.fmt_blue, logger.fmt_end, ' '.join(node_list)), state='i')
logger.out('{}Node list:{} {}'.format(fmt_blue, fmt_end, ' '.join(node_list)), state='i')
# Update node objects' list
for node in d_node:
@ -787,7 +807,7 @@ if enable_networking:
# Update and print new list
network_list = new_network_list
logger.out('{}Network list:{} {}'.format(logger.fmt_blue, logger.fmt_end, ' '.join(network_list)), state='i')
logger.out('{}Network list:{} {}'.format(fmt_blue, fmt_end, ' '.join(network_list)), state='i')
# Update node objects' list
for node in d_node:
@ -812,7 +832,7 @@ if enable_hypervisor:
# Update and print new list
domain_list = new_domain_list
logger.out('{}Domain list:{} {}'.format(logger.fmt_blue, logger.fmt_end, ' '.join(domain_list)), state='i')
logger.out('{}Domain list:{} {}'.format(fmt_blue, fmt_end, ' '.join(domain_list)), state='i')
# Update node objects' list
for node in d_node:
@ -843,7 +863,7 @@ if enable_storage:
# Update and print new list
osd_list = new_osd_list
logger.out('{}OSD list:{} {}'.format(logger.fmt_blue, logger.fmt_end, ' '.join(osd_list)), state='i')
logger.out('{}OSD list:{} {}'.format(fmt_blue, fmt_end, ' '.join(osd_list)), state='i')
# Pool objects
@zk_conn.ChildrenWatch('/ceph/pools')
@ -865,7 +885,7 @@ if enable_storage:
# Update and print new list
pool_list = new_pool_list
logger.out('{}Pool list:{} {}'.format(logger.fmt_blue, logger.fmt_end, ' '.join(pool_list)), state='i')
logger.out('{}Pool list:{} {}'.format(fmt_blue, fmt_end, ' '.join(pool_list)), state='i')
# Volume objects in each pool
for pool in pool_list:
@ -886,7 +906,7 @@ if enable_storage:
# Update and print new list
volume_list[pool] = new_volume_list
logger.out('{}Volume list [{pool}]:{} {plist}'.format(logger.fmt_blue, logger.fmt_end, pool=pool, plist=' '.join(volume_list[pool])), state='i')
logger.out('{}Volume list [{pool}]:{} {plist}'.format(fmt_blue, fmt_end, pool=pool, plist=' '.join(volume_list[pool])), state='i')
###############################################################################
# PHASE 9 - Run the daemon
@ -918,11 +938,11 @@ def update_zookeeper():
retcode, stdout, stderr = common.run_os_command('ceph health', timeout=1)
ceph_health = stdout.rstrip()
if 'HEALTH_OK' in ceph_health:
ceph_health_colour = logger.fmt_green
ceph_health_colour = fmt_green
elif 'HEALTH_WARN' in ceph_health:
ceph_health_colour = logger.fmt_yellow
ceph_health_colour = fmt_yellow
else:
ceph_health_colour = logger.fmt_red
ceph_health_colour = fmt_red
# Set ceph health information in zookeeper (primary only)
if this_node.router_state == 'primary':
@ -1218,9 +1238,9 @@ def update_zookeeper():
if config['log_keepalives']:
logger.out(
'{}{} keepalive{}'.format(
logger.fmt_purple,
fmt_purple,
myhostname,
logger.fmt_end
fmt_end
),
state='t'
)
@ -1232,8 +1252,8 @@ def update_zookeeper():
'{bold}Free memory [MiB]:{nofmt} {freemem} '
'{bold}Used memory [MiB]:{nofmt} {usedmem} '
'{bold}Load:{nofmt} {load}'.format(
bold=logger.fmt_bold,
nofmt=logger.fmt_end,
bold=fmt_bold,
nofmt=fmt_end,
domcount=this_node.domains_count,
freemem=this_node.memfree,
usedmem=this_node.memused,
@ -1248,9 +1268,9 @@ def update_zookeeper():
'{bold}Total OSDs:{nofmt} {total_osds} '
'{bold}Node OSDs:{nofmt} {node_osds} '
'{bold}Pools:{nofmt} {total_pools} '.format(
bold=logger.fmt_bold,
bold=fmt_bold,
health_colour=ceph_health_colour,
nofmt=logger.fmt_end,
nofmt=fmt_end,
health=ceph_health,
total_osds=len(osd_list),
node_osds=osds_this_node,

View File

@ -37,16 +37,42 @@ class Logger(object):
fmt_bold = '\033[1m'
fmt_end = '\033[0m'
last_colour = ''
last_prompt = ''
# Format maps
format_map_colourized = {
# Colourized formatting with chevron prompts (log_colours = True)
'o': { 'colour': fmt_green, 'prompt': '>>> ' },
'e': { 'colour': fmt_red, 'prompt': '>>> ' },
'w': { 'colour': fmt_yellow, 'prompt': '>>> ' },
't': { 'colour': fmt_purple, 'prompt': '>>> ' },
'i': { 'colour': fmt_blue, 'prompt': '>>> ' },
's': { 'colour': fmt_cyan, 'prompt': '>>> ' },
'x': { 'colour': last_colour, 'prompt': last_prompt }
}
format_map_textual = {
# Uncolourized formatting with text prompts (log_colours = False)
'o': { 'colour': '', 'prompt': 'ok: ' },
'e': { 'colour': '', 'prompt': 'failed: ' },
'w': { 'colour': '', 'prompt': 'warning: ' },
't': { 'colour': '', 'prompt': 'tick: ' },
'i': { 'colour': '', 'prompt': 'info: ' },
's': { 'colour': '', 'prompt': 'system: ' },
'x': { 'colour': '', 'prompt': last_prompt }
}
# Initialization of instance
def __init__(self, config):
self.config = config
if self.config['file_logging'] == 'True':
self.logfile = self.config['log_directory'] + '/pvc.log'
# We open the logfile for the duration of our session, but have a hup function
self.writer = open(self.logfile, 'a', buffering=1)
self.last_colour = self.fmt_cyan
else:
self.last_colour = ""
self.last_colour = ''
self.last_prompt = ''
# Provide a hup function to close and reopen the writer
def hup(self):
@ -54,49 +80,46 @@ class Logger(object):
self.writer = open(self.logfile, 'a', buffering=0)
# Output function
def out(self, message, state='', prefix=''):
def out(self, message, state=None, prefix=''):
# Get the date
if self.config['log_dates']:
date = '{} - '.format(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S.%f'))
endc = Logger.fmt_end
# Determine the formatting
# OK
if state == 'o':
colour = Logger.fmt_green
prompt = '>>> '
# Error
elif state == 'e':
colour = Logger.fmt_red
prompt = '>>> '
# Warning
elif state == 'w':
colour = Logger.fmt_yellow
prompt = '>>> '
# Tick
elif state == 't':
colour = Logger.fmt_purple
prompt = '>>> '
# Information
elif state == 'i':
colour = Logger.fmt_blue
prompt = '>>> '
# Startup
elif state == 's':
colour = Logger.fmt_cyan
prompt = '>>> '
# Continuation
else:
date = ''
colour = self.last_colour
prompt = '>>> '
# Append space to prefix
# Get the format map
if self.config['log_colours']:
format_map = self.format_map_colourized
endc = Logger.fmt_end
else:
format_map = self.format_map_textual
endc = ''
# Define an undefined state as 'x'; no date in these prompts
if not state:
state = 'x'
date = ''
# Get colour and prompt from the map
colour = format_map[state]['colour']
prompt = format_map[state]['prompt']
# Append space and separator to prefix
if prefix != '':
prefix = prefix + ' - '
# Assemble message string
message = colour + prompt + endc + date + prefix + message
# Log to stdout
if self.config['stdout_logging']:
print(message)
if self.config['file_logging'] == 'True':
# Log to file
if self.config['file_logging']:
self.writer.write(message + '\n')
# Set last message variables
self.last_colour = colour
self.last_prompt = prompt