#!/bin/ksh
#=======================================================================
# perfparse.sh - <SPYNuptm/bin/perfparse.sh>
#-----------------------------------------------------------------------
#
# - DESCRIPTION:
#
#   perfparse is run by the 'uptmagnt' binary to parse the 'sar'
#   data that has been extracted
#
# - DEPENDENCIES:
#
#     requires 'sar' /usr/lib/sa
#     'awk', 'nawk', 'fgrep'
#
#=======================================================================
# $Id: perfparse.sh,v 1.10 2007/09/06 21:12:04 dgermiquet Exp $
#
#
export LANG=en_US.ISO8859-1
export LC_COLLATE=C


# -- let's create a date string that is going to be used in our output
#    lines
UPTIMEHOME=/opt/uptime-agent
DATESTR=`date '+%Y%m%d%H%M'`
DATESTRSEC=`date '+%Y%m%d%H%M%S'`
SARBIN=/usr/sbin/sar
SADCBIN=/usr/lib/sa/sadc
NETSTATBIN=/usr/bin/netstat
MPSTATBIN=/usr/bin/mpstat
AWKBIN=/usr/bin/nawk
VMSTATBIN=/usr/bin/vmstat
PAGESIZEBIN=/usr/bin/pagesize
PSRINFOBIN=/usr/sbin/psrinfo
NETQBIN=$UPTIMEHOME/bin/netq
KSTATBIN=$UPTIMEHOME/bin/kstat
SARFILE=$UPTIMEHOME/tmp/uptm.sar
DFBIN='/usr/bin/df'
PRTMEMBIN=/opt/RMCmem/bin/prtmem
VXPRINTBIN=$UPTIMEHOME/bin/vxprint
VXSTATBIN=$UPTIMEHOME/bin/vxstat
VXDGBIN=$UPTIMEHOME/bin/vxdg
ABSTIMEBIN=$UPTIMEHOME/bin/abstime
MONITORBIN=/usr/local/bin/monitor
OSVERMAJOR=`uname -a | $AWKBIN '{print $4}'`
OSVERMINOR=`uname -a | $AWKBIN '{print $3}'`

PATH=$PATH:/usr/bin:/etc:/usr/sbin:/sbin:/bin

