Skip to content

Commit 5e8c941

Browse files
committed
Added Bar Graphs and Cleaned Up Pi-hole Stats, Network Info
Major: - Added status bars - Blocked domains now show as a bar graph - CPU and memory use in system stats show with bar graphs - Tweaked Pihole Stats and Network info - Added top domain to pi-hole stats - DHCP info is displayed in Network info, only if Pi-hole is the DHCP server - Additional Pi-hole stats shown if Pi-hole isn't the DHCP server - Added BarGenerator() to support percentage bars - Refactored CPUHeatmapGenerator to support interpretting a percentage or two numbers for CPU percentages Minor: -changed locale to en_us.utf8 so large numbers (domains blocked, etc.) look better - start up wait time reduced to 3 seconds - refactored and cleaned up code
1 parent d911d52 commit 5e8c941

File tree

1 file changed

+101
-41
lines changed

1 file changed

+101
-41
lines changed

chronometer2.sh

+101-41
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
# A more advanced version of the chronometer provided with Pihole
44

55
# SETS LOCALE
6-
# Addresses Issue 5: https://github.com/jpmck/chronometer2/issues/5 ... I think...
7-
export LC_ALL=C.UTF-8
6+
# Issue 5: https://github.com/jpmck/chronometer2/issues/5
7+
# Updated to en_US to support
8+
export LC_ALL=en_US.UTF-8
89

9-
chronometer2Version="1.2.2"
10+
chronometer2Version="1.3"
1011

1112
# COLORS
1213
blueColor=$(tput setaf 6)
@@ -45,16 +46,23 @@ GetFTLData() {
4546
}
4647

4748
GetSummaryInformation() {
49+
# From pihole -c
4850
local summary
4951
summary=$(GetFTLData "stats")
52+
5053
domains_being_blocked_raw=$(grep "domains_being_blocked" <<< "${summary}" | grep -Eo "[0-9]+$")
5154
domains_being_blocked=$(printf "%'.f" ${domains_being_blocked_raw})
55+
5256
dns_queries_today_raw=$(grep "dns_queries_today" <<< "$summary" | grep -Eo "[0-9]+$")
5357
dns_queries_today=$(printf "%'.f" ${dns_queries_today_raw})
58+
5459
ads_blocked_today_raw=$(grep "ads_blocked_today" <<< "$summary" | grep -Eo "[0-9]+$")
5560
ads_blocked_today=$(printf "%'.f" ${ads_blocked_today_raw})
61+
5662
ads_percentage_today_raw=$(grep "ads_percentage_today" <<< "$summary" | grep -Eo "[0-9.]+$")
57-
LC_NUMERIC=C ads_percentage_today=$(printf "%'.f" ${ads_percentage_today_raw})
63+
LC_NUMERIC=C ads_percentage_today=$(printf "%'.1f" ${ads_percentage_today_raw})
64+
65+
adsBlockedBar=$(BarGenerator $ads_percentage_today 40 "color")
5866
}
5967

