#!/usr/bin/python3 

import re, sys, os, time, getopt, socket
if sys.version_info[0]>2:
  from urllib.request import urlopen, URLError
  from io import BytesIO as StringIO
else:
  from urllib2 import urlopen, URLError
  from StringIO import StringIO

LOGDIR="/var/log/nagios/httpd-status"

show_states = list("_RWCD")
states = dict(
  _ = "waiting",
  S = "starting",
  R = "reading",
  W = "sending",
  K = "keepalive",
  D = "dns_lookup",
  C = "closing",
  L = "logging",
  G = "finishing",
  I = "idle",
  # lighttpd
  E = "error",
  # nginx
  A = "active"
)
states["."] = "open_slot"

apache2lighttpd = dict(
  W = "h",
  R = "r",
  S = "W",
  #h = "W",
  #r = "R",
  #q = "R",
  #Q = "R",
  #s = "W",
  #S = "W"
)

si = dict(
   B = 1,
  KB = 1024,
  MB = 1048576,
  GB = 1048576*1024,
  TB = 1048576*1048576
)

def getvalue(line, conv=str):
    return conv(line.strip().split(b": ", 1)[1])

count = dict([(x, 0) for x in states.keys()])

try:
  opts, files = getopt.gnu_getopt(sys.argv[1:], 'H:w:c:t:U:dln', [])
  argv = dict(opts)
except getopt.GetoptError as err:
  print("Error: %s" % err)
  sys.exit(1)

htmltags = re.compile(r"<[^>]*>", re.I)
if '-l' in argv:
  #lighttpd = True
  server = "lighttpd"
elif '-n' in argv:
  server = "nginx"
else:
  #lighttpd = False
  server = "apache"
if '-U' in argv:
  URL = argv['-U']
else:
  URL = "http://%s/server-status" % argv['-H']
if not '-d' in argv:
  URL += "?auto"
warn_time = float(argv.get("-w", 3.0))
crit_time = float(argv.get("-c", 5.0))
try:
  socket.setdefaulttimeout(int(argv.get('-t', 12)))
  t0 = time.time()
  f = urlopen(URL)
  cache = StringIO()
  t1 = time.time()-t0
except Exception as err:
  print("HTTP CRITICAL - %s" % err)
  sys.exit(2)
# search for worker table
total_accesses = 0
total_traffic = 0
while True:
  line = f.readline()
  cache.write(line)
  if not line:
    break # EOF
  elif line.startswith(b"<table border="):
    break
  elif line.startswith(b"Total Accesses:"):
    total_accesses = getvalue(line, int)
  elif line.startswith(b"Total kBytes:"):
    total_traffic = 1024*getvalue(line, int)
  elif line.startswith(b"IdleServers:"):
    # switch to lighttpd mode
    #lighttpd = True
    server = "lighttpd"
  elif line.startswith(b"Scoreboard:"):
    scores = getvalue(line)
    for key in count.keys():
      if server=="lighttpd":
        count[key] = scores.count(apache2lighttpd.get(key, key))
      else:
        count[key] = scores.count(key)
  elif b"Total accesses:" in line:
    a = htmltags.sub("", line.strip()).split(' ')
    total_accesses = a[2]
    total_traffic = float(a[6])*si[a[7].upper()]
  # nginx
  elif line.startswith(b"Active connections:"):
    count['A'] = int(getvalue(line))
  elif line.startswith(b"Reading:"):
    values = line.split(" ")
    count['R'] = int(values[1])
    count['W'] = int(values[3])
    count['_'] = int(values[5])

if '-d' in argv:
  # skip one next line
  cache.write(f.readline())
  # read data
  buf = ""
  for line in f.readlines():
    cache.write(line)
    if line.startswith("</table>"):
      f.close()
      break
    if line.strip()=="":
      if buf:
        tabrow = htmltags.sub("", buf).split("\t")
        srv,pid,acc,m,cpu,ss,req,conn,child,slot,client,vhost,request,_ = tabrow
        ss = int(ss)
        if m=="W" and ss>10:
          print("ss=%s, pid=%s, ip=%s, req=%s" % (ss,pid,client,request))
        count[m] += 1
      buf = ""
    else:
      buf += line.strip().replace("</td>", "\t")

stats = ' '.join([
  "%s=%s;;;0" % (states[key], count[key])
  for key in show_states
])

if t1<warn_time:
  reply = "OK"
  exit_code = 0
else:
  reply = "WARNING"
  exit_code = 1

# store cache
try:
  open(os.path.join(LOGDIR, URL.split('/',3)[2]), "w").write(cache.getvalue())
except IOError:
  pass

print(
  "HTTP %s - %6.4f seconds, %s|time=%ss;;;0 accesses=%sc;;;0 traffic=%sc;;;0 %s"
  % (reply, t1, stats, t1, total_accesses, total_traffic, stats)
)

sys.exit(exit_code)
