#!/usr/bin/env python

import argparse
import os
import sys

import beaver.config
import beaver.utils
import beaver.worker

from beaver.transport import TransportException
from time import sleep

epilog_example = """
Beaver provides an lightweight method for shipping local log
files to Logstash. It does this using either redis, stdin,
zeromq as the transport. This means you'll need a redis,
stdin, zeromq input somewhere down the road to get the events.

Events are sent in logstash's json_event format. Options can
also be set as environment variables.

Example 1: Listen to all files in the default path of /var/log on standard out as json
    cli: beaver

Example 2: Listen to all files in the default path of /var/log on standard out with msgpack
    cli: BEAVER_FORMAT='msgpack' beaver

Example 3: Listen to all files in the default path of /var/log on standard out as a string
    cli: BEAVER_FORMAT='string' beaver

Example 4: Sending logs from /var/log files to a redis list
    cli: REDIS_URL="redis://localhost:6379/0" beaver -t redis

Example 5: Use environment variables to send logs from /var/log files to a redis list
    cli: REDIS_URL="redis://localhost:6379/0" BEAVER_PATH="/var/log" BEAVER_TRANSPORT=redis beaver

Example 6: Zeromq listening on port 5556 (all interfaces)
    cli: ZEROMQ_ADDRESS="tcp://*:5556" beaver -m bind -t zmq

Please see the readme for more complete examples.

"""
parser = argparse.ArgumentParser(description='Beaver logfile shipper',
                                epilog=epilog_example,
                                formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-m', '--mode', help='bind or connect mode', dest='mode', choices=['bind', 'connect'])
parser.add_argument('-p', '--path', help='path to log files', dest='path')
parser.add_argument('-f', '--files', help='space-separated filelist to watch, can include globs (*.log). Overrides --path argument', dest='files', nargs='+')
parser.add_argument('-t', '--transport', help='log transport method', dest='transport', choices=['rabbitmq', 'redis', 'stdout', 'zmq', 'udp'])
parser.add_argument('-c', '--configfile', help='ini config file path', dest='config')
parser.add_argument('-d', '--debug', help='enable debug mode', type=bool, dest='debug')


# Support env variable parsing as well
files = os.environ.get("BEAVER_FILES", None)
if files is not None:
    files = files.split(',')

parser.set_defaults(
    mode=os.environ.get("BEAVER_MODE", 'bind'),
    path=os.environ.get("BEAVER_PATH", '/var/log'),
    files=files,
    transport=os.environ.get("BEAVER_TRANSPORT", 'stdout'),
    config='/dev/null',
    debug=False
)

args = parser.parse_args()
args.globs = files

logger = beaver.utils.setup_custom_logger('beaver', args.debug)

configfile = beaver.config.Config(args.config)
try:
    args.files.extend(configfile.getfilepaths())
    args.globs.extend(configfile.getglobs())
except AttributeError:
    args.files = configfile.getfilepaths()
    args.globs = configfile.getglobs()

failure_count = 0
respawn_delay = 3
max_failure = 7

while 1:
    try:
        worker = beaver.worker.run_worker(configfile, args)
    except TransportException, e:
        failure_count = failure_count + 1
        if failure_count > max_failure:
            failure_count = max_failure
        sleep_time = respawn_delay ** failure_count
        logger.info("Caught transport exception, respawning in %d seconds" % sleep_time)
        try:
            sleep(sleep_time)
        except KeyboardInterrupt:
            logger.info("User cancelled respawn.")
            sys.exit(0)
    except KeyboardInterrupt:
        logger.info("Shutting down. Please wait.")
        worker.close()
        logger.info("Shutdown complete.")
        sys.exit(0)