sar_cpustats_disp()
{
  #====================================================================
  # KSH_FUNCTION: <sar_disp - display sar data in meaningful format
  #--------------------------------------------------------------------
  # 
  # - DESCRIPTION
  #   this functions read in the two sample 'sar' file created by
  #   the 'uptmagnt' file and then outputs it to the agent
  #
  # - CAVEATS
  #   This function does not return data for the following fields.
  #   Zeroes are returned in place of the non existant data.
  #   (sar -g) pgouts/s, ppgouts/s, pgfree/s, pgscans/s, %ufs_ipf
  #   (sar -p) atch/s, pgin/s, ppgin/s, pflts/s, uflt/s, slock/s
  #
  #--------------------------------------------------------------------

  if [[ "$UDEBUG" = "1" ]]; then
    set -x
  fi

    # -- we now have the 'sar' data, so let's capture the lines of info
    #    that we need
   # VMSTAT=`$VMSTATBIN 1 2 | tail -1`

    # -- let's get CPU info (skip the average info)
    CPU=`$SARBIN -u -f $SARFILE | grep -v Average | egrep -v "^$" | tail -1`
    USR=`echo $CPU | $AWKBIN '{print $2}'`
    if [[ $USR -gt 100 ]]; then
      USR=100
    fi
    SYS=`echo $CPU | $AWKBIN '{print $3}'`
    if [[ $SYS -gt 100 ]]; then
      SYS=100
    fi
    WIO=`echo $CPU | $AWKBIN '{print $4}'`
    if [[ $WIO -gt 100 ]]; then
      WIO=100
    fi
    OUTLINE=$DATESTR','$USR','$SYS','$WIO','
#    OUTLINE=$DATESTR','`echo $CPU | $AWKBIN '{print $2 "," $3 "," $4 "," }'`

    # -- now, let's get the memory info (freemem, freeswap)
    # -- convert freemem to K from pages (8192bytes)
    # -- convert freeswap to K from blocks (512bytes)
    # SWAP=`$SARBIN -r -f $SARFILE | tail -1`
    #PAGESIZE=`$PAGESIZEBIN`
    #FREESWAP=`lsps -s | tail -1 |  nawk 'BEGIN { tot=0; free=0 } { gsub( /[A-Z]/, ""  ); tot=tot+$1; free=free+(($1*($2/100))) } END { print free }'`

EXPR='/usr/bin/expr'

    #  MEMORY=`bootinfo -r`

    #  PHYS_MEMORY=`$EXPR $MEMORY / 1024`

      VMSTAT=`/usr/bin/vmstat 1 2 | tail -1`

      PHYS_MEMORY_FREE=`echo $VMSTAT | awk '{print $4;}'`
      PHYS_MEMORY_FREE=`$EXPR $PHYS_MEMORY_FREE / 256` # -- free mem in MB
    #  PHYS_MEMORY_FREE=$(($PHYS_MEMORY_FREE/256*1024)) # -- free mem in kb
    #  SWAP=`$UPTIMEHOME/bin/pstat -s 2>/dev/null`
    # SWAP_MEMORY_USED=`echo $SWAP | awk '{print $7}'`
    #  SWAP_MEMORY_USED=`$EXPR $SWAP_MEMORY_USED / 256`
      SWAP_MEMORY_FREE=`$UPTIMEHOME/bin/pstat -s 2>/dev/null | awk '/^(.+)[0-9]/ {print $2}'`
      SWAP_MEMORY_FREE=`$EXPR $SWAP_MEMORY_FREE / 256 2>/dev/null`  # -- swap free is in MB
    #  SWAP_MEMORY_FREE=$(($SWAP_MEMORY_FREE/256*1024))  # -- swap free is kb now

    OUTLINE=$OUTLINE"$PHYS_MEMORY_FREE,$SWAP_MEMORY_FREE,"

    # -- runq-sz/%runq-occ
    # -- these can occasionally be blank so put in zeros
    RUNQ=`$SARBIN -q -f $SARFILE | tail -1`
    OUTLINE=$OUTLINE`echo $RUNQ | $AWKBIN '{ a=$2; b=$3;if (a == "" || a == "runq-sz" ) a="0"; if (b =="" || b =="%runocc") b="0"; print a "," b "," }'`

    # -- cache hits
    CACHE=`$SARBIN -b -f $SARFILE | tail -1`
    OUTLINE=$OUTLINE`echo $CACHE | $AWKBIN '{ a=$4; b=$7;if (a=="%rcache") a="0"; if (b=="%wcache") b="0";  print a "," b "," }'`

    # -- paging/swapping
    #PGOUT=`$SARBIN -g -f $SARFILE | tail -1`
    #OUTLINE=$OUTLINE`echo $PGOUT | $AWKBIN '{print $2 "," $3 "," $4 "," $5 "," }'` 
    #OUTLINE=$OUTLINE"0,0,0,0,"
    
    # -- we have to output 10 numbers in a row
    # -- pgout, ppgout, pgfree, pgscan, atch, pgin, ppgin, pflt, vflt, slock
    # -- on AIX, odio,0,0,cycle,0,free pageing,0,fault,0,0
    AIXPAG=`$SARBIN -r -f $SARFILE | tail -1`
    PPGIN=`echo $VMSTAT | $AWKBIN '{ print $6 }'`
    PPGOUT=`echo $VMSTAT | $AWKBIN '{ print $7 }'`
    OUTLINE=$OUTLINE`echo $AIXPAG $PPGIN $PPGOUT | $AWKBIN '{ a=$5; b=$3; c=$2; d=$4; ppi=$6; ppo=$7; if (a=="odio/s") a="0"; if (b=="cycle/s") b="0"; if (c=="slots") c="0"; if (d=="fault/s") d="0"; print a "," ppo ",0," b ",0," c "," ppi " ," d ",0,0" }'`

# 14:30:10   slots cycle/s fault/s  odio/s
# 14:30:11   16032    0.00  478.00    0.00

    # -- num procs
    #NPROC=`$KSTATBIN system_misc nproc`
    NPROC=`ps -ef|wc -l|sed -e 's/ *//'`
    OUTLINE=$OUTLINE','$NPROC

    # -- running,waiting,blocked procs
    VMPROC=`echo $VMSTAT | tail -1 | $AWKBIN '{ print $1","$2",0" }'`
    OUTLINE=$OUTLINE','$VMPROC

    # -- leave the DNLC empty right now
    OUTLINE=$OUTLINE',0'

    # -- forks/s and exec/s
    FRK=`$SARBIN -c -f $SARFILE | tail -1`
    OUTLINE=$OUTLINE`echo $FRK | $AWKBIN '{ a=$5; b=$6; if (a=="fork/s") a="0"; if (b=="exec/s") b="0"; print ","a","b }'`

    #echo $OUTLINE
    # -- if one value is blank, put it as -1
    echo $OUTLINE | /usr/bin/sed '/,,/ s/,,/,-1,/g' | /usr/bin/sed s/,,/,-1,/g | /usr/bin/sed 's/,$/,-1/'
} # sar_cpustats_disp()

