#!/usr/bin/env python
"""
Read Ganglia in, write NetLogger out.
"""

import logging
import re
import socket
import sys
import time

from netlogger import nlganglia
from netlogger.nllog import get_logger, OptionParser

BASE_METRICS = ('load_one', 'load_five', 'cpu_user', 'cpu_system', 'cpu_idle',
                'bytes_in', 'bytes_out', 'mem_free')

def main():
    # parse command line
    usage = "%prog [options]"
    desc = ' '.join(__doc__.split())
    parser = OptionParser(usage=usage, description=desc)
    parser.add_option('-e', '--filter', dest="expr", default=None,
                       metavar="REGEX",
                       help="regular expression to use as a filter. " +
                       "This expression operates on the formatted output, " +
                       "i.e. name=value pairs")
    parser.add_option('-i', '--interval', dest="interval", type='float',
                      default=-1.0, metavar="SEC",
                      help="poll interval in seconds (default=run once)")
    parser.add_option('-m', '--metrics', dest="metrics",
                      default="base", action="store", type="choice",
                      choices=("base", "all"),
                      help="set of metrics to display (default=%default)")
    parser.add_option('-o', "--output", dest="filename",
                      default=None, metavar="FILE",
                      help="output file (default=stdout)")
    parser.add_option('-s', '--server', dest="server",
                      default="localhost",
                      help="gmetad server host (default=%default)")
    parser.add_option('-p', '--port', dest='port',
                      default=8651, type='int',
                      help="gmetad server port (default=%default)")
    options, args = parser.parse_args()
    log = get_logger(__file__)  # Should be first done, just after parsing args
    # connect to server
    gmetad = nlganglia.Gmetad(host=options.server, port=options.port)
    log.debug("connect.end", status=0)
    # metrics
    if options.metrics == "all":
        metrics = None
    elif options.metrics == "base":
        metrics = dict.fromkeys(BASE_METRICS)
    else:
        parser.error("internal error: bad --metrics='%s'" % options.metrics)
    # output
    if options.filename is None:
        ofile = sys.stdout
    else:
        ofile = file(options.filename,'w')
    # filter
    if options.expr:
        expr = re.compile(options.expr)
    else:
        expr = None
    # read loop(s)
    log.info("run.start")
    ok = True
    while 1:
        if log.isEnabledFor(logging.DEBUG):
            log.debug("read.start", host=options.server, port=options.port)
        try:
            data = gmetad.read()
        except socket.error, E:
            log.error("read.error", msg=E, host=options.server,
                      port=options.port)
            ok = False
            break
        if log.isEnabledFor(logging.DEBUG):
            log.debug("read.end", status=0, data__len=len(data))
        if data == '':
            break
        for metric, log_entry in nlganglia.parse(data):
            if metrics is None or metric in metrics:
                if expr is None:
                    ofile.write(log_entry)
                else:
                    if expr.search(log_entry):
                        ofile.write(log_entry)
        if options.interval < 0:
            break
        if log.isEnabledFor(logging.DEBUG):
            log.debug("run.sleep.start", value=options.interval, unit="seconds")
        time.sleep(options.interval)
        if log.isEnabledFor(logging.DEBUG):
            log.debug("run.sleep.end", status=0)
    if ok:
        log.info("run.end", status=0)
    else:
        log.error("run.error", msg="failed")

if __name__ == '__main__':
    sys.exit(main())
