#!/usr/bin/env python2

# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""A script to parse apache error logs

The script gets the contents of the log file through stdin, and emits a counter
metric for the beginning of each error message it recognizes.
"""
from __future__ import print_function

import argparse
import re
import sys

import common

from chromite.lib import metrics
from chromite.lib import ts_mon_config
# infra_libs comes from chromite's third_party modules.
from infra_libs import ts_mon

from autotest_lib.site_utils.stats import log_daemon_common


LOOP_INTERVAL = 60
ERROR_LOG_METRIC = '/chromeos/autotest/apache/error_log'
ERROR_LOG_LINE_METRIC = '/chromeos/autotest/apache/error_log_line'
SEGFAULT_METRIC = '/chromeos/autotest/apache/segfault_count'
START_METRIC = '/chromeos/autotest/apache/start_count'
STOP_METRIC = '/chromeos/autotest/apache/stop_count'

ERROR_LOG_MATCHER = re.compile(
    r'^\[[^]]+\] ' # The timestamp. We don't need this.
    r'\[(mpm_event|core)?:(?P<log_level>\S+)\] '
    r'\[pid \d+[^]]+\] ' # The PID, possibly followed by a task id.
    # There may be other sections, such as [remote <ip>]
    r'(?P<sections>\[[^]]+\] )*'
    r'\S' # first character after pid must be non-space; otherwise it is
          # indented, meaning it is just a continuation of a previous message.
    r'(?P<mod_wsgi>od_wsgi)?' # Note: the 'm' of mod_wsgi was already matched.
    r'(?P<rest>.*)'
)

def EmitSegfault(_m):
    """Emits a Counter metric for segfaults.

    @param _m: A regex match object
    """
    metrics.Counter(
            SEGFAULT_METRIC,
            description='A metric counting segfaults in apache',
            field_spec=None,
    ).increment()


def EmitStart(_m):
    """Emits a Counter metric for apache service starts.

    @param _m: A regex match object
    """

    metrics.Counter(
            START_METRIC,
            description="A metric counting Apache service starts.",
            field_spec=None,
    ).increment()


def EmitStop(_m, graceful):
    """Emits a Counter metric for apache service stops

    @param _m: A regex match object
    @param graceful: Whether apache was stopped gracefully.
    """
    metrics.Counter(
            STOP_METRIC,
            description="A metric counting Apache service stops.",
            field_spec=[ts_mon.BooleanField('graceful')]
    ).increment(fields={
        'graceful': graceful
    })


MESSAGE_PATTERNS = {
        r'Segmentation fault': EmitSegfault,
        r'configured -- resuming normal operations': EmitStart,
        r'caught SIGTERM, shutting down': lambda m: EmitStop(m, graceful=True),
        # TODO(phobbs) add log message for when Apache dies ungracefully
}


def EmitErrorLog(m):
    """Emits a Counter metric for error log messages.

    @param m: A regex match object
    """
    log_level = m.group('log_level') or ''
    # It might be interesting to see whether the error/warning was emitted
    # from python at the mod_wsgi process or not.
    mod_wsgi_present = bool(m.group('mod_wsgi'))

    metrics.Counter(ERROR_LOG_METRIC).increment(fields={
        'log_level': log_level,
        'mod_wsgi': mod_wsgi_present})

    rest = m.group('rest')
    for pattern, handler in MESSAGE_PATTERNS.iteritems():
        if pattern in rest:
            handler(m)


def EmitErrorLogLine(_m):
    """Emits a Counter metric for each error log line.

    @param _m: A regex match object.
    """
    metrics.Counter(
            ERROR_LOG_LINE_METRIC,
            description="A count of lines emitted to the apache error log.",
            field_spec=None,
    ).increment()


MATCHERS = [
    (ERROR_LOG_MATCHER, EmitErrorLog),
    (re.compile(r'.*'), EmitErrorLogLine),
]


def ParseArgs():
    """Parses the command line arguments."""
    p = argparse.ArgumentParser(
        description='Parses apache logs and emits metrics to Monarch')
    p.add_argument('--output-logfile')
    p.add_argument('--debug-metrics-file',
                   help='Output metrics to the given file instead of sending '
                   'them to production.')
    return p.parse_args()


def Main():
    """Sets up logging and runs matchers against stdin"""
    args = ParseArgs()
    log_daemon_common.SetupLogging(args)

    # Set up metrics sending and go.
    ts_mon_args = {}
    if args.debug_metrics_file:
        ts_mon_args['debug_file'] = args.debug_metrics_file

    with ts_mon_config.SetupTsMonGlobalState('apache_error_log_metrics',
                                             **ts_mon_args):
      log_daemon_common.RunMatchers(sys.stdin, MATCHERS)
      metrics.Flush()


if __name__ == '__main__':
    Main()
