-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# rds-top.sh | |
# by <[email protected]>, 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 <[email protected]>, 20190822 | |
# based on the work of Matheus de Oliveira <[email protected]> | |
# | |
# 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