Skip to content

Commit

Permalink
Move logger logic into Markdown formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
Benito Palacios Sanchez committed Nov 11, 2016
1 parent 8bdccdc commit f83d6e1
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 69 deletions.
20 changes: 20 additions & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Log Parser for RTI Connext.
#
# Copyright 2016 Real-Time Innovations, Inc.
#
# 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.
"""Package LogParser."""

__version__ = "1.2a2"
__license__ = "Apache"
__copyright__ = "Copyright 2016 Real-Time Innovations, Inc."
15 changes: 13 additions & 2 deletions src/devices/formatdevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,19 @@ def write_header(self, state):
"""Write the header if any."""
raise NotImplementedError("write_header not implemented")

def write_message(self, state):
"""Write the message."""
def write_message(self, content, state):
"""Write the message.
The content argument is a dictionary with at least 'description' item.
The optional items are:
+ kind: the kind or remark for the message.
+ timestamp: the timestamp of the message.
+ input_line: the current input line.
+ output_line: the current output line.
+ inout: [packets-only] 'in' if it's input packet, 'out' otherwise.
+ remote: [packets-only] the remote address of the sender/receiver.
+ entity: [packets-only] the local entity sending/receiving.
"""
raise NotImplementedError("write_message not implemented")

def write_configurations(self, state):
Expand Down
130 changes: 79 additions & 51 deletions src/devices/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,82 +16,104 @@
"""Logger functions.
The module contains functions to log the new messages.
The 'content' dictionary is defined in the FormatDevice class.
Functions:
+ log: Log the given message.
+ log_recv: Log a received packet.
+ log_send: Log a sent packet.
+ log_process: Log a processed packet.
+ log_cfg: Log a configuration message.
+ log_warning: Log a warning message.
+ log_error: Log an error.
+ countset_add_element: Add an element to the countset.
+ log: log the given message.
+ log_recv: log a received packet.
+ log_send: log a sent packet.
+ log_process: log a processed packet.
+ log_cfg: log a configuration message.
+ log_warning: log a warning message.
+ log_error: log an error.
+ countset_add_element: add an element to the countset.
+ dict_regex_search: apply the regex over all the fields of the dictionary.
Constants:
+ COLORS: Colors to use in log messages.
+ COLORS: ANSI colors to use in log messages.
+ KIND_TO_COLOR: conversion between log kind and ANSI color
"""


COLORS = {'HEADER': '\033[95m', 'BLUE': '\033[94m', 'OK': '\033[92m',
'WARNING': '\033[93m', 'FAIL': '\033[91m', 'ENDC': '\033[0m',
'BOLD': '\033[1m', 'UNDERLINE': '\033[4m'}
COLORS = {
'RED': '\033[91m',
'GREEN': '\033[92m',
'YELLOW': '\033[93m',
'BLUE': '\033[94m',
'MAGENTA': '\033[95m',
'BOLD': '\033[1m',
'FAINT': '\033[2m',
'ITALIC': '\033[3m',
'UNDERLINE': '\033[4m',
'END': '\033[0m',
}

KIND_TO_COLOR = {
'WARNING': 'YELLOW|ITALIC',
'ERROR': 'RED|BOLD',
'IMPORTANT': 'BOLD'
}

def log(msg, level, state, color=None):

def log(content, level, state):
"""Log the given message."""
if state['verbosity'] < level:
return

# Add the clock if so
if not state['no_timestamp']:
if 'clocks' in state:
clock = " %s " % state['clocks'][1].isoformat()
else:
clock = "".ljust(28)
msg = clock + "|" + msg
# Add the clock if available
if 'clocks' in state and state['clocks'][1]:
content['timestamp'] = " %s " % state['clocks'][1].isoformat()

# Add the current line if so
if state['show_lines']:
msg = " %05d/%04d |%s" % (
state['input_line'], state['output_line'] + 1, msg)
# Add the current line
content['input_line'] = state['input_line']
content['output_line'] = state['output_line'] + 1 # This message count

if 'onlyIf' in state and not state['onlyIf'].search(msg):
# Apply the filter
if 'onlyIf' in state and not dict_regex_search(content, state['onlyIf']):
return

# Highlight the message if so
if 'highlight' in state and state['highlight'].search(msg):
color = (color or "") + COLORS['BOLD']
# Highlight the message if match
if 'highlight' in state and dict_regex_search(content, state['highlight']):
content['kind'] = content.get('kind', "") + "|IMPORTANT"

# Apply color if specified
if color and not state['no_colors']:
msg = color + msg + COLORS['ENDC']
if not state['no_colors']:
color = ""
for kind in filter(None, content.get('kind', '').split("|")):
for subkind in KIND_TO_COLOR[kind].split("|"):
color += COLORS[subkind]
if len(color) > 0:
content['description'] = color + content['description'] + \
COLORS['END']

# Write the message
state['output_device'].write(msg)
state['format_device'].write_message(content, state)


def log_recv(addr, entity, text, state, level=0):
"""Log a received packet."""
if not state['ignore_packets']:
log("%s|%s|%s| %s" %
("---> ".rjust(9), addr.center(24), entity.center(16), text),
level, state)
if state['ignore_packets']:
return
content = {'description': text, 'remote': addr, 'entity': entity,
'inout': 'in'}
log(content, level, state)


def log_send(addr, entity, text, state, level=0):
"""Log a sent packet."""
if not state['ignore_packets']:
log("%s|%s|%s| %s" %
(" <---".ljust(9), addr.center(24), entity.center(16), text),
level, state)
if state['ignore_packets']:
return
content = {'description': text, 'remote': addr, 'entity': entity,
'inout': 'out'}
log(content, level, state)


