#!/usr/bin/env python

"""JSON log tailer.

Usage:
  tail [--cross-finger] [--message=<text>] [--grep=<text> <filename>
  tail (-h | --help)
  tail --version

Options:
  -h --help       Show this screen.
  --version       Show version.
  --cross-finger  Output only if there was ERROR.
  --message=<text> Show only items with this text in message.
  --grep=<text> Show only items with this text in any field.

"""

import tailer
import anyjson
import re
import click

from click import echo
from collections import defaultdict


def print_item(item):
    print u'{ts} {msg}'.format(
        ts = item['@timestamp'].replace('T', ' '),
        msg = item['@message'])

    for kv in item['@fields'].iteritems():
        echo((u' ' * 20 + u'{0} = {1}').format(*kv))


@click.command()
@click.option('--cross-finger', is_flag=True,
              help='Output only if there was ERROR.')
@click.option('--message',
              help='Show only items with this text in message.')
@click.option('--grep',
              help='Show only items with this text in any field.')
@click.option('--name',
              help='Show only items with logger name which matches to this regexp.')
@click.argument('filename')
def process(filename, cross_finger, message, grep, name):
    buffer = defaultdict(list)

    def print_if_needed(item, line):
        if message:
            if re.search(message, item['@message'], re.I) is None:
                return
        if grep:
            if re.search(grep, line, re.I) is None:
                return
        if name:
            if re.search(name, item['@fields'].get('name', ''), re.I) is None:
                return
        print_item(item)


    for line in tailer.follow(open(filename)):
        item = anyjson.deserialize(line)
        fields = item['@fields']

        if cross_finger:
            if 'uuid' in fields:
                uuid = fields['uuid']
                buffer[uuid].append(item)
                if fields['level'] == 'ERROR':

                    echo('')
                    echo('=' * 80)
                    for item in buffer[uuid]:
                        print_if_needed(item, line)
                    del buffer[uuid]
            else:
                if fields['level'] == 'ERROR':
                    print_if_needed(item, line)
        else:
            print_if_needed(item, line)


if __name__ == '__main__':
    process()
