Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Format Devices #7

Merged
merged 2 commits into from
Dec 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Package LogParser or LogParser Packgage?


__version__ = "1.2a2"
__license__ = "Apache"
__copyright__ = "Copyright 2016 Real-Time Innovations, Inc."
65 changes: 65 additions & 0 deletions src/devices/formatdevice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# 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.
"""Device for the output format.

The module contains the abstract class representation for a formatter of the
parsed logs.

Classes:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this comment it is not necessary: we only have a class in this file (with the same name of the class).

+ FormatDevice: Abstract base class for format device implementations.
"""


class FormatDevice(object):
"""Abstract base class for format device implementations.

You will need to implement the following methods:
+ write_header: write the header if any.
+ write_configurations: write the configuration messages.
+ write_warnings: write the warning messages.
+ write_errors: write the error messages.
"""

def write_header(self, state):
"""Write the header if any."""
raise NotImplementedError("write_header not implemented")

def write_message(self, content, state):
"""Write the message.

The content argument is a dictionary with at least 'description' item.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is not a good idea to explain the "content" param in this way. Please, follow the same style as in the other functions

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):
"""Write the configuration messages."""
raise NotImplementedError("write_configurations not implemented")

def write_warnings(self, state):
"""Write the warning messages."""
raise NotImplementedError("write_warnings not implemented")

def write_errors(self, state):
"""Write the error messages."""
raise NotImplementedError("write_errors not implemented")
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about how to describe this param but I think that this is not correct


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
Loading