[tor-commits] [nyx/master] Move LogEntry to log util

atagar at torproject.org atagar at torproject.org
Tue May 5 05:42:06 UTC 2015


commit 7889e5e1b0ef095beba0017e92b74971437ea101
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Apr 12 13:49:21 2015 -0700

    Move LogEntry to log util
    
    We made a LogEntry namedtuple in the log util for read_tor_log(). This is very
    similar to the LogEntry class in the panel. Just moving the class - we'll want
    this to make our other helpers testable too.
---
 nyx/log_panel.py     |   62 +++++++++++++-------------------------------------
 nyx/util/log.py      |   45 ++++++++++++++++++++++++------------
 nyx/util/ui_tools.py |    2 +-
 3 files changed, 48 insertions(+), 61 deletions(-)

diff --git a/nyx/log_panel.py b/nyx/log_panel.py
index cdaca17..75fa59d 100644
--- a/nyx/log_panel.py
+++ b/nyx/log_panel.py
@@ -12,15 +12,17 @@ import logging
 import threading
 
 import stem
+import stem.response.events
+
 from stem.control import State
-from stem.response import events
 from stem.util import conf, log, str_tools
 
 import nyx.arguments
 import nyx.popups
+
 from nyx import __version__
 from nyx.util import panel, tor_controller, ui_tools
-from nyx.util.log import read_tor_log
+from nyx.util.log import LogEntry, read_tor_log
 
 try:
   # added in python 3.2
@@ -158,7 +160,7 @@ def get_daybreaks(events, ignore_time_for_cache = False):
 
     if event_day != last_day:
       marker_timestamp = (event_day * 86400) + TIMEZONE_OFFSET
-      new_listing.append(LogEntry(marker_timestamp, DAYBREAK_EVENT, '', 'white'))
+      new_listing.append(LogEntry(marker_timestamp, DAYBREAK_EVENT, ''))
 
     new_listing.append(entry)
     last_day = event_day
@@ -267,34 +269,6 @@ def is_duplicate(event, event_set, get_duplicates = False):
     return False
 
 
-class LogEntry():
-  """
-  Individual log file entry, having the following attributes:
-    timestamp - unix timestamp for when the event occurred
-    event_type - event type that occurred ('INFO', 'BW', 'NYX_WARN', etc)
-    msg       - message that was logged
-    color     - color of the log entry
-  """
-
-  def __init__(self, timestamp, event_type, msg):
-    self.timestamp = timestamp
-    self.type = event_type
-    self.msg = msg
-    self.color = CONFIG['attr.log_color'].get(event_type, 'white')
-
-  @lru_cache()
-  def get_display_message(self):
-    """
-    Provides the entry's message for the log.
-
-    Arguments:
-      include_date - appends the event's date to the start of the message
-    """
-
-    entry_time = time.localtime(self.timestamp)
-    return '%02i:%02i:%02i [%s] %s' % (entry_time[3], entry_time[4], entry_time[5], self.type, self.msg)
-
-
 class LogPanel(panel.Panel, threading.Thread, logging.Handler):
   """
   Listens for and displays tor, nyx, and stem events. This can prepopulate
@@ -427,8 +401,8 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
       if logging_location:
         try:
           for entry in read_tor_log(logging_location, read_limit):
-            if entry.runlevel in set_runlevels:
-              self.msg_log.append(LogEntry(entry.timestamp, entry.runlevel, entry.message))
+            if entry.type in set_runlevels:
+              self.msg_log.append(entry)
         except IOError as exc:
           log.info('Unable to read log located at %s: %s' % (logging_location, exc))
         except ValueError as exc:
@@ -460,9 +434,9 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
 
     msg = ' '.join(str(event).split(' ')[1:])
 
-    if isinstance(event, events.BandwidthEvent):
+    if isinstance(event, stem.response.events.BandwidthEvent):
       msg = 'READ: %i, WRITTEN: %i' % (event.read, event.written)
-    elif isinstance(event, events.LogEvent):
+    elif isinstance(event, stem.response.events.LogEvent):
       msg = event.message
 
     self.register_event(LogEntry(event.arrived_at, event.type, msg))
@@ -478,15 +452,11 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
     if event.type not in self.logged_events:
       return
 
-    # strips control characters to avoid screwing up the terminal
-
-    event.msg = ui_tools.get_printable(event.msg)
-
     # note event in the log file if we're saving them
 
     if self.log_file:
       try:
-        self.log_file.write(event.get_display_message() + '\n')
+        self.log_file.write(event.display_message + '\n')
         self.log_file.flush()
       except IOError as exc:
         log.error('Unable to write to log file: %s' % exc.strerror)
@@ -498,7 +468,7 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
 
     # notifies the display that it has new content
 
-    if not self.regex_filter or self.regex_filter.search(event.get_display_message()):
+    if not self.regex_filter or self.regex_filter.search(event.display_message):
       self._cond.acquire()
       self._cond.notifyAll()
       self._cond.release()
@@ -679,10 +649,10 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
 
     try:
       for entry in self.msg_log:
-        is_visible = not self.regex_filter or self.regex_filter.search(entry.get_display_message())
+        is_visible = not self.regex_filter or self.regex_filter.search(entry.display_message)
 
         if is_visible:
-          snapshot_file.write(entry.get_display_message() + '\n')
+          snapshot_file.write(entry.display_message + '\n')
 
       self.vals_lock.release()
     except Exception as exc:
@@ -814,7 +784,7 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
     while deduplicated_log:
       entry, duplicate_count = deduplicated_log.pop(0)
 
-      if self.regex_filter and not self.regex_filter.search(entry.get_display_message()):
+      if self.regex_filter and not self.regex_filter.search(entry.display_message):
         continue  # filter doesn't match log message - skip
 
       # checks if we should be showing a divider with the date
@@ -850,11 +820,11 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
 
         display_queue = []
 
-        msg_comp = entry.get_display_message().split('\n')
+        msg_comp = entry.display_message.split('\n')
 
         for i in range(len(msg_comp)):
           font = curses.A_BOLD if 'ERR' in entry.type else curses.A_NORMAL  # emphasizes ERR messages
-          display_queue.append((msg_comp[i].strip(), (font, entry.color), i != len(msg_comp) - 1))
+          display_queue.append((msg_comp[i].strip(), (font, CONFIG['attr.log_color'].get(entry.type, 'white')), i != len(msg_comp) - 1))
 
         if duplicate_count:
           plural_label = 's' if duplicate_count > 1 else ''
diff --git a/nyx/util/log.py b/nyx/util/log.py
index d2e2eff..2d8f523 100644
--- a/nyx/util/log.py
+++ b/nyx/util/log.py
@@ -3,7 +3,6 @@ Logging utilities, primiarily short aliases for logging a message at various
 runlevels.
 """
 
