[or-cvs] r23282: {arm} added: log panel dividers for the date (in arm/trunk: . src/interface src/interface/graphing)
Damian Johnson
atagar1 at gmail.com
Wed Sep 22 04:41:37 UTC 2010
Author: atagar
Date: 2010-09-22 04:41:37 +0000 (Wed, 22 Sep 2010)
New Revision: 23282
Modified:
arm/trunk/TODO
arm/trunk/armrc.sample
arm/trunk/src/interface/graphing/bandwidthStats.py
arm/trunk/src/interface/logPanel.py
Log:
added: log panel dividers for the date
Modified: arm/trunk/TODO
===================================================================
--- arm/trunk/TODO 2010-09-22 02:24:03 UTC (rev 23281)
+++ arm/trunk/TODO 2010-09-22 04:41:37 UTC (rev 23282)
@@ -24,6 +24,7 @@
* ask helix about steps for getting a deb and rpm included in the tor repo
* check performance of this version vs last version (general screen refresh
times)
+ * stress test under debug level and debug level with large log file
* pylint --indent-string=" " --disable-msg-cat=CR interface/foo.py | less
* double check __init__.py and README for changes
@@ -58,6 +59,10 @@
- http://www.linuxjournal.com/article/5737
- Bugs
+ * there seems to be an issue merging tor and arm events by timestamp for long
+ running instances (probably a bug with determing the day of prepopulated
+ events)
+ * when in client mode and tor stops the header panel doesn't say so
* util are assuming that tor is running under the default command name
attempt to determine the command name at runtime (if the pid is available
then ps can do the mapping)
Modified: arm/trunk/armrc.sample
===================================================================
--- arm/trunk/armrc.sample 2010-09-22 02:24:03 UTC (rev 23281)
+++ arm/trunk/armrc.sample 2010-09-22 04:41:37 UTC (rev 23282)
@@ -20,6 +20,7 @@
features.log.prepopulate true
features.log.prepopulateReadLimit 5000
features.log.maxRefreshRate 300
+features.log.showDateDividers true
# general graph parameters
# height: height of graphed stats
Modified: arm/trunk/src/interface/graphing/bandwidthStats.py
===================================================================
--- arm/trunk/src/interface/graphing/bandwidthStats.py 2010-09-22 02:24:03 UTC (rev 23281)
+++ arm/trunk/src/interface/graphing/bandwidthStats.py 2010-09-22 04:41:37 UTC (rev 23282)
@@ -107,8 +107,7 @@
missingReadEntries, missingWriteEntries = None, None
# converts from gmt to local with respect to DST
- if time.localtime()[8]: tz_offset = time.altzone
- else: tz_offset = time.timezone
+ tz_offset = time.altzone if time.localtime()[8] else time.timezone
for line in stateFile:
line = line.strip()
Modified: arm/trunk/src/interface/logPanel.py
===================================================================
--- arm/trunk/src/interface/logPanel.py 2010-09-22 02:24:03 UTC (rev 23281)
+++ arm/trunk/src/interface/logPanel.py 2010-09-22 04:41:37 UTC (rev 23282)
@@ -33,8 +33,9 @@
RUNLEVELS = ["DEBUG", "INFO", "NOTICE", "WARN", "ERR"]
RUNLEVEL_EVENT_COLOR = {"DEBUG": "magenta", "INFO": "blue", "NOTICE": "green", "WARN": "yellow", "ERR": "red"}
+DAYBREAK_EVENT = "DAYBREAK" # special event for marking when the date changes
-DEFAULT_CONFIG = {"features.log.prepopulate": True, "features.log.prepopulateReadLimit": 5000, "features.log.maxRefreshRate": 300, "cache.logPanel.size": 1000, "log.logPanel.prepopulateSuccess": log.INFO, "log.logPanel.prepopulateFailed": log.WARN}
+DEFAULT_CONFIG = {"features.log.prepopulate": True, "features.log.prepopulateReadLimit": 5000, "features.log.maxRefreshRate": 300, "features.log.showDateDividers": True, "cache.logPanel.size": 1000, "log.logPanel.prepopulateSuccess": log.INFO, "log.logPanel.prepopulateFailed": log.WARN}
def expandEvents(eventAbbr):
"""
@@ -214,6 +215,34 @@
log.log(DEFAULT_CONFIG["log.logPanel.prepopulateSuccess"], msg)
return loggedEvents
+def getDaybreaks(events):
+ """
+ Provides the input events back with special 'DAYBREAK_EVENT' markers inserted
+ whenever the date changed between log entries (or since the most recent
+ event). The timestamp matches the beginning of the day for the following
+ entry.
+
+ Arguments:
+ events - chronologically ordered listing of events
+ """
+
+ if not events: return []
+
+ newListing = []
+ timezoneOffset = time.altzone if time.localtime()[8] else time.timezone
+ lastDay = int((time.time() - timezoneOffset) / 86400)
+
+ for entry in events:
+ eventDay = int((entry.timestamp - timezoneOffset) / 86400) # days since epoch
+ if eventDay != lastDay:
+ markerTimestamp = (eventDay * 86400) + timezoneOffset
+ newListing.append(LogEntry(markerTimestamp, DAYBREAK_EVENT, "", "white"))
+
+ newListing.append(entry)
+ lastDay = eventDay
+
+ return newListing
+
class LogEntry():
"""
Individual log file entry, having the following attributes:
@@ -342,7 +371,6 @@
self._isPaused = False
self._pauseBuffer = [] # location where messages are buffered if paused
- self._isChanged = False # if true, has new event(s) since last drawn if true
self._lastUpdate = -1 # time the content was last revised
self._halt = False # terminates thread if true
self._cond = threading.Condition() # used for pausing/resuming the thread
@@ -352,13 +380,16 @@
self.valsLock = threading.RLock()
# cached parameters (invalidated if arguments for them change)
+ # last set of events we've drawn with
+ self._lastLoggedEvents = []
+
# _getTitle (args: loggedEvents, regexFilter pattern, width)
self._titleCache = None
self._titleArgs = (None, None, None)
- # _getContentLength (args: msgLog, regexFilter pattern, height, width)
+ # _getContentLength (args: msgLog, regexFilter pattern, height, width, day)
self._contentLengthCache = None
- self._contentLengthArgs = (None, None, None, None)
+ self._contentLengthArgs = (None, None, None, None, None)
# fetches past tor events from log file, if available
torEventBacklog = []
@@ -428,7 +459,6 @@
# notifies the display that it has new content
if not self.regexFilter or self.regexFilter.search(event.getDisplayMessage()):
- self._isChanged = True
self._cond.acquire()
self._cond.notifyAll()
self._cond.release()
@@ -501,6 +531,9 @@
If true, prevents message log from being updated with new events.
"""
+ # TODO: minor bug - if the date changes and the panel is redrawn then the
+ # new date marker is shown
+
if isPause == self._isPaused: return
self._isPaused = isPause
@@ -518,7 +551,7 @@
"""
self.valsLock.acquire()
- self._isChanged, self._lastUpdate = False, time.time()
+ self._lastLoggedEvents, self._lastUpdate = list(self.msgLog), time.time()
# draws the top label
self.addstr(0, 0, self._getTitle(width), curses.A_STANDOUT)
@@ -535,20 +568,36 @@
# draws log entries
lineCount = 1 - self.scroll
- for entry in self.msgLog:
+ eventLog = getDaybreaks(self.msgLog) if self._config["features.log.showDateDividers"] else self.msgLog
+ for entry in eventLog:
if self.regexFilter and not self.regexFilter.search(entry.getDisplayMessage()):
continue # filter doesn't match log message - skip
- for line in entry.getDisplayMessage().split("\n"):
- # splits over too lines if too long
- if len(line) < width:
- if lineCount >= 1: self.addstr(lineCount, xOffset, line, uiTools.getColor(entry.color))
- lineCount += 1
- else:
- (line1, line2) = uiTools.splitLine(line, width - xOffset)
- if lineCount >= 1: self.addstr(lineCount, xOffset, line1, uiTools.getColor(entry.color))
- if lineCount >= 0: self.addstr(lineCount + 1, xOffset, line2, uiTools.getColor(entry.color))
- lineCount += 2
+ if entry.type == DAYBREAK_EVENT:
+ # show a divider with the date
+ if lineCount >= 1:
+ dividerAttr = curses.A_BOLD | uiTools.getColor("yellow")
+ timeLabel = time.strftime(" %B %d, %Y ", time.localtime(entry.timestamp))
+ self.win.vline(lineCount, xOffset - 1, curses.ACS_ULCORNER | dividerAttr, 1)
+ self.win.hline(lineCount, xOffset, curses.ACS_HLINE | dividerAttr, 2)
+ self.addstr(lineCount, xOffset + 2, timeLabel, curses.A_BOLD | dividerAttr)
+
+ lineLength = width - xOffset - len(timeLabel) - 2
+ self.win.hline(lineCount, xOffset + len(timeLabel) + 2, curses.ACS_HLINE | dividerAttr, lineLength)
+ self.win.vline(lineCount, xOffset + len(timeLabel) + 2 + lineLength, curses.ACS_URCORNER | dividerAttr, 1)
+
+ lineCount += 1
+ else:
+ for line in entry.getDisplayMessage().split("\n"):
+ # splits over too lines if too long
+ if len(line) < width:
+ if lineCount >= 1: self.addstr(lineCount, xOffset, line, uiTools.getColor(entry.color))
+ lineCount += 1
+ else:
+ (line1, line2) = uiTools.splitLine(line, width - xOffset)
+ if lineCount >= 1: self.addstr(lineCount, xOffset, line1, uiTools.getColor(entry.color))
+ if lineCount >= 0: self.addstr(lineCount + 1, xOffset, line2, uiTools.getColor(entry.color))
+ lineCount += 2
if lineCount >= height: break # further log messages wouldn't fit
@@ -565,13 +614,20 @@
responsive if additions are less frequent.
"""
+ timezoneOffset = time.altzone if time.localtime()[8] else time.timezone
+ currentTime = time.time()
+
+ # unix time for the start of the current day (local time), used so we
+ # can redraw when the date changes
+ dayStartTime = currentTime - (currentTime - timezoneOffset) % 86400
while not self._halt:
- timeSinceReset = time.time() - self._lastUpdate
+ currentTime = time.time()
+ timeSinceReset = currentTime - self._lastUpdate
maxLogUpdateRate = self._config["features.log.maxRefreshRate"] / 1000.0
sleepTime = 0
- if not self._isChanged or self._isPaused:
- sleepTime = 10
+ if (self.msgLog == self._lastLoggedEvents and currentTime < dayStartTime + 86401) or self._isPaused:
+ sleepTime = 5
elif timeSinceReset < maxLogUpdateRate:
sleepTime = max(0.05, maxLogUpdateRate - timeSinceReset)
@@ -580,6 +636,7 @@
if not self._halt: self._cond.wait(sleepTime)
self._cond.release()
else:
+ dayStartTime = currentTime - (currentTime - timezoneOffset) % 86400
self.redraw(True)
def stop(self):
@@ -696,6 +753,11 @@
taking into account filtered/wrapped lines, the scroll bar, etc.
"""
+ if self._config["features.log.showDateDividers"]:
+ timezoneOffset = time.altzone if time.localtime()[8] else time.timezone
+ currentDay = int((time.time() - timezoneOffset) / 86400)
+ else: currentDay = 0
+
# if the arguments haven't changed then we can use cached results
self.valsLock.acquire()
height, width = self.getPreferredSize()
@@ -704,12 +766,14 @@
isUnchanged &= self._contentLengthArgs[1] == currentPattern
isUnchanged &= self._contentLengthArgs[2] == height
isUnchanged &= self._contentLengthArgs[3] == width
+ isUnchanged &= self._contentLengthArgs[4] == currentDay
if isUnchanged:
self.valsLock.release()
return self._contentLengthCache
contentLengths = [0, 0] # length of the content without and with a scroll bar
- for entry in self.msgLog:
+ eventLog = getDaybreaks(self.msgLog) if self._config["features.log.showDateDividers"] else self.msgLog
+ for entry in eventLog:
if not self.regexFilter or self.regexFilter.search(entry.getDisplayMessage()):
for line in entry.getDisplayMessage().split("\n"):
if len(line) >= width: contentLengths[0] += 2
@@ -722,7 +786,7 @@
actualLength = contentLengths[0] if contentLengths[0] <= height - 1 else contentLengths[1]
self._contentLengthCache = actualLength
- self._contentLengthArgs = (list(self.msgLog), currentPattern, height, width)
+ self._contentLengthArgs = (list(self.msgLog), currentPattern, height, width, currentDay)
self.valsLock.release()
return actualLength
More information about the tor-commits
mailing list