Addded new method to watch logs, but will fail if any errors are detected
@@ -4,6 +4,7 @@ from __future__ import absolute_import, with_statement
import errno
import glob
import locale
+import logging
import os
import psutil
import re
@@ -26,6 +27,8 @@ from ccmlib import common, extension
from ccmlib.repository import setup
from six.moves import xrange
+logger = logging.getLogger(__name__)
+
class Status():
UNINITIALIZED = "UNINITIALIZED"
@@ -556,6 +559,40 @@ class Node(object):
if process.returncode == 0:
return None
+ def watch_log_for_no_errors(self, exprs, from_mark=None, timeout=600, process=None, verbose=False, filename='system.log'):
+ """
+ Watch the log until one or more (regular) expression are found.
+ This methods when all the expressions have been found or the method
+ timeouts (a TimeoutError is then raised). On successful completion,
+ a list of pair (line matched, match object) is returned.
+
+ This method is different from watch_log_for since it will fail if
+ any errors are found.
+ """
+ start = time.time()
+ tofind = [exprs] if isinstance(exprs, string_types) else exprs
+ tofind = [re.compile(e) for e in tofind]
+ seek_start=0
+ if from_mark:
+ seek_start = from_mark
+ while True:
+ if start + timeout < time.time():
+ raise TimeoutError(time.strftime("%d %b %Y %H:%M:%S", time.gmtime()) + " [" + self.name + "] Missing: " + str([e.pattern for e in tofind]) + ":\n.....\nSee {} for remainder".format(filename))
+ try:
+ # process is bin/cassandra so choosing to ignore this argument to avoid early termination
+ return self.watch_log_for(to_watch, from_mark=from_mark, timeout=5, verbose=verbose, filename=filename)
+ except TimeoutError:
+ logger.debug("waited 5s watching for '{}' but was not found; checking for errors".format(to_watch))
+ # since the api doesn't return the mark read it isn't thread safe to use mark
+ # as the length of the file can change between calls which may mean we skip over
+ # errors; to avoid this keep reading the whole file over and over again...
+ # unless a explicit mark is given to the method, will read from that offset
+ errors = self.grep_log_for_errors_from(filename=filename, seek_start=seek_start)
+ if errors:
+ msg = "Errors were found in the logs while watching for '{}'; attempting to fail the test".format(to_watch)
+ logger.debug(msg)
+ raise AssertionError("{}:\n".format(msg) + '\n\n'.join(['\n'.join(msg) for msg in errors]))
+
def watch_log_for_death(self, nodes, from_mark=None, timeout=600, filename='system.log'):
"""
Watch the log of this node until it detects that the provided other
