Skip to content

Instantly share code, notes, and snippets.

@calh
Forked from sherwind/rds-top.sh
Last active June 16, 2022 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save calh/65c358694227aade156a852a7962f772 to your computer and use it in GitHub Desktop.
Save calh/65c358694227aade156a852a7962f772 to your computer and use it in GitHub Desktop.
Get AWS RDS Enhanced Monitoring statistics from CloudWatch and show something similar to Linux top command
#!/bin/bash
# rds-top.sh
# by <cal@fbsdata.com>, 20220616
# * Changed some --start-time syntax
# * Added --profile and --region
# * Made nicer numbers for memory/swap
# * Fixed disk IO output to only show devices with real data
# by <sherwin@daganato.com>, 20190822
# based on the work of Matheus de Oliveira <matioli.matheus@gmail.com>
#
# WISHLIST
#
# As this floats around the Intertubes, tack on some features you'd like
# others to think about and add:
# * ncurses / simplecurses like interface to make it more top-like
# * start at a time in the past and replay through the seconds
#
set -e
function usage()
{
cat << EOF
Usage: $0 [options] rds_instance_id
OPTIONS:
-s or --start-time=t Optional: Specify the start time in seconds since the Unix epoch
OR specify timestamp parsable by your GNU date utility
-m or --sort-by-mem Optional: Sorts output by memory. Default is to sort by CPU
--profile=me AWS CLI Profile
--region=us-east... AWS CLI Region
EXAMPLES:
rds_top my-prod-writer
rds_top --start-time "13 days ago" my-prod-readonly
rds_top --start-time 1655318348 my-prod-readonly
rds_top --profile me@account --region us-west-2 --sort-by-mem failover-instance
# a more top-like real time view
watch --interval=1 "rds_top my-instance"
EOF
}
if [ $# -eq 0 ]
then
usage
exit
fi
for i in "$@"
do
case $i in
# removing = token requirement for looser arguments
#-s=*|--start-time=*)
# START_TIME="${i#*=}"
-s | --start-time )
START_TIME="$2"
shift 2
;;
-m | --sort-by-mem )
SORT_BY_MEM=1
shift
;;
--profile )
PROFILE="--profile $2"
shift 2
;;
--region )
REGION="--region $2"
shift 2
;;
*)
# unknown option
;;
esac
done
INSTANCE_ID="$1"
if [[ "$INSTANCE_ID" == "" ]]
then
echo "You have to supply an instance ID!"
usage
exit
fi
if [[ "$START_TIME" != "" && ! "$START_TIME" =~ ^[[:digit:]]+$ ]]; then
START_TIME=$(date --date="$START_TIME" '+%s')
fi
AWS="aws $PROFILE $REGION"
# Get resource id
#echo "$AWS rds describe-db-instances --db-instance-identifier "$INSTANCE_ID" --output json | jq -r '.DBInstances[].DbiResourceId'"
resource_id="$($AWS rds describe-db-instances --db-instance-identifier "$INSTANCE_ID" --output json | jq -r '.DBInstances[].DbiResourceId')"
[[ "$resource_id" == "" ]] && exit 1
# Build logs parameters
params=(--log-group-name RDSOSMetrics --log-stream-name "$resource_id" --limit 1 --output json)
if [[ "$START_TIME" =~ ^[[:digit:]]+$ ]];
then
params+=(--start-time "$((START_TIME * 1000))" --start-from-head)
fi
# Get log events
message_json=$($AWS logs get-log-events "${params[@]}" | jq -r '.events[].message')
#echo "$message_json" | jq '.'
echo "${message_json}" |
jq -r '"\(.instanceID) - \(.timestamp) - \(.uptime) up, load average: \(.loadAverageMinute.one), \(.loadAverageMinute.five), \(.loadAverageMinute.fifteen)
Tasks: \(.tasks.total) total, \(.tasks.running) running, \(.tasks.sleeping) sleeping, \(.tasks.stopped) stopped, \(.tasks.zombie) zombie
%Cpu(s): \(.cpuUtilization.user) us, \(.cpuUtilization.system) sy, \(.cpuUtilization.nice) ni, \(.cpuUtilization.idle) id, \(.cpuUtilization.wait) wa, \(.cpuUtilization.steal) st
MiB Mem: \(.memory.total / 1024|floor) total, \(.memory.free / 1024|floor) free, \((.memory.total - .memory.free) / 1024|floor) used, \((.memory.cached + .memory.buffers) / 1024|floor) buff/cache
MiB Swap: \(.swap.total / 1024|floor) total, \(.swap.free / 1024|floor) free, \(.swap.cached|floor) cached"'
echo
echo "${message_json}" |
jq -r '.network[] | "Net \(.interface): \(.rx) rx, \(.tx) tx"'
# Mimic `iostat -x`
echo "${message_json}" |
jq -r '.diskIO[] | select('.device') | "Disk \(.device): \(.tps) tps, \(.rrqmPS) rrqm/s, \(.wrqmPS) wrqm/s, \(.writeKbPS) wKB/S, \(.readKbPS) rKB/S, \(.avgReqSz) avgrq-sz, \(.avgQueueLen) avgqu-sz, \(.await) await, \(.util) %util"'
echo
sort_by=".cpuUsedPc"
if [[ $SORT_BY_MEM -eq 1 ]]
then
sort_by=".memoryUsedPc"
fi
echo "${message_json}" |
jq -r '["PID", "PPID", "VSS", "RSS", "%CPU", "%MEM", "COMMAND"], (.processList | sort_by('"$sort_by"') | reverse[] | [.id, .parentID, .vss, .rss, .cpuUsedPc, .memoryUsedPc, .name]) | @tsv' |
column -t -s $'\t'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment