tor-commits
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
May 2015
- 22 participants
- 990 discussions

[translation/tails-misc] Update translations for tails-misc
by translation@torproject.org 05 May '15
by translation@torproject.org 05 May '15
05 May '15
commit 6af12eee220520fd755fcead298a1a8bb0209247
Author: Translation commit bot <translation(a)torproject.org>
Date: Tue May 5 09:15:35 2015 +0000
Update translations for tails-misc
---
fr.po | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/fr.po b/fr.po
index 7cee132..0922e8f 100644
--- a/fr.po
+++ b/fr.po
@@ -7,6 +7,7 @@
# Alex <chioubaca(a)gmail.com>, 2014
# tneskovic <antoine_ecuador(a)yahoo.fr>, 2014
# apaddlingduck, 2014
+# Athorcis, 2015
# Emmanuel Simond, 2014
# Jean-Yves Toumit <saiolar-c(a)yahoo.fr>, 2013
# Onizuka, 2013
@@ -17,8 +18,8 @@ msgstr ""
"Project-Id-Version: The Tor Project\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-05-02 23:47+0200\n"
-"PO-Revision-Date: 2015-05-03 08:25+0000\n"
-"Last-Translator: runasand <runa.sandvik(a)gmail.com>\n"
+"PO-Revision-Date: 2015-05-05 09:03+0000\n"
+"Last-Translator: Athorcis\n"
"Language-Team: French (http://www.transifex.com/projects/p/torproject/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -106,7 +107,7 @@ msgstr "_Gérer les Clés"
#: config/chroot_local-includes/usr/local/bin/gpgApplet:208
msgid "_Open Text Editor"
-msgstr ""
+msgstr "_Ouvrir l'éditeur de texte"
#: config/chroot_local-includes/usr/local/bin/gpgApplet:252
msgid "The clipboard does not contain valid input data."
1
0

05 May '15
commit ece58f823d9548f04f9a8027c8db17440e33700e
Author: Damian Johnson <atagar(a)torproject.org>
Date: Mon Apr 6 10:56:08 2015 -0700
Take advantage of stem.util.system.tail()
Using our new util rather than shelling out for this. Cuts down on one more
platform specific dependency.
---
nyx/log_panel.py | 99 ++++++++++++++++++++++--------------------------------
1 file changed, 40 insertions(+), 59 deletions(-)
diff --git a/nyx/log_panel.py b/nyx/log_panel.py
index 62d2319..b314eaa 100644
--- a/nyx/log_panel.py
+++ b/nyx/log_panel.py
@@ -190,82 +190,63 @@ def get_log_file_entries(runlevels, read_limit = None, add_limit = None):
if is_file_subset:
read_limit = add_limit
- # tries opening the log file, cropping results to avoid choking on huge logs
-
- lines = []
-
- try:
- if read_limit:
- lines = system.call('tail -n %i %s' % (read_limit, logging_location))
-
- if not lines:
- raise IOError()
- else:
- log_file = open(logging_location, 'r')
- lines = log_file.readlines()
- log_file.close()
- except IOError:
- log.warn("Unable to read tor's log file: %s" % logging_location)
-
- if not lines:
- return []
-
logged_events = []
current_unix_time, current_local_time = time.time(), time.localtime()
- for i in range(len(lines) - 1, -1, -1):
- line = lines[i]
-
- # entries look like:
- # Jul 15 18:29:48.806 [notice] Parsing GEOIP file.
+ try:
+ for line in system.tail(logging_location, read_limit):
+ # entries look like:
+ # Jul 15 18:29:48.806 [notice] Parsing GEOIP file.
- line_comp = line.split()
+ line_comp = line.split()
- # Checks that we have all the components we expect. This could happen if
- # we're either not parsing a tor log or in weird edge cases (like being
- # out of disk space)
+ # Checks that we have all the components we expect. This could happen if
+ # we're either not parsing a tor log or in weird edge cases (like being
+ # out of disk space)
- if len(line_comp) < 4:
- continue
+ if len(line_comp) < 4:
+ continue
- event_type = line_comp[3][1:-1].upper()
+ event_type = line_comp[3][1:-1].upper()
- if event_type in runlevels:
- # converts timestamp to unix time
+ if event_type in runlevels:
+ # converts timestamp to unix time
- timestamp = ' '.join(line_comp[:3])
+ timestamp = ' '.join(line_comp[:3])
- # strips the decimal seconds
+ # strips the decimal seconds
- if '.' in timestamp:
- timestamp = timestamp[:timestamp.find('.')]
+ if '.' in timestamp:
+ timestamp = timestamp[:timestamp.find('.')]
- # Ignoring wday and yday since they aren't used.
- #
- # Pretend the year is 2012, because 2012 is a leap year, and parsing a
- # date with strptime fails if Feb 29th is passed without a year that's
- # actually a leap year. We can't just use the current year, because we
- # might be parsing old logs which didn't get rotated.
- #
- # https://trac.torproject.org/projects/tor/ticket/5265
+ # Ignoring wday and yday since they aren't used.
+ #
+ # Pretend the year is 2012, because 2012 is a leap year, and parsing a
+ # date with strptime fails if Feb 29th is passed without a year that's
+ # actually a leap year. We can't just use the current year, because we
+ # might be parsing old logs which didn't get rotated.
+ #
+ # https://trac.torproject.org/projects/tor/ticket/5265
- timestamp = '2012 ' + timestamp
- event_time_comp = list(time.strptime(timestamp, '%Y %b %d %H:%M:%S'))
- event_time_comp[8] = current_local_time.tm_isdst
- event_time = time.mktime(event_time_comp) # converts local to unix time
+ timestamp = '2012 ' + timestamp
+ event_time_comp = list(time.strptime(timestamp, '%Y %b %d %H:%M:%S'))
+ event_time_comp[8] = current_local_time.tm_isdst
+ event_time = time.mktime(event_time_comp) # converts local to unix time
- # The above is gonna be wrong if the logs are for the previous year. If
- # the event's in the future then correct for this.
+ # The above is gonna be wrong if the logs are for the previous year. If
+ # the event's in the future then correct for this.
- if event_time > current_unix_time + 60:
- event_time_comp[0] -= 1
- event_time = time.mktime(event_time_comp)
+ if event_time > current_unix_time + 60:
+ event_time_comp[0] -= 1
+ event_time = time.mktime(event_time_comp)
- event_msg = ' '.join(line_comp[4:])
- logged_events.append(LogEntry(event_time, event_type, event_msg, RUNLEVEL_EVENT_COLOR[event_type]))
+ event_msg = ' '.join(line_comp[4:])
+ logged_events.append(LogEntry(event_time, event_type, event_msg, RUNLEVEL_EVENT_COLOR[event_type]))
- if 'opening log file' in line:
- break # this entry marks the start of this tor instance
+ if 'opening log file' in line:
+ break # this entry marks the start of this tor instance
+ except IOError:
+ log.warn("Unable to read tor's log file: %s" % logging_location)
if add_limit:
logged_events = logged_events[:add_limit]
1
0
commit fab856eae980a6adcaa451738b8e79146b8199a3
Author: Damian Johnson <atagar(a)torproject.org>
Date: Fri Apr 10 09:23:27 2015 -0700
Check for quote types in test
Taking advantage of Stem's new check to keep additions standardized on single
quotes.
---
nyx/log_panel.py | 2 +-
run_tests.py | 5 +++--
test/util/read_tor_log.py | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/nyx/log_panel.py b/nyx/log_panel.py
index 8650996..f58af4c 100644
--- a/nyx/log_panel.py
+++ b/nyx/log_panel.py
@@ -457,7 +457,7 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
if entry.runlevel in set_runlevels:
self.msg_log.append(LogEntry(entry.timestamp, entry.runlevel, entry.message, RUNLEVEL_EVENT_COLOR[entry.runlevel]))
except IOError as exc:
- log.info("Unable to read log located at %s: %s" % (logging_location, exc))
+ log.info('Unable to read log located at %s: %s' % (logging_location, exc))
except ValueError as exc:
log.info(str(exc))
diff --git a/run_tests.py b/run_tests.py
index 17e879d..6e62169 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -58,6 +58,7 @@ def main():
check_newlines = True,
check_trailing_whitespace = True,
check_exception_keyword = True,
+ prefer_single_quotes = True,
)
for path, issues in pep8_issues.items():
@@ -70,8 +71,8 @@ def main():
for file_path in static_check_issues:
print '* %s' % file_path
- for line_number, msg in static_check_issues[file_path]:
- print ' line %-4s - %s' % (line_number, msg)
+ for issue in static_check_issues[file_path]:
+ print ' line %-4s - %-40s %s' % (issue.line_number, issue.message, issue.line)
print
diff --git a/test/util/read_tor_log.py b/test/util/read_tor_log.py
index 3b2ca01..7f84c41 100644
--- a/test/util/read_tor_log.py
+++ b/test/util/read_tor_log.py
@@ -49,7 +49,7 @@ class TestReadTorLog(unittest.TestCase):
list(read_tor_log(data_path('malformed_runlevel')))
self.fail("Malformed content should've raised a ValueError")
except ValueError as exc:
- self.assertTrue("has an unrecognized runlevel: [unrecognized]" in str(exc))
+ self.assertTrue('has an unrecognized runlevel: [unrecognized]' in str(exc))
def test_with_malformed_date(self):
try:
1
0