-import collections
 import time
 
 import stem.util.log
@@ -11,15 +10,40 @@ import stem.util.system
 
 import nyx.util
 
-LogEntry = collections.namedtuple('LogEntry', [
-  'timestamp',
-  'runlevel',
-  'message',
-])
-
 TOR_RUNLEVELS = ['DEBUG', 'INFO', 'NOTICE', 'WARN', 'ERR']
 
 
+class LogEntry(object):
+  """
+  Individual tor or nyx log entry.
+
+  **Note:** Tor doesn't include the date in its timestamps so the year
+  component may be inaccurate. (:trac:`15607`)
+
+  :var int timestamp: unix timestamp for when the event occured
+  :var str type: event type
+  :var str message: event's message
+  :var str display_message: message annotated with our time and runlevel
+  """
+
+  def __init__(self, timestamp, type, message):
+    self.timestamp = timestamp
+    self.type = type
+    self.message = message
+
+    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)
+
+  def __eq__(self, other):
+    if isinstance(other, LogEntry):
+      return hash(self) == hash(other)
+    else:
+      return False
+
+  def __hash__(self):
+    return hash(self.display_message)
+
+
 def trace(msg, **attr):
   _log(stem.util.log.TRACE, msg, **attr)
 
@@ -59,13 +83,6 @@ def _log(runlevel, message, **attr):
 def read_tor_log(path, read_limit = None):
   """
   Provides logging messages from a tor log file, from newest to oldest.
-  LogEntry this provides have three attributes...
-
-    * **timestamp** (int)
-    * **runlevel** (str)
-    * **message** (str)
-
-  **Note:** The 'timestamp' has a hardcoded year of 2012 due to :trac:`15607`.
 
   :param str path: logging location to read from
   :param int read_limit: maximum number of lines to read from the file
diff --git a/nyx/util/ui_tools.py b/nyx/util/ui_tools.py
index 1123080..8d7edad 100644
--- a/nyx/util/ui_tools.py
+++ b/nyx/util/ui_tools.py
@@ -39,7 +39,7 @@ CONFIG = conf.config_dict('nyx', {
 
 def is_color_supported():
   """
-  Checks if curses presently supports rendering colors.
+  Checks if curses currently supports rendering colors.
 
   :returns: **True** if colors can be rendered, **False** otherwise
   """





More information about the tor-commits mailing list