def testWillMarkforSpecifiedTimeandNotAfterwards(self): level = 'FATAL' trace = "FATAL there could be an error in the application" sys.stdout = Writer() logcolors = LogColors() termcolors = TermColorCodes() message = Message(logcolors) notifier = notifications.CornerMark(0.01) anylog = Log('out.log') message.parse(trace, anylog) termcols = os.popen("tput cols") ttcols = termcols.readline() termcols.close() ttcols = int(ttcols) padding = ttcols - len(notifier.MARK) output = padding * " " + termcolors.backgroundemph + notifier.MARK +\ termcolors.reset notifier.notify(message, anylog) self.assertEqual(output, sys.stdout.captured[0]) trace = "INFO this is an info trace" sys.stdout.flush() time.sleep(0.02) message.parse(trace, anylog) notifier.notify(message, anylog) self.assertFalse(sys.stdout.captured)
def testMarkedTARGETOverMarkableLevel(self): configfile = CONFIG logfile = "/any/path/out.log" trace = "this is a FATAL targeted log trace" fh = open(configfile, 'w') fh.write("targets "+logfile+"=targeted\n") fh.close() properties = Property(configfile) properties.parse_properties() sys.stdout = Writer() logcolors = LogColors() termcolors = TermColorCodes() notifier = notifications.CornerMark(0.02) anylog = Log(logfile, properties) message = Message(logcolors, properties = properties) termcols = os.popen("tput cols") ttcols = termcols.readline() termcols.close() ttcols = int(ttcols) padding = ttcols - len(notifier.MARK) output = padding * " " + termcolors.oncyanemph + notifier.MARK +\ termcolors.reset message.parse(trace, anylog) notifier.notify(message, anylog) self.assertEqual(output, sys.stdout.captured[0])
def testReportToAFile(self): reportfileFullPath = "reportfile.txt" fh = open('aconfig','w') fh.write('analyticsnotification = '+ reportfileFullPath +'\n') fh.write('analyticsgaptime = 0.1\n') fh.close() properties = Property('aconfig') properties.parse_properties() self.assertTrue(properties.is_key('analyticsnotification')) log = Log('out.log') arrayLog = [log] resume = reporting.Resume(arrayLog) resume.setAnalyticsGapNotification(0.1) resume.notification_type(reportfileFullPath) fh = open('out.log') lines = fh.readlines() fh.close() logcolors = LogColors() msg = Message(logcolors) time.sleep(0.1) for line in lines: msg.parse(line, log) resume.update(msg, log) fh = open(reportfileFullPath) reportlength = len(fh.readlines()) fh.close() os.remove(reportfileFullPath) self.assertEquals(22, reportlength) os.remove('aconfig')
def testShouldExecuteIfTargetMessage(self): logcolor = LogColors() logfile = 'anylog' log = Log(logfile) fh = open(CONFIG, 'w') fh.write("executor = echo ' %s %s '\n") fh.close() trace = "this is an info log trace" trigger = ['echo', trace, logfile] properties = Property(CONFIG) properties.parse_properties() message = Message(logcolor, target = 'trace') executor_mock = self.mocker.mock() executor_mock._build_trigger(trace, logfile) self.mocker.result(trigger) executor_mock.started self.mocker.result(True) landing_mock = self.mocker.mock() landing_mock.landing(trigger) self.mocker.result(True) executor_mock.trigger_executor self.mocker.result(landing_mock) self.mocker.replay() message.parse(trace, log) self.assertTrue(message.isATarget()) notifications.Executor.notify.im_func(executor_mock, message, log)
def pipeOut(self): """Reads from standard input and prints to standard output""" message = Message(self.logcolors, self.loglevels, self.target, self.properties) stdin = sys.stdin anylog = Log('anylog') for line in stdin: message.parse(line, anylog) for action in self.actions: action.notify(message, anylog)
def testnoNotification(self): pattern = re.compile(r'hi, this line to be notified') trace = "info this is just a log trace" notifier = notifications.Filter(pattern) sys.stdout = Writer() logcolors = LogColors() message = Message(logcolors) anylog = Log('out.log') message.parse(trace, anylog) notifier.notify(message, anylog) # assert is empty self.assertFalse(sys.stdout.captured)
def testshouldNotColorizeifLevelKeyInaWord(self): # Testing boundary regex as for suggestion of # Carlo Bertoldi trace = "this is a logtrace where someinfoword could be found" sys.stdout = Writer() logcolors = LogColors() message = Message(logcolors) notifier = notifications.Print() anylog = Log('out.log') message.parse(trace, anylog) notifier.notify(message,anylog) self.assertEqual(trace, sys.stdout.captured[0]) self.assertEqual('', message.messageLevel)
def testshouldFailColorizeWithBackground(self): trace = "FATAL there could be an error in the application" level = 'WARN' sys.stdout = Writer() logcolors = LogColors() termcolors = TermColorCodes() logcolors.parse_config(PropertiesBackGround()) message = Message(logcolors) notifier = notifications.Print() anylog = Log('out.log') message.parse(trace, anylog) output = logcolors.getLevelColor(level)+trace+termcolors.reset notifier.notify(message,anylog) self.assertNotEqual(output, sys.stdout.captured[0])
def testShouldColorizeWarningLevelAsWell(self): '''test that *warning* keyword gets colorized as well''' level = 'WARNING' trace = "WARNING there could be an error in the application" sys.stdout = Writer() logcolors = LogColors() termcolors = TermColorCodes() message = Message(logcolors) notifier = notifications.Print() anylog = Log('out.log') message.parse(trace, anylog) output = logcolors.getLevelColor(level)+trace+termcolors.reset notifier.notify(message,anylog) self.assertEqual(output, sys.stdout.captured[0])
def testnotify(self): pattern = re.compile(r'hi, this line to be notified') trace = "info hi, this line to be notified" level = "INFO" notifier = notifications.Filter(pattern) sys.stdout = Writer() logcolors = LogColors() termcolors = TermColorCodes() message = Message(logcolors) anylog = Log('out.log') message.parse(trace, anylog) notifier.notify(message, anylog) output = logcolors.getLevelColor(level)+trace+termcolors.reset self.assertEqual(output, sys.stdout.captured[0])
def testshouldColorizefirstLevelFoundignoringSecondinSameTrace(self): # Test for fix 5 # Should give priority to FATAL in next trace level = 'FATAL' trace = "FATAL there could be an error in the application" sys.stdout = Writer() logcolors = LogColors() termcolors = TermColorCodes() message = Message(logcolors) notifier = notifications.Print() anylog = Log('out.log') message.parse(trace, anylog) output = logcolors.getLevelColor(level)+trace+termcolors.reset notifier.notify(message,anylog) self.assertEqual(output, sys.stdout.captured[0])
def testShouldContinueIfExecutorFails(self): logcolor = LogColors() message = Message(logcolor) log = Log('anylog') fh = open(CONFIG, 'w') fh.write('executor = anycommand\n') fh.close() trace = "this is a critical log trace" properties = Property(CONFIG) properties.parse_properties() executor = notifications.Executor(properties) message.parse(trace, log) executor.notify(message, log) time.sleep(0.0002) executor.stop()
def testShouldNotExecuteIfLevelNotInPullers(self): logcolor = LogColors() message = Message(logcolor) log = Log('anylog') fh = open(CONFIG, 'w') fh.write('executor = anything %s %s\n') fh.close() trace = "this is an info log trace" properties = Property(CONFIG) properties.parse_properties() executor = notifications.Executor(properties) message.parse(trace, log) executor.notify(message, log) time.sleep(0.0002) executor.stop() self.assertFalse(sys.stdout.captured)
def testShouldNotifyWithNoFullTrigger(self): logcolor = LogColors() message = Message(logcolor) log = Log('anylog') logpath = log.path fh = open(CONFIG, 'w') fh.write('executor = echo\n') fh.close() trace = "this is a fatal log trace" properties = Property(CONFIG) properties.parse_properties() executor = notifications.Executor(properties) message.parse(trace, log) trigger = executor._build_trigger(trace, logpath) self.assertEqual(['echo'], trigger) executor.notify(message, log) executor.stop()
def tailer(self): """Stdout multicolor tailer""" message = Message(self.logcolors, self.loglevels, self.target, self.properties) anylog = Log("anylog") for hostname in self.hostnames.keys(): command = self.hostnames[hostname]["command"] self.logger.debug("command [%s] to be executed in host [%s]" % (command, hostname)) self.hostnameChannels[hostname]["channel"].exec_command(command) try: lasthostnameChanged = "" while True: for hostname in self.hostnames.keys(): sshChannel = self.hostnameChannels[hostname]["channel"] rr, _, _ = select.select([sshChannel], [], [], 0.0) if len(rr) > 0: lines = sshChannel.recv(4096).split("\n") if hostname != lasthostnameChanged: self.__hostnameChangedHeader(hostname) for line in lines: message.parse(line, anylog) self.actions.notify(message, anylog) lasthostnameChanged = hostname time.sleep(1) except: print "\nfinishing ..." for hostname in self.hostnames.keys(): sshChannel = self.hostnameChannels[hostname]["channel"] sshclient = self.hostnameChannels[hostname]["client"] command = self.hostnames[hostname]["command"] procidCommand = "pgrep -f -x " + '"' + command + '"' self.logger.debug("procid command [%s]" % procidCommand) sshChannel.close() stdin, stdout, stderr = sshclient.exec_command(procidCommand) res = stdout.readlines() if res: procid = res[0].rstrip() self.logger.debug("procid [%s]" % procid) # is process still alive after closing channel? if procid: # kill it killprocid = "kill -9 " + procid stdin, stdout, stderr = sshclient.exec_command(killprocid) # sshChannel.shutdown(2) sshclient.close() print "Ended log4tailer, because colors are fun" sys.exit()
def testShouldContinueTailingIfExecutableTakesLongTime(self): logcolor = LogColors() message = Message(logcolor) log = Log('anylog') fh = open(CONFIG, 'w') fh.write('executor = ' + EXECUTABLE +'\n') fh.close() trace = "this is an error log trace" properties = Property(CONFIG) properties.parse_properties() executor = notifications.Executor(properties) message.parse(trace, log) start = time.time() executor.notify(message, log) finished = time.time() ellapsed = start - finished time.sleep(0.0002) executor.stop() # executable.py sleeps for three seconds self.assertTrue(ellapsed < 0.1)
def testMarkedFATALMarkedWARNING(self): termcols = os.popen("tput cols") ttcols = termcols.readline() termcols.close() trace = "FATAL this is a fatal trace" sys.stdout = Writer() logcolors = LogColors() termcolors = TermColorCodes() message = Message(logcolors) notifier = notifications.CornerMark(0.02) anylog = Log('out.log') message.parse(trace, anylog) notifier.notify(message, anylog) ttcols = int(ttcols) padding = ttcols - len(notifier.MARK) output = padding * " " + termcolors.onyellowemph + notifier.MARK +\ termcolors.reset trace = "WARN this is just a warn" message.parse(trace, anylog) notifier.notify(message, anylog) self.assertEquals(output, sys.stdout.captured[2])
def testShouldNotifyWithFullTrigger(self): logcolor = LogColors() message = Message(logcolor) log = Log('anylog') fh = open(CONFIG, 'w') fh.write('executor = ls -l %s %s\n') fh.close() trace = "this is a FATAL log trace" trigger = ['ls', '-l', trace, log.path ] properties = Property(CONFIG) properties.parse_properties() os_mock = self.mocker.replace('subprocess') os_mock.call(' '.join(trigger), shell = True) self.mocker.result(True) self.mocker.replay() # we just verify the trigger gets # called in the tearDown executor = notifications.Executor(properties) message.parse(trace, log) executor.notify(message, log) time.sleep(0.0002) executor.stop()
def test_shouldPost_if_alertable(self): properties = self.mocker.mock() properties.get_value('server_url') self.mocker.result('localhost') properties.get_value('server_port') self.mocker.result(8000) properties.get_value('server_service_uri') self.mocker.result('/') properties.get_value('server_service_register_uri') self.mocker.result('/register') properties.get_value('server_service_unregister_uri') self.mocker.result('/unregister') logcolors = LogColors() logtrace = 'this is an error log trace' log = Log('anylog') message = Message(logcolors) message.parse(logtrace, log) self.mocker.replay() poster = notifications.Poster(properties) require_server() response = poster.notify(message, log) self.assertEqual(response.status, 200)
def test_not_execute_if_not_alertable_Level(self): properties = self.mocker.mock() properties.get_value('server_url') self.mocker.result('localhost') properties.get_value('server_port') self.mocker.result(8000) properties.get_value('server_service_uri') self.mocker.result('/') properties.get_value('server_service_register_uri') self.mocker.result('/register') properties.get_value('server_service_unregister_uri') self.mocker.result('/unregister') logcolors = LogColors() logtrace = 'this is an info log trace' log = Log('anylog') message = Message(logcolors, target = 'anything') message.parse(logtrace, log) self.mocker.replay() poster = notifications.Poster(properties) poster.registered_logs[log] = True response = poster.notify(message, log) self.assertFalse(response)
def test_printandshoot(self): sys.stdout = Writer() log_traces = ['this is an info log trace', 'this is a fatal log trace'] log = Log('anylog') logcolors = LogColors() output = 'picture.png' propertiesmock = self.mocker.mock() propertiesmock.get_value('screenshot') self.mocker.result(output) self.mocker.replay() printandshoot = notifications.PrintShot(propertiesmock) message = Message(logcolors) for trace in log_traces: message.parse(trace, log) printandshoot.notify(message, log) found = False for msg in sys.stdout.captured: if msg.find(log_traces[1]) >= 0: found = True if not found: self.fail() self.assertTrue(os.path.exists(self.output))
def testMessage(self): logcolors = LogColors() #using default colors termcolors = TermColorCodes() target = None notifier = notifications.Print() message = Message(logcolors,target) log = Log(self.logfile) log.openLog() sys.stdout = Writer() #testing Colors with default pauseModes for count in range(len(self.someLogTraces)): line = log.readLine() line = line.rstrip() level = line.split('>') message.parse(line, log) output = logcolors.getLevelColor(level[0])+line+termcolors.reset notifier.notify(message,log) self.assertTrue(output in sys.stdout.captured) line = log.readLine() self.assertEqual('',line) message.parse(line, log) self.assertFalse(notifier.notify(message,log))
def printLastNLines(self,n): '''tail -n numberoflines method in pager mode''' message = Message(self.logcolors, self.loglevels) action = notifications.Print() for log in self.arrayLog: fd = log.openLog() numlines = log.numLines() pos = numlines-n count = 0 buff = [] ttlines = get_term_lines() for curpos,line in enumerate(fd): if curpos >= pos: line = line.rstrip() message.parse(line, log) action.notify(message, log) count += 1 buff.append(line) if (count % ttlines) == 0: raw_input("continue\n") count = 0 ttlines = get_term_lines() log.closeLog()
def testshouldColorizeMultilineLogTraces(self): trace = 'FATAL> something went wrong\nin here as well' trace0, trace1 = trace.split('\n') level = 'FATAL' termcolors = TermColorCodes() # now assert trace0 and trace1 are in FATAL level sys.stdout = Writer() logcolors = LogColors() message = Message(logcolors) notifier = notifications.Print() anylog = Log('out.log') expectedLogTrace0 = logcolors.getLevelColor(level) + \ trace0 + termcolors.reset expectedLogTrace1 = logcolors.getLevelColor(level) + \ trace1 + termcolors.reset message.parse(trace0, anylog) notifier.notify(message, anylog) self.assertEqual(expectedLogTrace0, sys.stdout.captured[0]) self.assertEqual('FATAL', message.messageLevel) message.parse(trace1, anylog) notifier.notify(message, anylog) self.assertEqual(expectedLogTrace1, sys.stdout.captured[2]) self.assertEqual('FATAL', message.messageLevel)
def testShouldReportaLogOwnTarget(self): logfile = "/any/path/outtarget.log" configfile = "aconfig.txt" logcolors = LogColors() fh = open(configfile, 'w') fh.write("targets "+logfile+" = should\n") fh.close() properties = Property(configfile) properties.parse_properties() mylog = Log(logfile, properties) optional_params = (None, True, logfile) self.assertEqual(optional_params, (mylog.ownOutputColor, mylog.patTarget, mylog.path)) arraylogs = [mylog] resume = reporting.Resume(arraylogs) message = Message(logcolors, properties = properties) logtrace = "log trace info target should be reported" message.parse(logtrace, mylog) resume.update(message, mylog) outLogReport = resume.logsReport[mylog.path] numofTargets = 1 gotnumTargets = outLogReport['TARGET'] self.assertEquals(numofTargets, gotnumTargets)
def tailer(self): '''Stdout multicolor tailer''' message = Message(self.logcolors,self.loglevels, self.target,self.properties) resume = self.resumeBuilder() self.posEnd() get_log_lines = "readLines" if self.throttleTime: get_log_lines = "readLine" if self.silence: daemonize() try: self.__initialize(message) lastLogPathChanged = "" curpath = "" while True: found = 0 time.sleep(self.throttleTime) for log in self.arrayLog: curpath = log.path if hasRotated(log): found = 0 lines = getattr(log, get_log_lines)() if not lines: # notify actions message.parse('', log) resume.update(message, log) self.notifyActions(message, log) continue if isinstance(lines, str): lines = [lines] for line in lines: found = 1 line = line.rstrip() # to emulate the tail command if curpath != lastLogPathChanged: print _printHeaderLog(log.path) lastLogPathChanged = log.path message.parse(line, log) resume.update(message, log) self.notifyActions(message, log) log.size = log.getcurrSize() if found == 0: #sleep for 1 sec time.sleep(self.pause) except (KeyboardInterrupt, OSError, IOError): for log in self.arrayLog: log.closeLog() if self.mailAction: self.mailAction.quitSMTP() for action in self.actions: # executor notification if hasattr(action, 'stop'): action.stop() # post notification if hasattr(action, 'unregister'): for log in self.arrayLog: action.unregister(log) print "\n" resume.report() print "Ended log4tailer, because colors are fun"