05 May '15
commit c1c1581b5d9a8435703822b42e806ad4b2693ad2
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Apr 11 16:26:09 2015 -0700
Don't provide dates when writing logs to files
Tor doesn't provide dates (#15607) so we provide made up information for
prepopulated events. Might as well just not provide dates at all until tor
improves this.
---
nyx/log_panel.py | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/nyx/log_panel.py b/nyx/log_panel.py
index ddf2c6e..cdaca17 100644
--- a/nyx/log_panel.py
+++ b/nyx/log_panel.py
@@ -283,7 +283,7 @@ class LogEntry():
self.color = CONFIG['attr.log_color'].get(event_type, 'white')
@lru_cache()
- def get_display_message(self, include_date = False):
+ def get_display_message(self):
"""
Provides the entry's message for the log.
@@ -291,13 +291,8 @@ class LogEntry():
include_date - appends the event's date to the start of the message
"""
- if include_date:
- entry_time = time.localtime(self.timestamp)
- time_label = '%i/%i/%i %02i:%02i:%02i' % (entry_time[1], entry_time[2], entry_time[0], entry_time[3], entry_time[4], entry_time[5])
- return '%s [%s] %s' % (time_label, self.type, self.msg)
- else:
- 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)
+ 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):
@@ -491,7 +486,7 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
if self.log_file:
try:
- self.log_file.write(event.get_display_message(True) + '\n')
+ self.log_file.write(event.get_display_message() + '\n')
self.log_file.flush()
except IOError as exc:
log.error('Unable to write to log file: %s' % exc.strerror)
@@ -687,7 +682,7 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
is_visible = not self.regex_filter or self.regex_filter.search(entry.get_display_message())
if is_visible:
- snapshot_file.write(entry.get_display_message(True) + '\n')
+ snapshot_file.write(entry.get_display_message() + '\n')
self.vals_lock.release()
except Exception as exc:
1
0