sar_diskstats_disp()
{
    # -- If you do not want to see non-active disk, please set ACTIVEONLY=0
    #    then up.time GUI will display active disk statistics only. By default,
    #    up.time will get all disks information, no matter active or not.   

    ACTIVEONLY=1    # Set ACTIVEONLY=0, if do not want to see non-active disk. 

    #-- now, let's do the disk info, first have to find out how long
    #   each entry is for all the disks and then take the last one 
    #   in the file (but not the Average info)

    #-- on AIX V5.2, sar output may have extra line as "System Configuration"
    #   remove this line and blank line under this line.
    SYSLINE=`$SARBIN -d 1 1 | grep -ni "System Configuration" | $AWKBIN -F : '{print $1}'`
    if [ "$SYSLINE" -eq "" ]; then
       SYSLINE=0
    fi
    NUMLINES=`$SARBIN -d -f $SARFILE | grep -vi "System Configuration" | sed "$SYSLINE"d | $AWKBIN 'BEGIN { lc=0;found=0 } /^$/ { lc = lc + 1; if ( lc == 3) {found=1; linec=NR }; if ( lc == 4 && found==1) { print NR-linec-1; exit } }'`

    # -- let's dump our region of interest and then remove the slice
    #    performance stats
    if [ "$NUMLINES" != "" ]; then
      sar -d -f $SARFILE | tail -$(($NUMLINES+1)) | sed '/^$/d' | fgrep -v , | cut -c9- | fgrep -v fd | fgrep -v nfs | fgrep -v cd | fgrep -v device  > $UPTIMEHOME/tmp/uptmsar.txt
      if [ "$ACTIVEONLY" != "0" ]; then
         cat $UPTIMEHOME/tmp/uptmsar.txt 2>/dev/null | $AWKBIN -v d=$DATESTR '{ print d " " $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7 }'
      else
         if [ "$OSVERMAJOR" != "5" ]; then     # -- on AIX V4.3 system
            lspv | grep -vi "none" | $AWKBIN '{print $1}' | while read BSD 
            do
              cat $UPTIMEHOME/tmp/uptmsar.txt 2>/dev/null | grep "$BSD" | $AWKBIN -v d=$DATESTR '{ print d " " $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7 }'
            done
         else       # -- on AIX V5 system
		if [ "$OSVERMINOR" != "1" ]; then  # -- on AIX V5.2 and up
            		lspv | grep active | awk '{print $1}' | while read BSD 
            		do
              			cat $UPTIMEHOME/tmp/uptmsar.txt 2>/dev/null | grep "$BSD" | $AWKBIN -v d=$DATESTR '{ print d " " $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7 }'
           		 done
		else                           # -- on AIX V5.1 system
			lspv | grep -vi "none" | $AWKBIN '{print $1}' | while read BSD
	                do
                        cat $UPTIMEHOME/tmp/uptmsar.txt 2>/dev/null | grep "$BSD" | $AWKBIN -v d=$DATESTR '{ print d " " $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7 }'
			done
		fi
         fi
      fi        
    
     rm -f $UPTIMEHOME/tmp/uptmsar.txt
    fi

} # sar_diskstats_disp()

