-
Notifications
You must be signed in to change notification settings - Fork 6
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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." |
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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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") |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,82 +16,104 @@ | |
"""Logger functions. | ||
|
||
The module contains functions to log the new messages. | ||
The 'content' dictionary is defined in the FormatDevice class. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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): | ||
|
@@ -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): | ||
|
@@ -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): | ||
|
@@ -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 |
There was a problem hiding this comment.
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?