6068
GetSystemInformation() {
@@ -74,35 +82,43 @@ GetSystemInformation() {
7482
temperature=$(printf %.1f "$(echo "scale=4; ${cpu}/1000" | bc)")°C
7583
fi
7684

77-
# CPU load and heatmap calculations
85+
# CPU load, heatmap and bar
7886
cpuLoad1=$(cat /proc/loadavg | awk '{print $1}')
79-
cpuLoad1Heatmap=$(CPUHeatmapGenerator ${cpuLoad1} ${numProc})
80-
87+
cpuLoad1Heatmap=$(HeatmapGenerator ${cpuLoad1} ${numProc})
8188
cpuLoad5=$(cat /proc/loadavg | awk '{print $2}')
82-
cpuLoad5Heatmap=$(CPUHeatmapGenerator ${cpuLoad5} ${numProc})
83-
89+
cpuLoad5Heatmap=$(HeatmapGenerator ${cpuLoad5} ${numProc})
8490
cpuLoad15=$(cat /proc/loadavg | awk '{print $3}')
85-
cpuLoad15Heatmap=$(CPUHeatmapGenerator ${cpuLoad15} ${numProc})
86-
91+
cpuLoad15Heatmap=$(HeatmapGenerator ${cpuLoad15} ${numProc})
8792
cpuPercent=$(printf %.1f "$(echo "scale=4; (${cpuLoad1}/${numProc})*100" | bc)")
88-
89-
# Memory use
90-
# Corrects Issue #9 https://github.com/jpmck/chronometer2/issues/9
91-
# Thanks, Twiggy159 and WaLLy3K!
92-
memoryUsedPercent=$(awk '/MemTotal:/{total=$2} /MemFree:/{free=$2} /Buffers:/{buffers=$2} /^Cached:/{cached=$2} END {printf "%.1f", (total-free-buffers-cached)*100/total}' '/proc/meminfo')
93+
cpuBar=$(BarGenerator ${cpuPercent} 10)
9394

9495
# CPU temperature heatmap
9596
if [ ${cpu} -gt 60000 ]; then
9697
tempHeatMap=${redColor}
9798
else
9899
tempHeatMap=${blueColor}
99100
fi
101+
102+
# Memory use, heatmap and bar
103+
memoryUsedPercent=$(awk '/MemTotal:/{total=$2} /MemFree:/{free=$2} /Buffers:/{buffers=$2} /^Cached:/{cached=$2} END {printf "%.1f", (total-free-buffers-cached)*100/total}' '/proc/meminfo')
104+
memoryHeatmap=$(HeatmapGenerator ${memoryUsedPercent})
105+
memoryBar=$(BarGenerator ${memoryUsedPercent} 10)
100106
}
101107

102-
CPUHeatmapGenerator () {
103-
x=$(echo "scale=2; ($1/$2)*100" | bc)
104-
load=$(printf "%.0f" "${x}")
108+
# Provides a color based on a provided percentage
109+
# takes in one or two parameters
110+
HeatmapGenerator () {
111+
# if one number is provided, just use that percentage to figure out the colors
112+
if [ -z "$2" ]; then
113+
load=$(printf "%.0f" "$1")
114+
# if two numbers are provided, do some math to make a percentage to figure out the colors
115+
else
116+
load=$(printf "%.0f" "$(echo "scale=2; ($1/$2)*100" | bc)")
117+
fi
105118

119+
# Color logic
120+
# | green | yellow | red ->
121+
# 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
106122
if [ ${load} -lt 75 ]; then
107123
out=${greenColor}
108124
elif [ ${load} -lt 90 ]; then
@@ -114,6 +130,40 @@ CPUHeatmapGenerator () {
114130
echo $out
115131
}
116132

133+
# Provides a "bar graph"
134+
# takes in two or three parameters
135+
# $1: percentage filled
136+
# $2: max length of the bar
137+
# $3: colored flag, if "color" backfill with color
138+
BarGenerator() {
139+
# number of filled in cells in the bar
140+
barNumber=$(printf %.f "$(echo "scale=1; (($1/100)*$2)" | bc)")
141+
frontFill=$(for i in $(seq $barNumber); do echo -n ''; done)
142+
143+
# remaining "unfilled" cells in the bar
144+
backfillNumber=$(($2-${barNumber}))
145+
146+
# if the filled in cells is less than the max length of the bar, fill it
147+
if [ "$barNumber" -lt "$2" ]; then
148+
# if the bar should be colored
149+
if [ "$3" = "color" ]; then
150+
# fill the rest in color
151+
backFill=$(for i in $(seq $backfillNumber); do echo -n ''; done)
152+
out="${redColor}${frontFill}${greenColor}${backFill}${resetColor}"
153+
# else, it shouldn't be colored in
154+
else
155+
# fill the rest with "space"
156+
backFill=$(for i in $(seq $backfillNumber); do echo -n '·'; done)
157+
out="${frontFill}${backFill}"
158+
fi
159+
# else, fill it all the way
160+
else
161+
out=$(for i in $(seq $2); do echo -n ''; done)
162+
fi
163+
164+
echo $out
165+
}
166+
117167
GetNetworkInformation() {
118168
# Is Pi-Hole acting as the DHCP server?
119169
if [[ "${DHCP_ACTIVE}" == "true" ]]; then
@@ -133,7 +183,7 @@ GetNetworkInformation() {
133183
dhcpStatus="Disabled"
134184

135185
# if the DHCP Router variable isn't set
136-
# Addresses Issue 3: https://github.com/jpmck/chronometer2/issues/3
186+
# Issue 3: https://github.com/jpmck/chronometer2/issues/3
137187
if [ -z ${DHCP_ROUTER+x} ]; then
138188
DHCP_ROUTER=$(/sbin/ip route | awk '/default/ { print $3 }')
139189
fi
@@ -289,12 +339,6 @@ GetVersionInformation() {
289339
fi
290340
}
291341

292-
outputDHCPInformation() {
293-
echo "DHCP SERVER ================================================"
294-
printf " %-10s${dhcpHeatmap}%-19s${resetColor}%-10s${dhcpIPv6Heatmap}%-19s${resetColor}\n" "Status:" "${dhcpStatus}" "IPv6:" ${dhcpIPv6Status}
295-
printf "${dhcpInfo}\n"
296-
}
297-
298342
outputJSON() {
299343
GetSummaryInformation
300344
echo "{\"domains_being_blocked\":${domains_being_blocked_raw},\"dns_queries_today\":${dns_queries_today_raw},\"ads_blocked_today\":${ads_blocked_today_raw},\"ads_percentage_today\":${ads_percentage_today_raw}}"
@@ -307,47 +351,64 @@ outputLogo() {
307351

308352
echo -e "${greenColor}' ${redColor}' ${magentaColor}' ${yellowColor}'${greenColor}-${blueColor}\`${magentaColor}-${redColor}'${yellowColor}'${greenColor}-${blueColor}\`${magentaColor}'${redColor}- ${resetColor}Chronometer2 ${chronometer2VersionHeatmap}v${chronometer2Version}${resetColor}"
309353

310-
311-
# echo " ___ _ _ _"
312-
# echo -e "| _ (_)___| |_ ___| |___ ${versionHeatmap}${versionStatus}"
313-
# echo "| _/ |___| ' \/ _ \ / -_)${resetColor} Pi-hole Core ${piholeVersionHeatmap}v${piholeVersion}${resetColor}"
314-
# echo "|_| |_| |_||_\___/_\___|${resetColor} (Web ${webVersionHeatmap}v${webVersion}${resetColor}, FTL ${ftlVersionHeatmap}v${ftlVersion}${resetColor})"
315354
echo ""
316355
}
317356

318357
outputNetworkInformation() {
319358
echo "NETWORK ===================================================="
320-
printf " %-10s%-19s%-10s%-19s\n" "Hostname:" "$(hostname)" "Domain:" ${PIHOLE_DOMAIN}
359+
printf " %-10s%-19s %-10s%-19s\n" "Hostname:" "$(hostname)" "Domain:" ${PIHOLE_DOMAIN}
321360
printf " %-10s%-19s\n" "IPv4:" "${IPV4_ADDRESS}"
322361
printf " %-10s%-19s\n" "IPv6:" "${IPV6_ADDRESS}"
362+
363+
if [[ "${DHCP_ACTIVE}" == "true" ]]; then
364+
printf " %-10s${dhcpHeatmap}%-19s${resetColor} %-10s${dhcpIPv6Heatmap}%-19s${resetColor}\n" "DHCP:" "${dhcpStatus}" "IPv6:" ${dhcpIPv6Status}
365+
printf "${dhcpInfo}\n"
366+
fi
323367
}
324368

325369
outputPiholeInformation() {
326370
echo "PI-HOLE ===================================================="
327-
printf " %-10s${piHoleHeatmap}%-19s${resetColor}%-10s${ftlHeatmap}%-19s${resetColor}\n" "Status:" "${piHoleStatus}" "FTL:" "${ftlStatus}"
371+
printf " %-10s${piHoleHeatmap}%-19s${resetColor} %-10s${ftlHeatmap}%-19s${resetColor}\n" "Status:" "${piHoleStatus}" "FTL:" "${ftlStatus}"
328372
}
329373

330374
outputPiholeStats() {
331375
# Pi-Hole Information
332376
echo "STATS ======================================================"
333-
printf " %-10s%0.0f\n" "Blocking:" "${domains_being_blocked}"
334-
printf " %-10s%-19s%-10s%-19s\n" "Queries:" "${dns_queries_today}" "Pi-holed:" "${ads_blocked_today} (${ads_percentage_today}%)"
335-
printf " %-10s%-39s\n" "Latest:" "${domain}"
377+
printf " %-10s%-49s\n" "Blocking:" "${domains_being_blocked} domains"
378+
printf " %-10s[%-40s] %-5s\n" "Pi-holed:" "${adsBlockedBar}" "${ads_percentage_today}%"
379+
printf " %-10s%-49s\n" "Pi-holed:" "${ads_blocked_today} out of ${dns_queries_today} queries"
380+
printf " %-10s%-39s\n" "Latest:" "${latestBlocked}"
381+
printf " %-10s%-39s\n" "Top Ad:" "${topBlocked}"
382+
if [[ "${DHCP_ACTIVE}" != "true" ]]; then
383+
printf " %-10s%-39s\n" "Top Dmn:" "${topDomain}"
384+
printf " %-10s%-39s\n" "Top Clnt:" "${topClient}"
385+
fi
336386
}
337387

338388
outputSystemInformation() {
339389
# System Information
340390
echo "SYSTEM ====================================================="
341-
printf " %-10s%-19s\n" "Uptime:" "${systemUptime}"
391+
# Uptime
392+
printf " %-10s%-39s\n" "Uptime:" "${systemUptime}"
393+
394+
# Temp and Loads
342395
printf " %-10s${tempHeatMap}%-19s${resetColor}" "CPU Temp:" "${temperature}"
343396
printf " %-10s${cpuLoad1Heatmap}%-4s${resetColor}, ${cpuLoad5Heatmap}%-4s${resetColor}, ${cpuLoad15Heatmap}%-4s${resetColor}\n" "CPU Load:" "${cpuLoad1}" "${cpuLoad5}" "${cpuLoad15}"
344-
printf " %-10s%-19s%-10s${cpuLoad1Heatmap}%-19s${resetColor}" "Memory:" "${memoryUsedPercent}%" "CPU Load:" "${cpuPercent}%"
397+
398+
# Memory and CPU bar
399+
printf " %-10s[${memoryHeatmap}%-10s${resetColor}] %-5s %-10s[${cpuLoad1Heatmap}%-10s${resetColor}] %-5s" "Memory:" "${memoryBar}" "${memoryUsedPercent}%" "CPU Load:" "${cpuBar}" "${cpuPercent}%"
345400
}
346401

347402
normalChrono() {
348403
for (( ; ; )); do
349404
GetSummaryInformation
350-
domain=$(GetFTLData recentBlocked)
405+
406+
latestBlocked=$(GetFTLData recentBlocked)
407+
topBlocked=$(GetFTLData "top-ads (1)" | awk '{print $3}')
408+
409+
topDomain=$(GetFTLData "top-domains (1)" | awk '{print $3}')
410+
topClient=$(GetFTLData "top-clients (1)" | awk '{print $3}')
411+
351412
clear
352413

353414
# Get Config variables
@@ -358,7 +419,6 @@ normalChrono() {
358419
outputPiholeInformation
359420
outputPiholeStats
360421
outputNetworkInformation
361-
outputDHCPInformation
362422
outputSystemInformation
363423

364424
# Get our information
@@ -439,7 +499,7 @@ if [[ $# = 0 ]]; then
439499
echo ""
440500
printf "Chronometer2 will start in"
441501

442-
for i in 5 4 3 2 1
502+
for i in 3 2 1
443503
do
444504
printf " $i..."
445505
sleep 1

0 commit comments

Comments
 (0)