mpstat_disp()
{
  TITLELINE=`$SARBIN -P ALL 1 | grep -n "%usr" | $AWKBIN -F : '{print $1}'`
  CPUIDLINE=$(($TITLELINE+1))

  sar -f $SARFILE -P ALL 1 | tail +$CPUIDLINE | cut -c9- >$UPTIMEHOME/tmp/$$.m

  cat $UPTIMEHOME/tmp/$$.m | grep -v U | while read cpu_id usr sys wio idle dummy  
  do
    if [ "$usr" -eq "" ]; then
      usr=0
    fi 
    if [ "$sys" -eq "" ]; then
      sys=0
    fi
    if [ "$wio" -eq "" ]; then
      wio=0
    fi
    if [ "$idle" -eq "" ]; then
      idle=0
    fi 
    if [[ "$cpu_id" != "-" ]]; then 
      echo "$DATESTR $cpu_id 0 0 0 0 0 0 0 0 0 0 0 $usr $sys $wio $idle"
    fi

  done

  rm -f $UPTIMEHOME/tmp/$$.m
}

netstat_disp()
{

  ifconfig -a | awk '{print $1}' | grep : | grep -v lo | while read ifname
  do
    # --- Get the previous values for the netstat samples
    if [[ ! -f $UPTIMEHOME/tmp/.uptm.$ifname ]]
    then
      HOUR=`date +%H | awk '{print $1/1}'`
      MIN=`date +%M | awk '{print $1/1}'`
      SEC=`date +%S | awk '{print $1/1}'`
      netstat -I $ifname | tail -1 | sed -g 's/\-//' | awk -v HOUR=$HOUR -v MIN=$MIN -v SEC=$SEC '{print HOUR,MIN,SEC,$5, $6, $7, $8, $9}' > $UPTIMEHOME/tmp/.uptm.$ifname
    fi

      awk '{print $1,$2,$3,$4,$5,$6,$7,$8}' $UPTIMEHOME/tmp/.uptm.$ifname | read prevhour prevmin prevsec ipkts ierrors opkts oerrors coll
      
    # --- Generate new samples 
      HOUR=`date +%H | awk '{print $1/1}'`
      MIN=`date +%M | awk '{print $1/1}'`
      SEC=`date +%S | awk '{print $1/1}'`
      netstat -I $ifname | tail -1 | sed -g 's/\-//' | awk -v HOUR=$HOUR -v MIN=$MIN -v SEC=$SEC '{print HOUR,MIN,SEC,$5, $6, $7, $8, $9}' > $UPTIMEHOME/tmp/.uptm.$ifname

    # --- Read in the new samples
    awk '{print $1,$2,$3,$4,$5,$6,$7,$8}' $UPTIMEHOME/tmp/.uptm.$ifname | read hournow minnow secnow ipktsnow ierrorsnow opktsnow oerrorsnow collnow


    interface=`echo ${ifname%?}`
    if [ $hournow -ge $prevhour ]; then
      (( timedelta =(hournow-prevhour)*3600+(minnow-prevmin)*60+(secnow-prevsec) ))
      else
      (( timedelta=(hournow+24-prevhour)*3600+(minnow-prevmin)*60+(secnow-prevsec) ))
    fi
    if [ $timedelta -le 0 ]; then
      timedelta=1
    fi
    (( rxpacketdelta = ipktsnow - ipkts ))
    (( ierrorsdelta = ierrorsnow - ierrors ))
    (( txpacketdelta = opktsnow - opkts ))
    (( oerrorsdelta = oerrorsnow - oerrors ))
    (( colldelta = collnow - coll ))

    # -- If counter rollover, we have to re-calculate those delta
    if [ $ipktsnow -lt $ipkts ]; then
     (( rxpacketdelta = ipktsnow+4294967296-ipkts ))
    fi
    if [ $ierrorsnow -lt $ierrors ]; then
     (( ierrorsdelta = ierrorsnow+4294967296-ierrors ))
    fi
    if [ $opktsnow -lt $opkts ]; then
     (( txpacketdelta = opktsnow+4294967296-opkts ))
    fi
    if [ $oerrorsnow -lt $oerrors ]; then
     (( oerrorsdelta = oerrorsnow+4294967296-oerrors ))
    fi
    if [ $collnow -lt $coll ]; then
     (( colldelta = collnow+4294967296-coll ))
    fi

    (( rxbytessec = rxpacketdelta / timedelta ))
    (( txbytessec = txpacketdelta / timedelta ))
    (( collisions = colldelta / timedelta ))
    (( rxerrorssec = oerrorsdelta / timedelta ))
    (( txerrorssec = ierrorsdelta / timedelta ))   

    STATS="$interface $rxbytessec $txbytessec $collisions $rxerrorssec $txerrorssec"
    echo $DATESTR" "$STATS

  done 

}

