commit 4135a5498a289a6b75320535ab5ecb20020ac54b Author: Damian Johnson atagar@torproject.org Date: Sun Apr 12 14:39:49 2015 -0700
Move deduplication to log util
This fits very nicely as a method of the LogEntry. This will also make it much easier to add tests. --- nyx/log_panel.py | 42 +----------------------------------------- nyx/util/log.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 41 deletions(-)
diff --git a/nyx/log_panel.py b/nyx/log_panel.py index 75fa59d..cdb2346 100644 --- a/nyx/log_panel.py +++ b/nyx/log_panel.py @@ -24,12 +24,6 @@ from nyx import __version__ from nyx.util import panel, tor_controller, ui_tools from nyx.util.log import LogEntry, read_tor_log
-try: - # added in python 3.2 - from functools import lru_cache -except ImportError: - from stem.util.lru_cache import lru_cache - DAYBREAK_EVENT = 'DAYBREAK' # special event for marking when the date changes TIMEZONE_OFFSET = time.altzone if time.localtime()[8] else time.timezone
@@ -104,23 +98,6 @@ def days_since(timestamp = None): return int((timestamp - TIMEZONE_OFFSET) / 86400)
-@lru_cache() -def common_log_messages(): - """ - Fetches a mapping of common log messages to their runlevels from the config. - """ - - nyx_config = conf.get_config('nyx') - messages = {} - - for conf_key in nyx_config.keys(): - if conf_key.startswith('dedup.'): - event_type = conf_key[4:].upper() - messages[event_type] = nyx_config.get(conf_key, []) - - return messages - - def log_file_path(): for log_entry in tor_controller().get_conf('Log', [], True): entry_comp = log_entry.split() # looking for an entry like: notice file /var/log/tor/notices.log @@ -240,24 +217,7 @@ def is_duplicate(event, event_set, get_duplicates = False): break
if event.type == forward_entry.type: - is_duplicate = False - - if event.msg == forward_entry.msg: - is_duplicate = True - else: - for common_msg in common_log_messages().get(event.type, []): - # if it starts with an asterisk then check the whole message rather - # than just the start - - if common_msg[0] == '*': - is_duplicate = common_msg[1:] in event.msg and common_msg[1:] in forward_entry.msg - else: - is_duplicate = event.msg.startswith(common_msg) and forward_entry.msg.startswith(common_msg) - - if is_duplicate: - break - - if is_duplicate: + if event.is_duplicate(forward_entry): if get_duplicates: duplicate_indices.append(i) else: diff --git a/nyx/util/log.py b/nyx/util/log.py index 2d8f523..a753390 100644 --- a/nyx/util/log.py +++ b/nyx/util/log.py @@ -5,14 +5,41 @@ runlevels.
import time
+import stem.util.conf import stem.util.log import stem.util.system
import nyx.util
+try: + # added in python 3.2 + from functools import lru_cache +except ImportError: + from stem.util.lru_cache import lru_cache + TOR_RUNLEVELS = ['DEBUG', 'INFO', 'NOTICE', 'WARN', 'ERR']
+@lru_cache() +def _common_log_messages(): + """ + Provides a mapping of message types to its common log messages. These are + message prefixes unless it starts with an asterisk, in which case it can + appear anywhere in the message. + + :returns: **dict** of the form {event_type => [msg1, msg2...]} + """ + + nyx_config, messages = stem.util.conf.get_config('nyx'), {} + + for conf_key in nyx_config.keys(): + if conf_key.startswith('dedup.'): + event_type = conf_key[4:] + messages[event_type] = nyx_config.get(conf_key, []) + + return messages + + class LogEntry(object): """ Individual tor or nyx log entry. @@ -34,6 +61,32 @@ class LogEntry(object): entry_time = time.localtime(self.timestamp) self.display_message = '%02i:%02i:%02i [%s] %s' % (entry_time[3], entry_time[4], entry_time[5], self.type, self.message)
+ @lru_cache() + def is_duplicate(self, entry): + """ + Checks if we are a duplicate of the given message or not. + + :returns: **True** if the given log message is a duplicate of us and **False** otherwise + """ + + if self.message == entry.message: + return True + elif self.type != entry.type: + return False + + for common_msg in _common_log_messages().get(self.type, []): + # if it starts with an asterisk then check the whole message rather + # than just the start + + if common_msg[0] == '*': + if common_msg[1:] in self.message and common_msg[1:] in entry.message: + return True + else: + if self.message.startswith(common_msg) and entry.message.startswith(common_msg): + return True + + return False + def __eq__(self, other): if isinstance(other, LogEntry): return hash(self) == hash(other)