summaryrefslogtreecommitdiffstats
path: root/src/fluent-bit/lib/monkey/qa/checklog
diff options
context:
space:
mode:
Diffstat (limited to 'src/fluent-bit/lib/monkey/qa/checklog')
-rwxr-xr-xsrc/fluent-bit/lib/monkey/qa/checklog239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/fluent-bit/lib/monkey/qa/checklog b/src/fluent-bit/lib/monkey/qa/checklog
new file mode 100755
index 000000000..f1df314aa
--- /dev/null
+++ b/src/fluent-bit/lib/monkey/qa/checklog
@@ -0,0 +1,239 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2010, Eduardo Silva <edsiper@gmail.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import os
+import sys
+import re
+import getopt
+import ConfigParser
+
+RULES_PATH = 'log_rules'
+ACCESS_FILE = '../logs/access.log'
+ERROR_FILE = '../logs/error.log'
+
+class AccessRule:
+ def __init__(self,
+ ip = None, time = None,
+ method = None, uri = None,
+ protocol = None, status = None,
+ size = None):
+
+ self.type = 'access'
+ self.ip = ip
+ self.time = time
+ self.method = method
+ self.uri = uri
+ self.status = status
+ self.protocol = protocol
+ self.status = status
+
+ if size is not None:
+ if size.isdigit():
+ self.size = size
+ else:
+ if size[:8] == 'FILESIZE':
+ target = size[8:].strip()
+ self.size = os.path.getsize(target)
+ else:
+ self.size = size
+ else:
+ self.size = size
+
+class ErrorRule:
+ def __init__(self,
+ ip = None, time = None,
+ error = None, message = None):
+
+ self.type = 'error'
+ self.ip = ip
+ self.time = time
+ self.error = error
+ self.message = message
+
+class Config(ConfigParser.ConfigParser):
+ def __init__(self):
+ ConfigParser.ConfigParser.__init__(self)
+
+ def _get_value(self, section, key):
+ try:
+ value = self.get(section, key)
+ except:
+ value = None
+
+ return value
+
+ def get_rules(self, path):
+ self.read(path)
+
+ rules = []
+ for section in self.sections():
+ if section == 'access':
+ ip = self._get_value(section, 'ip')
+ time = self._get_value(section, 'time')
+ method = self._get_value(section, 'method')
+ uri = self._get_value(section, 'uri')
+ protocol = self._get_value(section, 'protocol')
+ status = self._get_value(section, 'status')
+ size = self._get_value(section, 'size')
+
+ rule = AccessRule(ip, time, method, uri, protocol, status, size)
+
+ elif section == 'error':
+ ip = self._get_value(section, 'ip')
+ time = self._get_value(section, 'time')
+ error = self._get_value(section, 'error')
+ message = self._get_value(section, 'message')
+
+ rule = ErrorRule(ip, time, error, message)
+
+ # Add rule to list
+ rules.append(rule)
+
+ return rules
+
+class Logfile:
+
+ def __init__(self):
+ self.silent_mode = False
+ self.target_logfile = None
+
+ self.check_arguments()
+
+ # Check if file exists
+ if os.path.isfile(self.target_logfile) is False:
+ # No rules exists for this test
+ if self.silent_mode is False:
+ print "No rules for target"
+ exit(2)
+
+ # Read rules
+ config = Config()
+ rules = config.get_rules(self.target_logfile)
+
+ if len(rules) == 0:
+ if self.silent_mode is False:
+ print "Error, no rules found on target file"
+ exit(2)
+
+ # Check rules
+ self.check_rules(rules)
+
+ def check_arguments(self):
+ optlist, args = getopt.getopt(sys.argv[1:], 'shl:')
+ for key, val in optlist:
+ if key == '-s':
+ self.silent_mode = True
+ elif key == '-l':
+ self.target_logfile = val
+ elif key == '-h':
+ self.help()
+
+ if self.target_logfile is None:
+ self.help()
+
+ def help(self):
+ print "** Monkey QA Checklog **"
+ print "Usage: ./checklog [-s] [-l logfile_rules]"
+ print "\nAvailable options"
+ print " -s Run checklog in silent mode, no messages to stdout"
+ print " -l logfile Specify the logfile rule"
+ print " -h Show this help"
+ print
+ exit(1)
+
+ def get_last_file_line(self, file):
+ f = open(file, 'r')
+ lines = f.readlines()
+ f.close()
+
+ if len(lines) < 1:
+
+ return None
+
+ # get last file line
+ last = lines[len(lines) - 1]
+ return last
+
+ def check_field(self, rule, log):
+ if rule is not None:
+ if str(rule) != str(log):
+ if self.silent_mode is False:
+ print "Rule does not match, expect '" + str(rule) + '\' got \'' + log + '\''
+ exit(1)
+ else:
+ return 0
+ else:
+ return 0
+
+ def check_rules(self, rules):
+ # Parse access log format, anyone is invited to fix this nasty regex
+ access_re = re.compile("^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})( - )(\[.*\])( .* ){1,4}(/.* )(.*/.* )(\d.* )(.*)\n$")
+ error_re = re.compile("^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})( - )(\[.*\])( \[.*\])(.*)$")
+
+ for r in rules:
+ if r.type == 'access':
+ line = self.get_last_file_line(ACCESS_FILE)
+ fields = access_re.split(line)
+
+ data = {'ip': fields[1],
+ 'time': fields[3],
+ 'method': fields[4].strip(),
+ 'uri': fields[5].strip(),
+ 'protocol': fields[6].strip(),
+ 'status': fields[7].strip(),
+ 'size': fields[8]
+ }
+
+ self.check_field(r.ip, data['ip'])
+ self.check_field(r.time, data['time'])
+ self.check_field(r.method, data['method'])
+ self.check_field(r.uri, data['uri'])
+ self.check_field(r.protocol, data['protocol'])
+ self.check_field(r.status, data['status'])
+ self.check_field(r.size, data['size'])
+
+ elif r.type == 'error':
+ line = self.get_last_file_line(ERROR_FILE)
+ fields = error_re.split(line)
+
+ # We always expect at least 4 fields
+ if len(fields) < 4:
+ if self.silent_mode is False:
+ print "Error: we did not find the expected fields"
+ print "Logfile line"
+ print " %s " % line
+ exit(1)
+
+ data = {'ip': fields[1],
+ 'time': fields[3],
+ 'error': fields[4].strip('[error (\d)]'),
+ 'message': fields[5].strip()
+ }
+
+ self.check_field(r.ip, data['ip'])
+ self.check_field(r.time, data['time'])
+ self.check_field(r.error, data['error'])
+ self.check_field(r.message, data['message'])
+
+
+ if self.silent_mode is False:
+ print "Check passed :)"
+
+if __name__ == '__main__':
+ Logfile()
+