#!/bin/bash
#
#   Copyright (C) 2017 Rackspace, Inc.
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License along
#   with this program; if not, write to the Free Software Foundation, Inc.,
#   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#
#~ Usage: _tool_ OPTIONS
#~ Options:
#~   -c, --connections PORT           Show all network connections of a PORT.
#~   -e, --established PORT           Show only established network connections of a PORT.
#~   -d, --path PATH                  Specify the recap log PATH.
#~   -m, --mem  PROCESS_NAME          Show mem info of PROCESS_NAME.
#~   -p, --proc PROCESS_NAME          Show proc info of PROCESS_NAME.
#~   -b, --memproc PROCESS_NAME       Show both mem and proc info of PROCESS_NAME.
#~   -q, --querycount                 Show mysql connections.
#~   -h, --help                       Print this help.
#~   -V, --version                    Print version and exit.
#~

## Version
declare -r _VERSION='2.0.2'

## Default settings
BASEDIR="/var/log/recap"
cmds=""
CONFFILE="/etc/recap.conf"

## Overriding defaults
if [[ -r "${CONFFILE}" ]]; then
  source "${CONFFILE}"
fi

memproc() {
  PROCESS="${@}"
  TMP=$( mktemp )
  >"${TMP}"
  for i in $( ls "${BASEDIR}"/ps_*.log ); do
    head -n 1 "${i}" | tr "\n" "\t" >> "${TMP}"
    egrep "${PROCESS}" "${i}" -c | tr "\n" "\t" >> "${TMP}"
    egrep "${PROCESS}" "${i}" | awk '{ SUM += $6 } END {print SUM/1024, "M"};' >> "${TMP}"
  done
  sort "${TMP}"
  rm -f "${TMP}"
}

proc() {
  PROCESS="${@}"
  TMP=$( mktemp )
  >"${TMP}"
  for i in $( ls "${BASEDIR}"/ps_*.log ); do
    head -n 1 "${i}" | tr "\n" "\t" >> "${TMP}"
    egrep "${PROCESS}" "${i}" -c >> "${TMP}"
  done
  sort "${TMP}"
  rm -f "${TMP}"
}

mem() {
  PROCESS="${@}"
  TMP=$( mktemp )
  >"${TMP}"
  for i in $( ls "${BASEDIR}"/ps_*.log ); do
    head -n 1 "${i}" | tr "\n" "\t" >> "${TMP}"
    egrep "${PROCESS}" "${i}" | awk '{ SUM += $6 } END {print SUM/1024, "M"};' >> "${TMP}"
  done
  sort "${TMP}"
  rm -f "${TMP}"
}

connections() {
  PORT="${@}"
  TMP=$( mktemp )
  >"${TMP}"
  for i in $( ls "${BASEDIR}"/netstat_*.log ); do
    head -n 1 "${i}" | tr "\n" "\t" >> "${TMP}"
    egrep -c ":${PORT} " "${i}" >> "${TMP}"
  done
  sort "${TMP}"
  rm -f "${TMP}"
}

established() {
  PORT="${@}"
  TMP=$( mktemp )
  >"${TMP}"
  for i in $( ls "${BASEDIR}"/netstat_*.log ); do
    head -n 1 "${i}" | tr "\n" "\t" >> "${TMP}"
    egrep -c "ESTAB .*:${PORT} " "${i}" >> "${TMP}"
  done
  sort "${TMP}"
  rm -f "${TMP}"
}

querycount() {
  TMP=$( mktemp )
  >"${TMP}"
  for i in $( ls "${BASEDIR}"/mysql_*.log ); do
    head -n 1 "${i}" | tr "\n" "\t" >> "${TMP}"
    grep "Query" -c "${i}" >> "${TMP}"
  done
  sort "${TMP}"
  rm -f "${TMP}"
}

print_usage() {
  echo
  grep -E '^#~' "${0}" | sed -e 's/^#~\s\?//' \
                             -e "s/_tool_/$( basename ${0} )/"
}

# Set options
OPTIONS=Vc:d:e:m:p:b:qh
LONG_OPTIONS=version,connections:,path:,established:,mem:,proc:,memproc:,querycount,help

# Parse options and show usage if invalid options provided
! ALL_ARGS=$(getopt --options=${OPTIONS} --longoptions=${LONG_OPTIONS} --name "$0" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
  print_usage
  exit 1
fi

# Set the positional parameters to the parsed options
eval set -- "${ALL_ARGS}"

# Create an array to store commands to be executed
declare -a CMDS

# Act on the valid arguments provided
while [[ ${#} -gt 0 ]]; do
  case "${1}" in
    -V|--version)
      echo "${_VERSION}"
      exit 0
      ;;
    -c|--connections)
        PORT=${2}
        shift 2
        CMDS+=("connections ${PORT}")
      ;;
    -e|--established)
        PORT=${2}
        shift 2
        CMDS+=("established ${PORT}")
      ;;
    -d|--path)
      DIR=true
      if [[ -d "${2}" ]]; then
        BASEDIR="${2}"
        shift 2
      else
        echo "Error: ${2} is not a valid directory."
        print_usage
        exit 1
      fi
      ;;
    -m|--mem)
        PROCESS_NAME="${2}"
        shift 2
        CMDS+=("mem ${PROCESS_NAME}")
      ;;
    -p|--proc)
        PROCESS_NAME="${2}"
        shift 2
        CMDS+=("proc ${PROCESS_NAME}")
      ;;
    -b|--memproc)
        PROCESS_NAME="${2}"
        shift 2
        CMDS+=("memproc ${PROCESS_NAME}")
      ;;
    -q|--querycount)
        CMDS+=(querycount)
        shift
      ;;
    -h|--help)
        print_usage
        exit 0
      ;;
    --)
      shift; break ;;
  esac
done

if [[ ${#CMDS[@]} -eq 0 ]]; then
  msg="Error: Please supply more arguments."
  [[ $DIR ]] && msg="${msg} The 'path' option is not enough."
  echo "${msg}"
  print_usage
  exit 1
fi

echo "Information: Using ${BASEDIR} as recap log path"

for cmd in "${CMDS[@]}"; do
  echo "Information: Executing ${cmd}"
  eval ${cmd}
  echo
done

exit 0