def log_process(addr, entity, text, state, level=0):
"""Log a processed packet."""
if not state['ignore_packets']:
log("%s|%s|%s| %s" %
("".ljust(9), addr.center(24), entity.center(16), text),
level, state)
if state['ignore_packets']:
return
content = {'description': text, 'remote': addr, 'entity': entity}
log(content, level, state)


def log_cfg(text, state, level=0):
Expand All @@ -103,8 +125,8 @@ def log_cfg(text, state, level=0):

def log_event(text, state, level=0):
"""Log an application event."""
log("%s|%s|%s| %s" % ("".ljust(9), "".ljust(24), "".ljust(16), text),
level, state)
content = {'description': text}
log(content, level, state)


def log_warning(text, state, level=0):
Expand All @@ -114,9 +136,8 @@ def log_warning(text, state, level=0):

countset_add_element(state['warnings'], text)
if state['inline']:
text = "%s|%s|%s| *Warning: %s*" % (
"".ljust(9), "".ljust(24), "".ljust(16), text)
log(text, level, state, COLORS['WARNING'])
content = {'description': "Warning: " + text, 'kind': 'WARNING'}
log(content, level, state)


def log_error(text, state, level=0):
Expand All @@ -126,13 +147,20 @@ def log_error(text, state, level=0):

countset_add_element(state['errors'], text)
if state['inline']:
text = "%s|%s|%s| **Error: %s**" % (
"".ljust(9), "".ljust(24), "".ljust(16), text)
log(text, level, state, COLORS['FAIL'])
content = {'description': "Error: " + text, 'kind': 'ERROR'}
log(content, level, state)


def countset_add_element(countset, el):
"""Add an element to the countset."""
if el not in countset:
countset[el] = [len(countset), 0]
countset[el][1] += 1


def dict_regex_search(content, regex):
"""Apply the regex over all the fields of the dictionary."""
match = False
for field in content:
match = match if match else regex.search(field)
return match
50 changes: 35 additions & 15 deletions src/devices/markdownformatdevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
Classes:
+ MarkdownFormatDevice: Format device for Markdown.
"""
from __future__ import absolute_import
from __init__ import __version__
from devices.formatdevice import FormatDevice
from devices.logger import COLORS
from rtilogparser import __version__


class MarkdownFormatDevice(FormatDevice):
Expand All @@ -44,6 +44,8 @@ class MarkdownFormatDevice(FormatDevice):
def __init__(self, state):
"""Initialize the device."""
self.write = state['output_device'].write
self.show_timestamp = not state['no_timestamp']
self.show_lines = state['show_lines']

def write_header(self, state):
"""Write the header."""
Expand All @@ -70,32 +72,50 @@ def write_header(self, state):
self.write("## Network Data Flow and Application Events")
header = " In/Out | Remote Address | Local Entity | Message"
headln = "---------|:----------------------:|:--------------:|--------"
if not state['no_timestamp']:
if self.show_timestamp:
header = "Timestamp".ljust(28) + "|" + header
headln = "----------------------------|" + headln
if state['show_lines']:
headln = "-".ljust(28, "-") + "|" + headln
if self.show_lines:
header = " Log/Parser |" + header
headln = "------------|" + headln
self.write(header)
self.write(headln)

def write_message(self, state):
def write_message(self, content, state):
"""Write the message."""
raise NotImplementedError("write_message not implemented")
# Create the standard message
if 'inout' not in content:
inout = "".ljust(9)
elif content['inout'] == 'in':
inout = "---> ".center(9)
else:
inout = " <---".center(9)
description = content['description']
if content.get('kind') in ['ERROR', 'IMPORTANT']:
description = "**" + description + "**"
elif content.get('kind') == 'WARNING':
description = "*" + description + "*"
remote = content.get('remote', '').center(24)
entity = content.get('entity', '').center(16)
msg = "%s|%s|%s| %s" % (inout, remote, entity, description)

# Add the optional columns
if self.show_timestamp:
timestamp = content.get('timestamp', '').center(28)
msg = timestamp + "|" + msg
if self.show_lines:
msg = " %05d/%04d |%s" % (content['input_line'],
content['output_line'], msg)

self.write(msg)

def write_warnings(self, state):
"""Write the warning messages."""
title = "Warnings"
if not state['no_colors']:
title = COLORS['WARNING'] + title + COLORS['ENDC']
self.write_countset(state['warnings'], title)
self.write_countset(state['warnings'], "Warnings")

def write_errors(self, state):
"""Write the warning messages."""
title = "Errors"
if not state['no_colors']:
title = COLORS['FAIL'] + title + COLORS['ENDC']
self.write_countset(state['errors'], title)
self.write_countset(state['errors'], "Errors")

def write_configurations(self, state):
"""Write the configuration messages."""
Expand Down
3 changes: 2 additions & 1 deletion src/rtilogparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@
from sys import exc_info
from traceback import extract_tb

from __init__ import __version__
from devices.inputdevices import InputConsoleDevice, InputFileDevice
from devices.logger import log_error, log_warning
from devices.markdownformatdevice import MarkdownFormatDevice
from devices.outputdevices import OutputConsoleDevice, OutputFileDevice
from logs import create_regex_list
from utils import compare_times

__version__ = "1.2a2"

DATE_REGEX = re.compile(r'\[(\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}.\d{6})\]' +
r'\[(\d{10}.\d{6})\]')
SINGLE_DATE_REGEX = re.compile(r'\[(\d{10}).(\d{6})\]')
Expand Down

0 comments on commit f83d6e1

Please sign in to comment.