05 May '15
commit b20b60df25a5f99f32b0f347173083883e6fb409
Author: Damian Johnson <atagar(a)torproject.org>
Date: Mon Apr 6 15:41:50 2015 -0700
read_tor_log() for reading tor log files
Replacing get_log_file_entries() with a tested, simpler function. This is still
a lot grosser than I'd like, but not much I can do unless something happens
with #15607.
---
nyx/config/strings.cfg | 1 +
nyx/log_panel.py | 149 ++++-----------------------------
nyx/util/__init__.py | 9 +-
nyx/util/log.py | 77 +++++++++++++++++
run_tests.py | 5 +-
test/util/data/malformed_date | 21 +++++
test/util/data/malformed_line | 21 +++++
test/util/data/malformed_runlevel | 21 +++++
test/util/data/multiple_tor_instances | 33 ++++++++
test/util/data/tor_log | 21 +++++
test/util/read_tor_log.py | 59 +++++++++++++
11 files changed, 282 insertions(+), 135 deletions(-)
diff --git a/nyx/config/strings.cfg b/nyx/config/strings.cfg
index d1169b9..7660bfb 100644
--- a/nyx/config/strings.cfg
+++ b/nyx/config/strings.cfg
@@ -24,6 +24,7 @@ msg.panel.graphing.prepopulation_successful Bandwidth graph has information for
msg.panel.graphing.bw_event_cache_malformed Tor's 'GETINFO bw-event-cache' provided malformed output: {response}
msg.panel.header.fd_used_at_sixty_percent Tor's file descriptor usage is at {percentage}%.
msg.panel.header.fd_used_at_ninety_percent Tor's file descriptor usage is at {percentage}%. If you run out Tor will be unable to continue functioning.
+msg.panel.log.read_from_log_file Read {count} entries from tor's log file: {path} (read limit: {read_limit}, runtime: {runtime})
msg.setup.nyx_is_running_as_root Nyx is currently running with root permissions. This isn't a good idea, nor should it be necessary. Try starting nyx with "sudo -u {tor_user} nyx" instead.
msg.setup.chroot_doesnt_exist The chroot path set in your config ({path}) doesn't exist.
diff --git a/nyx/log_panel.py b/nyx/log_panel.py
index b314eaa..8650996 100644
--- a/nyx/log_panel.py
+++ b/nyx/log_panel.py
@@ -14,12 +14,13 @@ import threading
import stem
from stem.control import State
from stem.response import events
-from stem.util import conf, log, str_tools, system
+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
RUNLEVEL_EVENT_COLOR = {
log.DEBUG: 'magenta',
@@ -124,136 +125,12 @@ def load_log_messages():
COMMON_LOG_MESSAGES[event_type] = messages
-def get_log_file_entries(runlevels, read_limit = None, add_limit = None):
- """
- Parses tor's log file for past events matching the given runlevels, providing
- a list of log entries (ordered newest to oldest). Limiting the number of read
- entries is suggested to avoid parsing everything from logs in the GB and TB
- range.
-
- Arguments:
- runlevels - event types (DEBUG - ERR) to be returned
- read_limit - max lines of the log file that'll be read (unlimited if None)
- add_limit - maximum entries to provide back (unlimited if None)
- """
-
- start_time = time.time()
-
- if not runlevels:
- return []
-
- # checks tor's configuration for the log file's location (if any exists)
-
- logging_types, logging_location = None, None
-
- for logging_entry in tor_controller().get_conf('Log', [], True):
- # looks for an entry like: notice file /var/log/tor/notices.log
-
- entry_comp = logging_entry.split()
+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
if entry_comp[1] == 'file':
- logging_types, logging_location = entry_comp[0], entry_comp[2]
- break
-
- if not logging_location:
- return []
-
- # includes the prefix for tor paths
-
- logging_location = CONFIG['tor.chroot'] + logging_location
-
- # if the runlevels argument is a superset of the log file then we can
- # limit the read contents to the add_limit
-
- runlevels = list(log.Runlevel)
- logging_types = logging_types.upper()
-
- if add_limit and (not read_limit or read_limit > add_limit):
- if '-' in logging_types:
- div_index = logging_types.find('-')
- start_index = runlevels.index(logging_types[:div_index])
- end_index = runlevels.index(logging_types[div_index + 1:])
- log_file_run_levels = runlevels[start_index:end_index + 1]
- else:
- start_index = runlevels.index(logging_types)
- log_file_run_levels = runlevels[start_index:]
-
- # checks if runlevels we're reporting are a superset of the file's contents
-
- is_file_subset = True
-
- for runlevel_type in log_file_run_levels:
- if runlevel_type not in runlevels:
- is_file_subset = False
- break
-
- if is_file_subset:
- read_limit = add_limit
-
- logged_events = []
- current_unix_time, current_local_time = time.time(), time.localtime()
-
- try:
- for line in system.tail(logging_location, read_limit):
- # entries look like:
- # Jul 15 18:29:48.806 [notice] Parsing GEOIP file.
-
- line_comp = line.split()
-
- # Checks that we have all the components we expect. This could happen if
- # we're either not parsing a tor log or in weird edge cases (like being
- # out of disk space)
-
- if len(line_comp) < 4:
- continue
-
- event_type = line_comp[3][1:-1].upper()
-
- if event_type in runlevels:
- # converts timestamp to unix time
-
- timestamp = ' '.join(line_comp[:3])
-
- # strips the decimal seconds
-
- if '.' in timestamp:
- timestamp = timestamp[:timestamp.find('.')]
-
- # Ignoring wday and yday since they aren't used.
- #
- # Pretend the year is 2012, because 2012 is a leap year, and parsing a
- # date with strptime fails if Feb 29th is passed without a year that's
- # actually a leap year. We can't just use the current year, because we
- # might be parsing old logs which didn't get rotated.
- #
- # https://trac.torproject.org/projects/tor/ticket/5265
-
- timestamp = '2012 ' + timestamp
- event_time_comp = list(time.strptime(timestamp, '%Y %b %d %H:%M:%S'))
- event_time_comp[8] = current_local_time.tm_isdst
- event_time = time.mktime(event_time_comp) # converts local to unix time
-
- # The above is gonna be wrong if the logs are for the previous year. If
- # the event's in the future then correct for this.
-
- if event_time > current_unix_time + 60:
- event_time_comp[0] -= 1
- event_time = time.mktime(event_time_comp)
-
- event_msg = ' '.join(line_comp[4:])
- logged_events.append(LogEntry(event_time, event_type, event_msg, RUNLEVEL_EVENT_COLOR[event_type]))
-
- if 'opening log file' in line:
- break # this entry marks the start of this tor instance
- except IOError:
- log.warn("Unable to read tor's log file: %s" % logging_location)
-
- if add_limit:
- logged_events = logged_events[:add_limit]
-
- log.info("Read %i entries from tor's log file: %s (read limit: %i, runtime: %0.3f)" % (len(logged_events), logging_location, read_limit, time.time() - start_time))
-
- return logged_events
+ return CONFIG['tor.chroot'] + entry_comp[2]
def get_daybreaks(events, ignore_time_for_cache = False):
@@ -571,10 +448,18 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
if CONFIG['features.log.prepopulate']:
set_runlevels = list(set.intersection(set(self.logged_events), set(list(log.Runlevel))))
read_limit = CONFIG['features.log.prepopulateReadLimit']
- add_limit = CONFIG['cache.log_panel.size']
- for entry in get_log_file_entries(set_runlevels, read_limit, add_limit):
- self.msg_log.append(entry)
+ logging_location = log_file_path()
+
+ 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, RUNLEVEL_EVENT_COLOR[entry.runlevel]))
+ except IOError as exc:
+ log.info("Unable to read log located at %s: %s" % (logging_location, exc))
+ except ValueError as exc:
+ log.info(str(exc))
# crops events that are either too old, or more numerous than the caching size
diff --git a/nyx/util/__init__.py b/nyx/util/__init__.py
index 0e07dfc..58e739c 100644
--- a/nyx/util/__init__.py
+++ b/nyx/util/__init__.py
@@ -17,11 +17,13 @@ import sys
import stem.connection
import stem.util.conf
+import stem.util.log
from nyx.util import log
TOR_CONTROLLER = None
BASE_DIR = os.path.sep.join(__file__.split(os.path.sep)[:-2])
+TESTING = False
try:
uses_settings = stem.util.conf.uses_settings('nyx', os.path.join(BASE_DIR, 'config'), lazy_load = False)
@@ -105,5 +107,10 @@ def msg(message, config, **attr):
try:
return config.get('msg.%s' % message).format(**attr)
except:
- log.notice('BUG: We attempted to use an undefined string resource (%s)' % message)
+ msg = 'BUG: We attempted to use an undefined string resource (%s)' % message
+
+ if TESTING:
+ raise ValueError(msg)
+
+ stem.util.log.notice(msg)
return ''
diff --git a/nyx/util/log.py b/nyx/util/log.py
index 05061b9..d2e2eff 100644
--- a/nyx/util/log.py
+++ b/nyx/util/log.py
@@ -3,10 +3,22 @@ Logging utilities, primiarily short aliases for logging a message at various
runlevels.
"""
+import collections
+import time
+
import stem.util.log
+import stem.util.system
import nyx.util
+LogEntry = collections.namedtuple('LogEntry', [
+ 'timestamp',
+ 'runlevel',
+ 'message',
+])
+
+TOR_RUNLEVELS = ['DEBUG', 'INFO', 'NOTICE', 'WARN', 'ERR']
+
def trace(msg, **attr):
_log(stem.util.log.TRACE, msg, **attr)
@@ -42,3 +54,68 @@ def _log(runlevel, message, **attr):
"""
stem.util.log.log(runlevel, nyx.util.msg(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
+
+ :returns: **iterator** for **LogEntry** for the file's contents
+
+ :raises:
+ * **ValueError** if the log file has unrecognized content
+ * **IOError** if unable to read the file
+ """
+
+ start_time = time.time()
+ count, isdst = 0, time.localtime().tm_isdst
+
+ for line in stem.util.system.tail(path, read_limit):
+ # entries look like:
+ # Jul 15 18:29:48.806 [notice] Parsing GEOIP file.
+
+ line_comp = line.split()
+
+ # Checks that we have all the components we expect. This could happen if
+ # we're either not parsing a tor log or in weird edge cases (like being
+ # out of disk space).
+
+ if len(line_comp) < 4:
+ raise ValueError("Log located at %s has a line that doesn't match the format we expect: %s" % (path, line))
+ elif len(line_comp[3]) < 3 or line_comp[3][1:-1].upper() not in TOR_RUNLEVELS:
+ raise ValueError('Log located at %s has an unrecognized runlevel: %s' % (path, line_comp[3]))
+
+ runlevel = line_comp[3][1:-1].upper()
+ msg = ' '.join(line_comp[4:])
+
+ # Pretending the year is 2012 because 2012 is a leap year. We don't know
+ # the actual year (#15607) so picking something else risks strptime failing
+ # when it reads Feb 29th (#5265).
+
+ try:
+ timestamp_str = '2012 ' + ' '.join(line_comp[:3])
+ timestamp_str = timestamp_str.split('.', 1)[0] # drop fractional seconds
+ timestamp_comp = list(time.strptime(timestamp_str, '%Y %b %d %H:%M:%S'))
+ timestamp_comp[8] = isdst
+
+ timestamp = int(time.mktime(timestamp_comp)) # converts local to unix time
+ except ValueError:
+ raise ValueError("Log located at %s has a timestamp we don't recognize: %s" % (path, ' '.join(line_comp[:3])))
+
+ count += 1
+ yield LogEntry(timestamp, runlevel, msg)
+
+ if 'opening log file' in msg:
+ break # this entry marks the start of this tor instance
+
+ info('panel.log.read_from_log_file', count = count, path = path, read_limit = read_limit if read_limit else 'none', runtime = '%0.3f' % (time.time() - start_time))
diff --git a/run_tests.py b/run_tests.py
index d239393..17e879d 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -13,7 +13,7 @@ import unittest
import stem.util.conf
import stem.util.test_tools
-from nyx.util import uses_settings
+import nyx.util
NYX_BASE = os.path.dirname(__file__)
@@ -25,8 +25,9 @@ SRC_PATHS = [os.path.join(NYX_BASE, path) for path in (
)]
-@uses_settings
+(a)nyx.util.uses_settings
def main():
+ nyx.util.TESTING = True
test_config = stem.util.conf.get_config('test')
test_config.load(os.path.join(NYX_BASE, 'test', 'settings.cfg'))
diff --git a/test/util/data/empty_file b/test/util/data/empty_file
new file mode 100644
index 0000000..e69de29
diff --git a/test/util/data/malformed_date b/test/util/data/malformed_date
new file mode 100644
index 0000000..712149d
--- /dev/null
+++ b/test/util/data/malformed_date
@@ -0,0 +1,21 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Zed 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/data/malformed_line b/test/util/data/malformed_line
new file mode 100644
index 0000000..ac9a367
--- /dev/null
+++ b/test/util/data/malformed_line
@@ -0,0 +1,21 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Apr 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/data/malformed_runlevel b/test/util/data/malformed_runlevel
new file mode 100644
index 0000000..dd8810b
--- /dev/null
+++ b/test/util/data/malformed_runlevel
@@ -0,0 +1,21 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Apr 06 11:03:52.000 [unrecognized] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/data/multiple_tor_instances b/test/util/data/multiple_tor_instances
new file mode 100644
index 0000000..1793ce5
--- /dev/null
+++ b/test/util/data/multiple_tor_instances
@@ -0,0 +1,33 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Apr 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
+Apr 06 11:53:54.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening log file.
+Apr 06 11:53:54.392 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:53:54.392 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:53:54.392 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:53:54.392 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:53:54.396 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:53:54.396 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:53:54.000 [warn] Your log may contain sensitive information - you're logging more than "notice". Don't log unless it serves an important reason. Overwrite the log afterwards.
+Apr 06 11:53:54.000 [debug] tor_disable_debugger_attach(): Attemping to disable debugger attachment to Tor for unprivileged users.
+Apr 06 11:53:54.000 [debug] tor_disable_debugger_attach(): Debugger attachment disabled for unprivileged users.
+Apr 06 11:53:54.000 [info] tor_lockfile_lock(): Locking "/home/atagar/.tor/lock"
+Apr 06 11:53:54.000 [debug] parse_dir_authority_line(): Trusted 100 dirserver at 128.31.0.39:9131 (9695)
diff --git a/test/util/data/tor_log b/test/util/data/tor_log
new file mode 100644
index 0000000..0a4464e
--- /dev/null
+++ b/test/util/data/tor_log
@@ -0,0 +1,21 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Apr 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/read_tor_log.py b/test/util/read_tor_log.py
new file mode 100644
index 0000000..3b2ca01
--- /dev/null
+++ b/test/util/read_tor_log.py
@@ -0,0 +1,59 @@
+import os
+import unittest
+
+from nyx.util.log import LogEntry, read_tor_log
+
+
+def data_path(filename):
+ return os.path.join(os.path.dirname(__file__), 'data', filename)
+
+
+class TestReadTorLog(unittest.TestCase):
+ def test_general_log(self):
+ entries = list(read_tor_log(data_path('tor_log')))
+ self.assertEqual(21, len(entries))
+
+ self.assertEqual(LogEntry(1333738426, 'NOTICE', 'Interrupt: exiting cleanly.'), entries[0])
+ self.assertEqual(LogEntry(1333735419, 'NOTICE', 'Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.'), entries[-1])
+
+ def test_with_multiple_tor_instances(self):
+ entries = list(read_tor_log(data_path('multiple_tor_instances')))
+ self.assertEqual(12, len(entries))
+
+ self.assertEqual(LogEntry(1333738434, 'DEBUG', 'parse_dir_authority_line(): Trusted 100 dirserver at 128.31.0.39:9131 (9695)'), entries[0])
+ self.assertEqual(LogEntry(1333738434, 'INFO', 'tor_lockfile_lock(): Locking "/home/atagar/.tor/lock"'), entries[1])
+ self.assertEqual(LogEntry(1333738434, 'NOTICE', 'Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening log file.'), entries[-1])
+
+ def test_with_read_limit(self):
+ entries = list(read_tor_log(data_path('tor_log'), 5))
+ self.assertEqual(5, len(entries))
+ self.assertEqual('Interrupt: exiting cleanly.', entries[0].message)
+ self.assertEqual('Bootstrapped 90%: Establishing a Tor circuit', entries[-1].message)
+
+ def test_with_empty_file(self):
+ entries = list(read_tor_log(data_path('empty_file')))
+ self.assertEqual(0, len(entries))
+
+ def test_with_missing_path(self):
+ self.assertRaises(IOError, list, read_tor_log(data_path('no_such_path')))
+
+ def test_with_malformed_line(self):
+ try:
+ list(read_tor_log(data_path('malformed_line')))
+ self.fail("Malformed content should've raised a ValueError")
+ except ValueError as exc:
+ self.assertTrue("has a line that doesn't match the format we expect: Apr 06 11:03:53.000" in str(exc))
+
+ def test_with_malformed_runlevel(self):
+ try:
+ list(read_tor_log(data_path('malformed_runlevel')))
+ self.fail("Malformed content should've raised a ValueError")
+ except ValueError as exc:
+ self.assertTrue("has an unrecognized runlevel: [unrecognized]" in str(exc))
+
+ def test_with_malformed_date(self):
+ try:
+ list(read_tor_log(data_path('malformed_date')))
+ self.fail("Malformed content should've raised a ValueError")
+ except ValueError as exc:
+ self.assertTrue("has a timestamp we don't recognize: Zed 06 11:03:52.000" in str(exc))
1
0
commit 552bdf3756af1e3bc254bc5c0e7c7f3019d7cd69
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Apr 11 16:23:16 2015 -0700
Move log colors to config
This is a simple 'event type => color' mapping so no need for it to be littered
throughout our code.
---
nyx/config/attributes.cfg | 18 ++++++++++++++++++
nyx/log_panel.py | 38 +++++++++-----------------------------
2 files changed, 27 insertions(+), 29 deletions(-)
diff --git a/nyx/config/attributes.cfg b/nyx/config/attributes.cfg
index 30bfafb..fe24120 100644
--- a/nyx/config/attributes.cfg
+++ b/nyx/config/attributes.cfg
@@ -39,3 +39,21 @@ attr.graph.header.secondary bandwidth => Upload
attr.graph.header.secondary connections => Outbound
attr.graph.header.secondary resources => Memory
+attr.log_color DEBUG => magenta
+attr.log_color INFO => blue
+attr.log_color NOTICE => green
+attr.log_color WARN => yellow
+attr.log_color ERR => red
+
+attr.log_color NYX_DEBUG => magenta
+attr.log_color NYX_INFO => blue
+attr.log_color NYX_NOTICE => green
+attr.log_color NYX_WARN => yellow
+attr.log_color NYX_ERR => red
+
+attr.log_color CIRC => yellow
+attr.log_color BW => cyan
+attr.log_color NS => blue
+attr.log_color NEWCONSENSUS => blue
+attr.log_color GUARD => yellow
+
diff --git a/nyx/log_panel.py b/nyx/log_panel.py
index 33af9dd..ddf2c6e 100644
--- a/nyx/log_panel.py
+++ b/nyx/log_panel.py
@@ -28,14 +28,6 @@ try:
except ImportError:
from stem.util.lru_cache import lru_cache
-RUNLEVEL_EVENT_COLOR = {
- log.DEBUG: 'magenta',
- log.INFO: 'blue',
- log.NOTICE: 'green',
- log.WARN: 'yellow',
- log.ERR: 'red',
-}
-
DAYBREAK_EVENT = 'DAYBREAK' # special event for marking when the date changes
TIMEZONE_OFFSET = time.altzone if time.localtime()[8] else time.timezone
@@ -66,6 +58,7 @@ CONFIG = conf.config_dict('nyx', {
'cache.log_panel.size': 1000,
'msg.misc.event_types': '',
'tor.chroot': '',
+ 'attr.log_color': {},
}, conf_handler)
DUPLICATE_MSG = ' [%i duplicate%s hidden]'
@@ -283,11 +276,11 @@ class LogEntry():
color - color of the log entry
"""
- def __init__(self, timestamp, event_type, msg, color):
+ def __init__(self, timestamp, event_type, msg):
self.timestamp = timestamp
self.type = event_type
self.msg = msg
- self.color = color
+ self.color = CONFIG['attr.log_color'].get(event_type, 'white')
@lru_cache()
def get_display_message(self, include_date = False):
@@ -415,8 +408,7 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
if record.levelname == 'WARNING':
record.levelname = 'WARN'
- event_color = RUNLEVEL_EVENT_COLOR[record.levelname]
- self.register_event(LogEntry(int(record.created), 'NYX_%s' % record.levelname, record.msg, event_color))
+ self.register_event(LogEntry(int(record.created), 'NYX_%s' % record.levelname, record.msg))
def reprepopulate_events(self):
"""
@@ -441,7 +433,7 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
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, RUNLEVEL_EVENT_COLOR[entry.runlevel]))
+ self.msg_log.append(LogEntry(entry.timestamp, entry.runlevel, entry.message))
except IOError as exc:
log.info('Unable to read log located at %s: %s' % (logging_location, exc))
except ValueError as exc:
@@ -471,26 +463,14 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
register_event().
"""
- msg, color = ' '.join(str(event).split(' ')[1:]), 'white'
+ msg = ' '.join(str(event).split(' ')[1:])
- if isinstance(event, events.CircuitEvent):
- color = 'yellow'
- elif isinstance(event, events.BandwidthEvent):
- color = 'cyan'
+ if isinstance(event, events.BandwidthEvent):
msg = 'READ: %i, WRITTEN: %i' % (event.read, event.written)
elif isinstance(event, events.LogEvent):
- color = RUNLEVEL_EVENT_COLOR[event.runlevel]
msg = event.message
- elif isinstance(event, events.NetworkStatusEvent):
- color = 'blue'
- elif isinstance(event, events.NewConsensusEvent):
- color = 'magenta'
- elif isinstance(event, events.GuardEvent):
- color = 'yellow'
- elif event.type not in nyx.arguments.TOR_EVENT_TYPES.values():
- color = 'red' # unknown event type
-
- self.register_event(LogEntry(event.arrived_at, event.type, msg, color))
+
+ self.register_event(LogEntry(event.arrived_at, event.type, msg))
def register_event(self, event):
"""
1
0
commit 90522a52bf85bc6eb66671db531e5e988052ed89
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Apr 11 15:59:28 2015 -0700
Use @lru_cache for common log messages
Classic instance for a cache rather than doing it manually.
---
nyx/log_panel.py | 48 +++++++++++++++++-------------------------------
1 file changed, 17 insertions(+), 31 deletions(-)
diff --git a/nyx/log_panel.py b/nyx/log_panel.py
index f58af4c..33af9dd 100644
--- a/nyx/log_panel.py
+++ b/nyx/log_panel.py
@@ -22,6 +22,12 @@ from nyx import __version__
from nyx.util import panel, tor_controller, ui_tools
from nyx.util.log import read_tor_log
+try:
+ # added in python 3.2
+ from functools import lru_cache
+except ImportError:
+ from stem.util.lru_cache import lru_cache
+
RUNLEVEL_EVENT_COLOR = {
log.DEBUG: 'magenta',
log.INFO: 'blue',
@@ -71,11 +77,6 @@ DUPLICATE_MSG = ' [%i duplicate%s hidden]'
CONTENT_HEIGHT_REDRAW_THRESHOLD = 3
-# static starting portion of common log entries, fetched from the config when
-# needed if None
-
-COMMON_LOG_MESSAGES = None
-
# cached values and the arguments that generated it for the get_daybreaks and
# get_duplicates functions
@@ -108,21 +109,21 @@ def days_since(timestamp = None):
return int((timestamp - TIMEZONE_OFFSET) / 86400)
-def load_log_messages():
+@lru_cache()
+def common_log_messages():
"""
Fetches a mapping of common log messages to their runlevels from the config.
"""
- global COMMON_LOG_MESSAGES
nyx_config = conf.get_config('nyx')
-
- COMMON_LOG_MESSAGES = {}
+ messages = {}
for conf_key in nyx_config.keys():
if conf_key.startswith('dedup.'):
event_type = conf_key[4:].upper()
- messages = nyx_config.get(conf_key, [])
- COMMON_LOG_MESSAGES[event_type] = messages
+ messages[event_type] = nyx_config.get(conf_key, [])
+
+ return messages
def log_file_path():
@@ -191,11 +192,6 @@ def get_duplicates(events):
if CACHED_DUPLICATES_ARGUMENTS == events:
return list(CACHED_DUPLICATES_RESULT)
- # loads common log entries from the config if they haven't been
-
- if COMMON_LOG_MESSAGES is None:
- load_log_messages()
-
start_time = time.time()
events_remaining = list(events)
return_events = []
@@ -253,8 +249,8 @@ def is_duplicate(event, event_set, get_duplicates = False):
if event.msg == forward_entry.msg:
is_duplicate = True
- elif event.type in COMMON_LOG_MESSAGES:
- for common_msg in COMMON_LOG_MESSAGES[event.type]:
+ 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
@@ -292,8 +288,8 @@ class LogEntry():
self.type = event_type
self.msg = msg
self.color = color
- self._display_message = None
+ @lru_cache()
def get_display_message(self, include_date = False):
"""
Provides the entry's message for the log.
@@ -303,16 +299,12 @@ class LogEntry():
"""
if include_date:
- # not the common case so skip caching
entry_time = time.localtime(self.timestamp)
time_label = '%i/%i/%i %02i:%02i:%02i' % (entry_time[1], entry_time[2], entry_time[0], entry_time[3], entry_time[4], entry_time[5])
return '%s [%s] %s' % (time_label, self.type, self.msg)
-
- if not self._display_message:
+ else:
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.msg)
-
- return self._display_message
+ 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):
@@ -333,12 +325,6 @@ class LogPanel(panel.Panel, threading.Thread, logging.Handler):
threading.Thread.__init__(self)
self.setDaemon(True)
- # Make sure that the msg.* messages are loaded. Lazy loading it later is
- # fine, but this way we're sure it happens before warning about unused
- # config options.
-
- load_log_messages()
-
# regex filters the user has defined
self.filter_options = []
1
0
commit 95ea86e2e907006bd4b9d8ccd53d8ccfa152fb1f
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun Apr 12 14:38:48 2015 -0700
Fix nyx log message deduplication
The name shuffle missed our dedup.cfg, breaking deduplication of this type of
message.
---
nyx/config/dedup.cfg | 62 +++++++++++++++++++++++++-------------------------
1 file changed, 31 insertions(+), 31 deletions(-)
diff --git a/nyx/config/dedup.cfg b/nyx/config/dedup.cfg
index ce8afcb..06c4ff2 100644
--- a/nyx/config/dedup.cfg
+++ b/nyx/config/dedup.cfg
@@ -47,17 +47,17 @@
# [WARN] Problem bootstrapping. Stuck at 80%: Connecting to the Tor network.
# (Network is unreachable; NOROUTE; count 47; recommendation warn)
# [WARN] 4 unknown, 1 missing key, 3 good, 0 bad, 1 no signature, 4 required
-# [ARM_DEBUG] refresh rate: 0.001 seconds
-# [ARM_DEBUG] proc call (process connections): /proc/net/[tcp|udp] (runtime: 0.0018)
-# [ARM_DEBUG] system call: ps -p 2354 -o %cpu,rss,%mem,etime (runtime: 0.02)
-# [ARM_DEBUG] system call: netstat -npt | grep 2354/tor (runtime: 0.02)
-# [ARM_DEBUG] recreating panel 'graph' with the dimensions of 14/124
-# [ARM_DEBUG] redrawing the log panel with the corrected content height (estimat was off by 4)
-# [ARM_DEBUG] GETINFO accounting/bytes-left (runtime: 0.0006)
-# [ARM_DEBUG] GETINFO traffic/read (runtime: 0.0004)
-# [ARM_DEBUG] GETINFO traffic/written (runtime: 0.0002)
-# [ARM_DEBUG] GETCONF MyFamily (runtime: 0.0007)
-# [ARM_DEBUG] Unable to query process resource usage from ps, waiting 6.25 seconds (unrecognized output from ps: ...)
+# [NYX_DEBUG] refresh rate: 0.001 seconds
+# [NYX_DEBUG] proc call (process connections): /proc/net/[tcp|udp] (runtime: 0.0018)
+# [NYX_DEBUG] system call: ps -p 2354 -o %cpu,rss,%mem,etime (runtime: 0.02)
+# [NYX_DEBUG] system call: netstat -npt | grep 2354/tor (runtime: 0.02)
+# [NYX_DEBUG] recreating panel 'graph' with the dimensions of 14/124
+# [NYX_DEBUG] redrawing the log panel with the corrected content height (estimat was off by 4)
+# [NYX_DEBUG] GETINFO accounting/bytes-left (runtime: 0.0006)
+# [NYX_DEBUG] GETINFO traffic/read (runtime: 0.0004)
+# [NYX_DEBUG] GETINFO traffic/written (runtime: 0.0002)
+# [NYX_DEBUG] GETCONF MyFamily (runtime: 0.0007)
+# [NYX_DEBUG] Unable to query process resource usage from ps, waiting 6.25 seconds (unrecognized output from ps: ...)
#
################################################################################
@@ -84,24 +84,24 @@ dedup.WARN I have no descriptor for the router named
dedup.WARN Controller gave us config lines that didn't validate
dedup.WARN Problem bootstrapping. Stuck at
dedup.WARN *missing key,
-dedup.ARM_DEBUG refresh rate:
-dedup.ARM_DEBUG proc call (cwd):
-dedup.ARM_DEBUG proc call (memory usage):
-dedup.ARM_DEBUG proc call (process command
-dedup.ARM_DEBUG proc call (process utime
-dedup.ARM_DEBUG proc call (process stime
-dedup.ARM_DEBUG proc call (process start time
-dedup.ARM_DEBUG proc call (process connections):
-dedup.ARM_DEBUG system call: ps
-dedup.ARM_DEBUG system call: netstat
-dedup.ARM_DEBUG recreating panel '
-dedup.ARM_DEBUG redrawing the log panel with the corrected content height (
-dedup.ARM_DEBUG GETINFO accounting/bytes
-dedup.ARM_DEBUG GETINFO accounting/bytes-left
-dedup.ARM_DEBUG GETINFO accounting/interval-end
-dedup.ARM_DEBUG GETINFO accounting/hibernating
-dedup.ARM_DEBUG GETINFO traffic/read
-dedup.ARM_DEBUG GETINFO traffic/written
-dedup.ARM_DEBUG GETCONF
-dedup.ARM_DEBUG Unable to query process resource usage from ps
+dedup.NYX_DEBUG refresh rate:
+dedup.NYX_DEBUG proc call (cwd):
+dedup.NYX_DEBUG proc call (memory usage):
+dedup.NYX_DEBUG proc call (process command
+dedup.NYX_DEBUG proc call (process utime
+dedup.NYX_DEBUG proc call (process stime
+dedup.NYX_DEBUG proc call (process start time
+dedup.NYX_DEBUG proc call (process connections):
+dedup.NYX_DEBUG system call: ps
+dedup.NYX_DEBUG system call: netstat
+dedup.NYX_DEBUG recreating panel '
+dedup.NYX_DEBUG redrawing the log panel with the corrected content height (
+dedup.NYX_DEBUG GETINFO accounting/bytes
+dedup.NYX_DEBUG GETINFO accounting/bytes-left
+dedup.NYX_DEBUG GETINFO accounting/interval-end
+dedup.NYX_DEBUG GETINFO accounting/hibernating
+dedup.NYX_DEBUG GETINFO traffic/read
+dedup.NYX_DEBUG GETINFO traffic/written
+dedup.NYX_DEBUG GETCONF
+dedup.NYX_DEBUG Unable to query process resource usage from ps
1
0
commit 7889e5e1b0ef095beba0017e92b74971437ea101
Author: Damian Johnson <atagar(a)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
"""
1
0
commit e3797bd6bcef5347f118e0208d9ed95b08b42fad
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun Apr 12 14:37:55 2015 -0700
Move log util tests to their own module
About to add some more so better to group them in a module.
---
test/util/__init__.py | 2 +-
test/util/data/malformed_date | 21 ----------
test/util/data/malformed_line | 21 ----------
test/util/data/malformed_runlevel | 21 ----------
test/util/data/multiple_tor_instances | 33 ----------------
test/util/data/tor_log | 21 ----------
test/util/log/__init__.py | 7 ++++
test/util/log/data/malformed_date | 21 ++++++++++
test/util/log/data/malformed_line | 21 ++++++++++
test/util/log/data/malformed_runlevel | 21 ++++++++++
test/util/log/data/multiple_tor_instances | 33 ++++++++++++++++
test/util/log/data/tor_log | 21 ++++++++++
test/util/log/read_tor_log.py | 59 +++++++++++++++++++++++++++++
test/util/read_tor_log.py | 59 -----------------------------
14 files changed, 184 insertions(+), 177 deletions(-)
diff --git a/test/util/__init__.py b/test/util/__init__.py
index cc6042f..a03ad4f 100644
--- a/test/util/__init__.py
+++ b/test/util/__init__.py
@@ -2,4 +2,4 @@
Unit tests for nyx's utilities.
"""
-__all__ = ['bandwidth_from_state']
+__all__ = ['log', 'tracker']
diff --git a/test/util/data/empty_file b/test/util/data/empty_file
deleted file mode 100644
index e69de29..0000000
diff --git a/test/util/data/malformed_date b/test/util/data/malformed_date
deleted file mode 100644
index 712149d..0000000
--- a/test/util/data/malformed_date
+++ /dev/null
@@ -1,21 +0,0 @@
-Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
-Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
-Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
-Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
-Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
-Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
-Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
-Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
-Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
-Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
-Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
-Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
-Zed 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
-Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
-Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
-Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/data/malformed_line b/test/util/data/malformed_line
deleted file mode 100644
index ac9a367..0000000
--- a/test/util/data/malformed_line
+++ /dev/null
@@ -1,21 +0,0 @@
-Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
-Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
-Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
-Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
-Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
-Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
-Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
-Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
-Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
-Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
-Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
-Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
-Apr 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
-Apr 06 11:03:53.000
-Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
-Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/data/malformed_runlevel b/test/util/data/malformed_runlevel
deleted file mode 100644
index dd8810b..0000000
--- a/test/util/data/malformed_runlevel
+++ /dev/null
@@ -1,21 +0,0 @@
-Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
-Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
-Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
-Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
-Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
-Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
-Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
-Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
-Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
-Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
-Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
-Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
-Apr 06 11:03:52.000 [unrecognized] Bootstrapped 90%: Establishing a Tor circuit
-Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
-Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
-Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/data/multiple_tor_instances b/test/util/data/multiple_tor_instances
deleted file mode 100644
index 1793ce5..0000000
--- a/test/util/data/multiple_tor_instances
+++ /dev/null
@@ -1,33 +0,0 @@
-Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
-Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
-Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
-Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
-Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
-Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
-Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
-Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
-Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
-Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
-Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
-Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
-Apr 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
-Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
-Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
-Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
-Apr 06 11:53:54.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening log file.
-Apr 06 11:53:54.392 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
-Apr 06 11:53:54.392 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
-Apr 06 11:53:54.392 [notice] This version is not a stable Tor release. Expect more bugs than usual.
-Apr 06 11:53:54.392 [notice] Read configuration file "/home/atagar/.tor/torrc".
-Apr 06 11:53:54.396 [notice] Opening Socks listener on 127.0.0.1:9050
-Apr 06 11:53:54.396 [notice] Opening Control listener on 127.0.0.1:9051
-Apr 06 11:53:54.000 [warn] Your log may contain sensitive information - you're logging more than "notice". Don't log unless it serves an important reason. Overwrite the log afterwards.
-Apr 06 11:53:54.000 [debug] tor_disable_debugger_attach(): Attemping to disable debugger attachment to Tor for unprivileged users.
-Apr 06 11:53:54.000 [debug] tor_disable_debugger_attach(): Debugger attachment disabled for unprivileged users.
-Apr 06 11:53:54.000 [info] tor_lockfile_lock(): Locking "/home/atagar/.tor/lock"
-Apr 06 11:53:54.000 [debug] parse_dir_authority_line(): Trusted 100 dirserver at 128.31.0.39:9131 (9695)
diff --git a/test/util/data/tor_log b/test/util/data/tor_log
deleted file mode 100644
index 0a4464e..0000000
--- a/test/util/data/tor_log
+++ /dev/null
@@ -1,21 +0,0 @@
-Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
-Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
-Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
-Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
-Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
-Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
-Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
-Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
-Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
-Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
-Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
-Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
-Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
-Apr 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
-Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
-Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
-Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
-Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/log/__init__.py b/test/util/log/__init__.py
new file mode 100644
index 0000000..b2fb6f7
--- /dev/null
+++ b/test/util/log/__init__.py
@@ -0,0 +1,7 @@
+"""
+Unit tests for nyx's log utilities.
+"""
+
+__all__ = [
+ 'read_tor_log',
+]
diff --git a/test/util/log/data/empty_file b/test/util/log/data/empty_file
new file mode 100644
index 0000000..e69de29
diff --git a/test/util/log/data/malformed_date b/test/util/log/data/malformed_date
new file mode 100644
index 0000000..712149d
--- /dev/null
+++ b/test/util/log/data/malformed_date
@@ -0,0 +1,21 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Zed 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/log/data/malformed_line b/test/util/log/data/malformed_line
new file mode 100644
index 0000000..ac9a367
--- /dev/null
+++ b/test/util/log/data/malformed_line
@@ -0,0 +1,21 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Apr 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/log/data/malformed_runlevel b/test/util/log/data/malformed_runlevel
new file mode 100644
index 0000000..dd8810b
--- /dev/null
+++ b/test/util/log/data/malformed_runlevel
@@ -0,0 +1,21 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Apr 06 11:03:52.000 [unrecognized] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/log/data/multiple_tor_instances b/test/util/log/data/multiple_tor_instances
new file mode 100644
index 0000000..1793ce5
--- /dev/null
+++ b/test/util/log/data/multiple_tor_instances
@@ -0,0 +1,33 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Apr 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
+Apr 06 11:53:54.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening log file.
+Apr 06 11:53:54.392 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:53:54.392 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:53:54.392 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:53:54.392 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:53:54.396 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:53:54.396 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:53:54.000 [warn] Your log may contain sensitive information - you're logging more than "notice". Don't log unless it serves an important reason. Overwrite the log afterwards.
+Apr 06 11:53:54.000 [debug] tor_disable_debugger_attach(): Attemping to disable debugger attachment to Tor for unprivileged users.
+Apr 06 11:53:54.000 [debug] tor_disable_debugger_attach(): Debugger attachment disabled for unprivileged users.
+Apr 06 11:53:54.000 [info] tor_lockfile_lock(): Locking "/home/atagar/.tor/lock"
+Apr 06 11:53:54.000 [debug] parse_dir_authority_line(): Trusted 100 dirserver at 128.31.0.39:9131 (9695)
diff --git a/test/util/log/data/tor_log b/test/util/log/data/tor_log
new file mode 100644
index 0000000..0a4464e
--- /dev/null
+++ b/test/util/log/data/tor_log
@@ -0,0 +1,21 @@
+Apr 06 11:03:39.000 [notice] Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.
+Apr 06 11:03:39.832 [notice] Tor v0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) running on Linux with Libevent 2.0.16-stable, OpenSSL 1.0.1 and Zlib 1.2.3.4.
+Apr 06 11:03:39.832 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
+Apr 06 11:03:39.833 [notice] This version is not a stable Tor release. Expect more bugs than usual.
+Apr 06 11:03:39.833 [notice] Read configuration file "/home/atagar/.tor/torrc".
+Apr 06 11:03:39.838 [notice] Opening Socks listener on 127.0.0.1:9050
+Apr 06 11:03:39.838 [notice] Opening Control listener on 127.0.0.1:9051
+Apr 06 11:03:39.000 [notice] Bootstrapped 0%: Starting
+Apr 06 11:03:42.000 [notice] Bootstrapped 45%: Asking for relay descriptors
+Apr 06 11:03:43.000 [notice] Bootstrapped 50%: Loading relay descriptors
+Apr 06 11:03:49.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:03:51.000 [notice] Bootstrapped 55%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 63%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 69%: Loading relay descriptors
+Apr 06 11:03:51.000 [notice] Bootstrapped 74%: Loading relay descriptors
+Apr 06 11:03:52.000 [notice] Bootstrapped 80%: Connecting to the Tor network
+Apr 06 11:03:52.000 [notice] Bootstrapped 90%: Establishing a Tor circuit
+Apr 06 11:03:53.000 [notice] Tor has successfully opened a circuit. Looks like client functionality is working.
+Apr 06 11:03:53.000 [notice] Bootstrapped 100%: Done
+Apr 06 11:03:55.000 [notice] New control connection opened from 127.0.0.1.
+Apr 06 11:53:46.000 [notice] Interrupt: exiting cleanly.
diff --git a/test/util/log/read_tor_log.py b/test/util/log/read_tor_log.py
new file mode 100644
index 0000000..7f84c41
--- /dev/null
+++ b/test/util/log/read_tor_log.py
@@ -0,0 +1,59 @@
+import os
+import unittest
+
+from nyx.util.log import LogEntry, read_tor_log
+
+
+def data_path(filename):
+ return os.path.join(os.path.dirname(__file__), 'data', filename)
+
+
+class TestReadTorLog(unittest.TestCase):
+ def test_general_log(self):
+ entries = list(read_tor_log(data_path('tor_log')))
+ self.assertEqual(21, len(entries))
+
+ self.assertEqual(LogEntry(1333738426, 'NOTICE', 'Interrupt: exiting cleanly.'), entries[0])
+ self.assertEqual(LogEntry(1333735419, 'NOTICE', 'Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.'), entries[-1])
+
+ def test_with_multiple_tor_instances(self):
+ entries = list(read_tor_log(data_path('multiple_tor_instances')))
+ self.assertEqual(12, len(entries))
+
+ self.assertEqual(LogEntry(1333738434, 'DEBUG', 'parse_dir_authority_line(): Trusted 100 dirserver at 128.31.0.39:9131 (9695)'), entries[0])
+ self.assertEqual(LogEntry(1333738434, 'INFO', 'tor_lockfile_lock(): Locking "/home/atagar/.tor/lock"'), entries[1])
+ self.assertEqual(LogEntry(1333738434, 'NOTICE', 'Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening log file.'), entries[-1])
+
+ def test_with_read_limit(self):
+ entries = list(read_tor_log(data_path('tor_log'), 5))
+ self.assertEqual(5, len(entries))
+ self.assertEqual('Interrupt: exiting cleanly.', entries[0].message)
+ self.assertEqual('Bootstrapped 90%: Establishing a Tor circuit', entries[-1].message)
+
+ def test_with_empty_file(self):
+ entries = list(read_tor_log(data_path('empty_file')))
+ self.assertEqual(0, len(entries))
+
+ def test_with_missing_path(self):
+ self.assertRaises(IOError, list, read_tor_log(data_path('no_such_path')))
+
+ def test_with_malformed_line(self):
+ try:
+ list(read_tor_log(data_path('malformed_line')))
+ self.fail("Malformed content should've raised a ValueError")
+ except ValueError as exc:
+ self.assertTrue("has a line that doesn't match the format we expect: Apr 06 11:03:53.000" in str(exc))
+
+ def test_with_malformed_runlevel(self):
+ try:
+ list(read_tor_log(data_path('malformed_runlevel')))
+ self.fail("Malformed content should've raised a ValueError")
+ except ValueError as exc:
+ self.assertTrue('has an unrecognized runlevel: [unrecognized]' in str(exc))
+
+ def test_with_malformed_date(self):
+ try:
+ list(read_tor_log(data_path('malformed_date')))
+ self.fail("Malformed content should've raised a ValueError")
+ except ValueError as exc:
+ self.assertTrue("has a timestamp we don't recognize: Zed 06 11:03:52.000" in str(exc))
diff --git a/test/util/read_tor_log.py b/test/util/read_tor_log.py
deleted file mode 100644
index 7f84c41..0000000
--- a/test/util/read_tor_log.py
+++ /dev/null
@@ -1,59 +0,0 @@
-import os
-import unittest
-
-from nyx.util.log import LogEntry, read_tor_log
-
-
-def data_path(filename):
- return os.path.join(os.path.dirname(__file__), 'data', filename)
-
-
-class TestReadTorLog(unittest.TestCase):
- def test_general_log(self):
- entries = list(read_tor_log(data_path('tor_log')))
- self.assertEqual(21, len(entries))
-
- self.assertEqual(LogEntry(1333738426, 'NOTICE', 'Interrupt: exiting cleanly.'), entries[0])
- self.assertEqual(LogEntry(1333735419, 'NOTICE', 'Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening new log file.'), entries[-1])
-
- def test_with_multiple_tor_instances(self):
- entries = list(read_tor_log(data_path('multiple_tor_instances')))
- self.assertEqual(12, len(entries))
-
- self.assertEqual(LogEntry(1333738434, 'DEBUG', 'parse_dir_authority_line(): Trusted 100 dirserver at 128.31.0.39:9131 (9695)'), entries[0])
- self.assertEqual(LogEntry(1333738434, 'INFO', 'tor_lockfile_lock(): Locking "/home/atagar/.tor/lock"'), entries[1])
- self.assertEqual(LogEntry(1333738434, 'NOTICE', 'Tor 0.2.7.0-alpha-dev (git-4247ce99e5d9b7b2) opening log file.'), entries[-1])
-
- def test_with_read_limit(self):
- entries = list(read_tor_log(data_path('tor_log'), 5))
- self.assertEqual(5, len(entries))
- self.assertEqual('Interrupt: exiting cleanly.', entries[0].message)
- self.assertEqual('Bootstrapped 90%: Establishing a Tor circuit', entries[-1].message)
-
- def test_with_empty_file(self):
- entries = list(read_tor_log(data_path('empty_file')))
- self.assertEqual(0, len(entries))
-
- def test_with_missing_path(self):
- self.assertRaises(IOError, list, read_tor_log(data_path('no_such_path')))
-
- def test_with_malformed_line(self):
- try:
- list(read_tor_log(data_path('malformed_line')))
- self.fail("Malformed content should've raised a ValueError")
- except ValueError as exc:
- self.assertTrue("has a line that doesn't match the format we expect: Apr 06 11:03:53.000" in str(exc))
-
- def test_with_malformed_runlevel(self):
- try:
- list(read_tor_log(data_path('malformed_runlevel')))
- self.fail("Malformed content should've raised a ValueError")
- except ValueError as exc:
- self.assertTrue('has an unrecognized runlevel: [unrecognized]' in str(exc))
-
- def test_with_malformed_date(self):
- try:
- list(read_tor_log(data_path('malformed_date')))
- self.fail("Malformed content should've raised a ValueError")
- except ValueError as exc:
- self.assertTrue("has a timestamp we don't recognize: Zed 06 11:03:52.000" in str(exc))
1
0