tcpinfo_disp()
{
  PDATE=`cat $UPTIMEHOME/tmp/.tcp.uptm | $AWKBIN '{ print $1 }'`
  PVALUE=`cat $UPTIMEHOME/tmp/.tcp.uptm | $AWKBIN '{ print $2 }'`

  NETSTRA=`$NETSTATBIN -s | fgrep retransmitted | $AWKBIN '{print $4}'`
  NETSTR=`echo ${NETSTRA#?}`
  netdelta=$NETSTR

  if [[ $PDATE = "" ]]; then
    PDATE=$DATESTR
    PVALUE=$NETSTR
  fi

    if [ $NETSTR -lt $PVALUE ]; then
     (( netdelta = $NETSTR+4294967296-PVALUE ))
    else
     (( netdelta = NETSTR - PVALUE )) 
    fi
  (( DATEVAL = DATESTR - PDATE ))
  (( DATEVAL = DATEVAL / 60 + 1 ))
  (( TCPVAL = netdelta / DATEVAL ))
  echo $DATESTR " " $NETSTR >$UPTIMEHOME/tmp/.tcp.uptm 
  echo $DATESTR " " $netdelta
}

volcap_disp()
{
  # -- don't display any nfs mounted file systems
  echo $DATESTR
  $DFBIN -k | fgrep -v "/proc" | fgrep -v "/dev/fd" | fgrep -v "/cdrom" | fgrep -v "/net" | fgrep -v "/etc/mnttab" | fgrep -v "/var/run" | $AWKBIN '{ if ( index( $1, ":" ) <= 0 ) { print $1 " " $2 " " $2-$3 " " $3 " " $4 " " $7 } }' | $AWKBIN '{  if ($2=="") { fs=$1; getline; print fs " " $0} else { print $0 } } ' | tail +2
}

vxprint_disp()
{
  echo "!" 
}

metastat_disp()
{
  echo "!"
}

vxvolstat_disp()
{
  echo "!"
}

prtmem_disp()
{
    echo "!"
}


chk4()
{
  PROC="$*"
#
# Use ps with format option to limit fields, then grep to narrow down the
# possibilities, then scripting to ensure
# you have actually mathces the process name, not the path or UID.
#
  TLIST=""
#  ps -eo "user pid args" | fgrep $PROC | fgrep -v fgrep | fgrep -v perfparse | while read ID PID PROC1 PARAMS
count=`ps -eo "user pid args" | egrep -v "perfparse" | egrep -v egrep | egrep "$PROC" | wc -l | sed "s/ //g"` 

if [ count -gt 0 ] ; then
  echo "OK - Found $count proc "
 else
  echo "CRIT - $PROC not running "
fi
}
disp_help()
{ 
  echo "perfparse.sh [cpu|disk|mpstat] <sarfile>"
}

tailvaradm()
{
  default=10
  tail -$1 $2
}

lastuser()
{
  last | head -10
}

whoin()
{
  echo $DATESTR
  who >$UPTIMEHOME/tmp/$$.wx
  who | awk '{ print $1 }' | sort -u | while read id
  do
    C=`fgrep -c $id $UPTIMEHOME/tmp/$$.wx`
    echo $id" "$C
  done

  rm -f $UPTIMEHOME/tmp/$$.wx 2>/dev/null
}

taillog()
{
  tail -n $2 $1
}

main() {


  # -- if we're doing an mpstat, then don't collect 'sar' data
  case $1 in
    mpstat)	mpstat_disp
		exit
		;;
    netstat)	netstat_disp
		exit
		;;
    volcap)	volcap_disp
		exit
		;;
    tcpinfo)	tcpinfo_disp
		exit
		;;
    vxprint)    vxprint_disp
		exit	
		;;
    metastat)	metastat_disp
		exit
		;;
    prtmem)	prtmem_disp
		exit
		;;

    chk4)       shift  1
                chk4 "$*"
                exit
                ;;

    vxvolstat) vxvolstat_disp
		exit
		;;
    tailvaradm) tailvaradm $2 $3
		exit
		;;
 taillog) taillog $2 $3
           exit
	;;
	lastuser) lastuser
		exit
		;;
	whoin) whoin
		exit
		;;
  esac

  # -- collect a current sample (to store for next time)
  # -- collect another curent sample to tack to the historical
  #    data point
  TEMPFILE=$UPTIMEHOME/tmp/$$.d
  $SADCBIN 1 2 $TEMPFILE
  if [ -e $SARFILE ]; then
    # -- the file doesn't exist
    FILLERSTATEMENT=''
  else
    chmod ugo+rw $SARFILE 2>/dev/null
    $SADCBIN 1 2 $SARFILE
  fi
  $SADCBIN 1 2 $SARFILE
  UPTIMEUSER=`cat /etc/inetd.conf | grep uptmagnt | awk '{ print $5 }'`

  if [ "$USER" != "$UPTIMEUSER" ] ; then
    chown $UPTIMEUSER $SARFILE
  fi

  case $1 in
    cpu) 	sar_cpustats_disp 
		;;
    disk) 	sar_diskstats_disp 
		;;
    lpars) $UPTIMEHOME/bin/lpars
		;;
    workload)  TECH=`oslevel -s | cut -f 2 -d -`
               if [ -x "$UPTIMEHOME/bin/workload${TECH}ml" ] ; then
               $UPTIMEHOME/bin/workload${TECH}ml
               else
               $UPTIMEHOME/bin/workload 
               fi 
               /usr/bin/lsrsrc -x IBM.ManagementServer LocalHostname | grep Hostname | sed 's/^[^=]*=[ ]*/lpar_hostname=/' | sed 's/"//g'
		;;
    *) 		disp_help
		exit 1
		;;
  esac

  mv -f $TEMPFILE $SARFILE 2>/dev/null 
  chmod ugo+rw $SARFILE 2>/dev/null
  find $UPTIMEHOME/tmp/ -name *.d -print | xargs rm -f

} # main()

main $*

# -- The End.
