Zbieranie różnych danych statystycznych w OpenWrt
Ostatnia zmiana: 2014-04-09 22:35
Strona projektu:
http://collectd.org/Collectd jest demonem zbierającym dane i zapisującym je w różnorodnej postaci. Sam z siebie nie potrafi rysować wykresów, ale dzięki odpowiednim pluginom można te dane gromadzić i obrabiać w dowolnym programie. Najczęściej wykorzystywane jest zapisywanie danych w plikach RRD, z których można prosto wygenerować wykresy dzięki narzędziu RRDtool.
Siłą tego programu jest duża liczba pluginów pozwalająca na zbieranie danych z dowolnych źródeł. Jeżeli z jakiegoś powodu nie znajdziemy odpowiedniego pluginu, istnieje możliwość wykonania dowolnego programu lub skryptu, dzięki czemu możliwości tego programu stają się nieograniczone. Główne jego zastosowanie to różnorodne zbieranie statystyk w celu późniejszej prezentacji.
Poniższe rozwiązanie sprawdzono w OpenWrt Attitude Adjustment 12.09.

Instalacja
# opkg update
# opkg install collectd
Sam program to jeszcze za mało, należy zainstalować wymagane pluginy. W chwili pisania tego opisu w OpenWrt dostępne były następujące:
- collectd-mod-apache: apache status input plugin
- collectd-mod-apcups: apcups status input plugin
- collectd-mod-ascent: ascent status input plugin
- collectd-mod-bind: BIND server/zone input plugin
- collectd-mod-conntrack: connection tracking table size input plugin
- collectd-mod-contextswitch: context switch input plugin
- collectd-mod-cpu: CPU input plugin
- collectd-mod-csv: CSV output plugin
- collectd-mod-curl: cURL input plugin
- collectd-mod-dbi: relational database input plugin
- collectd-mod-df: disk space input plugin
- collectd-mod-disk: disk usage/timing input plugin
- collectd-mod-dns: DNS traffic input plugin
- collectd-mod-email: email output plugin
- collectd-mod-exec: process exec input plugin
- collectd-mod-filecount: file count input plugin
- collectd-mod-fscache: file-system based caching framework input plugin
- collectd-mod-interface: network interfaces input plugin
- collectd-mod-iptables: iptables status input plugin
- collectd-mod-irq: interrupt usage input plugin
- collectd-mod-iwinfo: libiwinfo wireless statistics plugin
- collectd-mod-load: system load input plugin
- collectd-mod-logfile: log files output plugin
- collectd-mod-madwifi: MadWifi status input plugin
- collectd-mod-memory: physical memory usage input plugin
- collectd-mod-mysql: MySQL status input plugin
- collectd-mod-netlink: netlink input plugin
- collectd-mod-network: network input/output plugin
- collectd-mod-nginx: nginx status input plugin
- collectd-mod-ntpd: NTP daemon status input plugin
- collectd-mod-olsrd: OLSRd status input plugin
- collectd-mod-openvpn: OpenVPN traffic/compression input plugin
- collectd-mod-ping: ping status input plugin
- collectd-mod-postgresql: PostgreSQL status input plugin
- collectd-mod-powerdns: PowerDNS server status input plugin
- collectd-mod-processes: process status input plugin
- collectd-mod-protocols: network protocols input plugin
- collectd-mod-rrdtool: RRDtool output plugin
- collectd-mod-snmp: SNMP input plugin
- collectd-mod-syslog: syslog output plugin
- collectd-mod-table: table-like structured file input plugin
- collectd-mod-tail: tail input plugin
- collectd-mod-tcpconns: TCP connection tracking input plugin
- collectd-mod-teamspeak2: TeamSpeak2 input plugin
- collectd-mod-ted: The Energy Detective input plugin
- collectd-mod-thermal: system temperatures input plugin
- collectd-mod-unixsock: unix socket output plugin
- collectd-mod-uptime: uptime status input plugin
- collectd-mod-users: user logged in status input plugin
- collectd-mod-vmem: virtual memory usage input plugin
- collectd-mod-wireless: wireless status input plugin
- collectd-mod-write-http: HTTP POST output plugin
Mamy więc pluginy zbierające dane z UPS, sprawdzające statusy serwerów dns, baz danych i innych demonów, monitorujące wykorzystanie procesora, przerwań, pamięci dysku, dane statystyczne z systemów plików, interfejsów, dane z czujników, interfejsów bezprzewodowych. Można zbierać dane z SNMP (dzięki czemu można gromadzić dane z innych urządzeń do których można podłączyć się w ten sposób) a także zbierać dane przez wykonanie dowolnego skryptu lub programu. Dostępny jest plugin iptables potrafiący zbierać dane z różnych łańcuchów (więc nic nie stoi na przeszkodzie aby zbierać statystyki dla poszczególnych hostów).
Instalujemy więc kilka z nich:
# opkg install collectd-mod-cpu collectd-mod-df collectd-mod-interface
# opkg install collectd-mod-load collectd-mod-memory collectd-mod-wireless
# opkg install collectd-mod-ping collectd-mod-iwinfo
Ten zestaw zapewni nam informacje o obciążeniu i wykorzystaniu procesora, zużyciu pamięci, ilość wolnej przestrzeni na dyskach, ilości przesłanych bajtów przez interfejsy a także np. dostępność łącza internetowego przez wizualizację czasu odpowiedzi pingu.
Pluginy te służą do zbierania danych, a należy jeszcze je gdzieś przechowywać. Można to zrobić instalując plugin CSV zapisujący dane w tym formacie
# opkg install collectd-mod-csv
lub w plikach RRD niezbędnych w późniejszym czasie do generowania wykresów
# opkg install collectd-mod-rrdtool
Konfiguracja
Plik konfiguracyjny to
/etc/collectd.conf. Jego składnia jest dość prosta: na początku znajdują się opcje globalne dla
collectd:
BaseDir "/var/lib/collectd"
PIDFile "/var/run/collectd.pid"
Interval 30
ReadThreads 2
Każdy plugin ładujemy poleceniem
LoadPlugin nazwa, np:
Jeżeli plugin wymaga jakiś opcji konfiguracyjnych lub chcemy jakieś zmienić należy utworzyć sekcję
<Plugin nazwa> </Plugin> i podać parametry. Dla wspomnianego pluginu ping, w przypadku potrzeby pingowania np. DNS Google może to wyglądać następująco:
<Plugin ping>
Host "8.8.8.8"
</Plugin>
Jeżeli nie podamy danych - zostaną przyjęte wartości domyślne. Opcje pluginów są
bardzo dobrze udokumentowane, należy więc zapoznać się z odpowiednim fragmentem dokumentacji przy konfiguracji pluginu.
Dla wspomnianego zestawu pluginów plik konfiguracyjny może wyglądać następująco:
BaseDir "/var/lib/collectd"
PIDFile "/var/run/collectd.pid"
Interval 30
ReadThreads 2
LoadPlugin cpu
LoadPlugin df
LoadPlugin interface
LoadPlugin load
LoadPlugin memory
LoadPlugin rrdtool
LoadPlugin wireless
LoadPlugin ping
LoadPlugin iwinfo
<Plugin ping>
Host "8.8.8.8"
</Plugin>
<Plugin rrdtool>
DataDir "/mnt/sda1/rrd"
RRARows 100
RRASingle 1
RRATimespan 600
RRATimespan 3600
RRATimespan 86400
RRATimespan 604800
RRATimespan 2678400
RRATimespan 31622400
</Plugin>
Szczegółowo został skonfigurowany plugin rrdtool, wykorzystując katalog
/mnt/sda1/rrd do tworzenia pliku danych gromadzonych pomiary w okresie 10 minut, jednej godziny, jednego dnia, jednego tygodnia, jednego miesiąca i jednego roku.
Uruchomienie
# /etc/init.d/collectd enable
# /etc/init.d/collectd start
Wcześniej należy zadbać o prawidłowe ustawienie daty i godziny systemowej. Po uruchomieniu demon zbiera dane w katalogu
/mnt/sda1/rrd, na podstawie parametrów zdefiniowanych w pliku konfiguracyjnym. Niestety dane wynikowe są w mało czytelnej postaci i warto przekształcić je na wykresy.
Wykresy
Pliki RRD są to bazy danych, w określonym formacie, przechowujące dane wg określonych parametrów podanych podczas ich tworzenia. Obróbką tych danych może zająć się program RRDtool, który pozwala m.in. na wyciąganie danych i generowanie plików graficznych.
Informacje o pliku
Sprawdźmy jakie dane przechowuje taki plik RRD - np. z danymi od pluginu ping:
# rrdtool info /mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd
filename = "/mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd"
rrd_version = "0001"
step = 30
last_update = 1363598694
ds[ping].type = "GAUGE"
ds[ping].minimal_heartbeat = 60
ds[ping].min = 0.0000000000e+00
ds[ping].max = 6.5535000000e+04
ds[ping].last_ds = "UNKN"
ds[ping].value = 3.9543297360e+03
ds[ping].unknown_sec = 0
rra[0].cf = "AVERAGE"
rra[0].rows = 100
rra[0].pdp_per_row = 1
rra[0].xff = 1.0000000000e-01
rra[0].cdp_prep[0].value = NaN
rra[0].cdp_prep[0].unknown_datapoints = 0
rra[1].cf = "MIN"
rra[1].rows = 100
rra[1].pdp_per_row = 1
rra[1].xff = 1.0000000000e-01
rra[1].cdp_prep[0].value = NaN
rra[1].cdp_prep[0].unknown_datapoints = 0
rra[2].cf = "MAX"
rra[2].rows = 100
rra[2].pdp_per_row = 1
rra[2].xff = 1.0000000000e-01
rra[2].cdp_prep[0].value = NaN
rra[2].cdp_prep[0].unknown_datapoints = 0
rra[3].cf = "AVERAGE"
rra[3].rows = 120
rra[3].pdp_per_row = 1
rra[3].xff = 1.0000000000e-01
rra[3].cdp_prep[0].value = NaN
rra[3].cdp_prep[0].unknown_datapoints = 0
rra[4].cf = "MIN"
rra[4].rows = 120
rra[4].pdp_per_row = 1
rra[4].xff = 1.0000000000e-01
rra[4].cdp_prep[0].value = NaN
rra[4].cdp_prep[0].unknown_datapoints = 0
rra[5].cf = "MAX"
rra[5].rows = 120
rra[5].pdp_per_row = 1
rra[5].xff = 1.0000000000e-01
rra[5].cdp_prep[0].value = NaN
rra[5].cdp_prep[0].unknown_datapoints = 0
rra[6].cf = "AVERAGE"
rra[6].rows = 103
rra[6].pdp_per_row = 28
rra[6].xff = 1.0000000000e-01
rra[6].cdp_prep[0].value = 3.5622209716e+03
rra[6].cdp_prep[0].unknown_datapoints = 0
rra[7].cf = "MIN"
rra[7].rows = 103
rra[7].pdp_per_row = 28
rra[7].xff = 1.0000000000e-01
rra[7].cdp_prep[0].value = 1.1713506000e+02
rra[7].cdp_prep[0].unknown_datapoints = 0
rra[8].cf = "MAX"
rra[8].rows = 103
rra[8].pdp_per_row = 28
rra[8].xff = 1.0000000000e-01
rra[8].cdp_prep[0].value = 2.6052363000e+02
rra[8].cdp_prep[0].unknown_datapoints = 0
rra[9].cf = "AVERAGE"
rra[9].rows = 101
rra[9].pdp_per_row = 201
rra[9].xff = 1.0000000000e-01
rra[9].cdp_prep[0].value = 2.5435662137e+04
rra[9].cdp_prep[0].unknown_datapoints = 0
rra[10].cf = "MIN"
rra[10].rows = 101
rra[10].pdp_per_row = 201
rra[10].xff = 1.0000000000e-01
rra[10].cdp_prep[0].value = 6.2110382600e+01
rra[10].cdp_prep[0].unknown_datapoints = 0
rra[11].cf = "MAX"
rra[11].rows = 101
rra[11].pdp_per_row = 201
rra[11].xff = 1.0000000000e-01
rra[11].cdp_prep[0].value = 2.8323346740e+02
rra[11].cdp_prep[0].unknown_datapoints = 0
rra[12].cf = "AVERAGE"
rra[12].rows = 101
rra[12].pdp_per_row = 892
rra[12].xff = 1.0000000000e-01
rra[12].cdp_prep[0].value = 3.8038554151e+04
rra[12].cdp_prep[0].unknown_datapoints = 308
rra[13].cf = "MIN"
rra[13].rows = 101
rra[13].pdp_per_row = 892
rra[13].xff = 1.0000000000e-01
rra[13].cdp_prep[0].value = 6.2110382600e+01
rra[13].cdp_prep[0].unknown_datapoints = 308
rra[14].cf = "MAX"
rra[14].rows = 101
rra[14].pdp_per_row = 892
rra[14].xff = 1.0000000000e-01
rra[14].cdp_prep[0].value = 2.9323911280e+02
rra[14].cdp_prep[0].unknown_datapoints = 308
rra[15].cf = "AVERAGE"
rra[15].rows = 101
rra[15].pdp_per_row = 10540
rra[15].xff = 1.0000000000e-01
rra[15].cdp_prep[0].value = 3.8038554151e+04
rra[15].cdp_prep[0].unknown_datapoints = 4580
rra[16].cf = "MIN"
rra[16].rows = 101
rra[16].pdp_per_row = 10540
rra[16].xff = 1.0000000000e-01
rra[16].cdp_prep[0].value = 6.2110382600e+01
rra[16].cdp_prep[0].unknown_datapoints = 4580
rra[17].cf = "MAX"
rra[17].rows = 101
rra[17].pdp_per_row = 10540
rra[17].xff = 1.0000000000e-01
rra[17].cdp_prep[0].value = 2.9323911280e+02
rra[17].cdp_prep[0].unknown_datapoints = 4580
(w pliku są już zgromadzone pewne dane).
Generowanie wykresu
Znając możliwości RRDtool można wygenerować na podstawie tych danych odpowiedni plik graficzny, np:
# rrdtool graph /www/ping-8.8.8.8-1hour.png -t "OpenWrt/ping/ping-8.8.8.8 1hour" --imgformat PNG --width 600 --height 100 --start now-1hour --end now --interlaced DEF:ping_avg=/mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd:ping:AVERAGE DEF:ping_max=/mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd:ping:MAX AREA:ping_max#ffe8e8 LINE2:ping_avg#ff7777:ping GPRINT:ping_avg:AVERAGE:%5.1lf%sAvg GPRINT:ping_max:MAX:%5.1lf%sMax >/dev/null 2>&1
# rrdtool graph /www/ping-8.8.8.8-1day.png -t "OpenWrt/ping/ping-8.8.8.8 1day" --imgformat PNG --width 600 --height 100 --start now-1day --end now --interlaced DEF:ping_avg=/mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd:ping:AVERAGE DEF:ping_max=/mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd:ping:MAX AREA:ping_max#ffe8e8 LINE2:ping_avg#ff7777:ping GPRINT:ping_avg:AVERAGE:%5.1lf%sAvg GPRINT:ping_max:MAX:%5.1lf%sMax >/dev/null 2>&1
# rrdtool graph /www/ping-8.8.8.8-1week.png -t "OpenWrt/ping/ping-8.8.8.8 1week" --imgformat PNG --width 600 --height 100 --start now-1week --end now --interlaced DEF:ping_avg=/mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd:ping:AVERAGE DEF:ping_max=/mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd:ping:MAX AREA:ping_max#ffe8e8 LINE2:ping_avg#ff7777:ping GPRINT:ping_avg:AVERAGE:%5.1lf%sAvg GPRINT:ping_max:MAX:%5.1lf%sMax >/dev/null 2>&1
# rrdtool graph /www/ping-8.8.8.8-1month.png -t "OpenWrt/ping/ping-8.8.8.8 1month" --imgformat PNG --width 600 --height 100 --start now-1month --end now --interlaced DEF:ping_avg=/mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd:ping:AVERAGE DEF:ping_max=/mnt/sda1/rrd/OpenWrt/ping/ping-8.8.8.8.rrd:ping:MAX AREA:ping_max#ffe8e8 LINE2:ping_avg#ff7777:ping GPRINT:ping_avg:AVERAGE:%5.1lf%sAvg GPRINT:ping_max:MAX:%5.1lf%sMax >/dev/null 2>&1
Generuje to w katalogu /www cztery pliki PNG będące wykresami średniego czasu ping do hosta 8.8.8.8 (DNS Google) w przedziale 1 godziny, 1 dnia, 1 tygodnia i jednego miesiąca.

Wyświetlanie na stronie WWW
O ile nie mamy zainstalowanego serwera www to należy wykonać to teraz i go uruchomić:
# opkg install uhttpd
# /etc/init.d/uhttpd enable
# /etc/init.d/uhttpd start
A następnie utworzyć stronę zawierającą te wykresy:
# echo "<html><body><img src=ping-8.8.8.8-1hour.png><br><img src=ping-8.8.8.8-1day.png><br><img src=ping-8.8.8.8-1week.png><br><img src=ping-8.8.8.8-1month.png></body></html>" > /www/wykres.html
Wczytujemy w przeglądarce stronę http://192.168.1.1/wykres.html i oglądamy rezultat naszych działań.
Poniżej zaprezentowane kilka różnych wykresów:








Generowanie wykresów ze wszystkich plików
Jeżeli zainstalowaliśmy dużo pluginów to plików z danymi RRD jest bardzo dużo (w tym przykładzie: 44). Próba ręcznego utworzenia skryptów tworzących wykresy jest dość pracochłonna i wymaga pewnego nakładu czasu na jego przygotowanie. Można sprawę uprościć uruchamiając odpowiedni skrypt który samodzielnie wygeneruje wszystkie wykresy; taki skrypt jest zawarty w pakiecie źródłowym
collectd pod nazwą
collectd2html.pl i wymaga do działania perla. Jego instalacja:
# opkg install perl
# opkg install perlbase-essential perlbase-fatal
# opkg install perlbase-file perlbase-getopt
# wget http://dl.eko.one.pl/projekty/collectd/collectd2html.px -O /bin/collectd2html.pl
# chmod 777 /bin/collectd2html.pl
Jego uruchomienie w bieżącym katalogu spowoduje wygenerowanie odpowiednich podkatalogów wraz z plikami graficznymi oraz samego pliku indeksu:
# cd /www
# collectd2html.pl
Generowany plik indeksu ma nazwę
nazwa_hosta.xhtml, wystarczy więc jeszcze zrobić odpowiedni link:
# ln -s /www/OpenWrt.xhtml /www/wykresy.html
I wczytać w przeglądarce adres http://192.168.1.1/wykresy.html
Domyślny wygląd strony nie należy do najładniejszych, ale generuje za nas wszystkie wymagane pliki. Jeżeli ktoś jest dociekliwy to
pod tym linkiem można znaleźć listę poleceń dzięki którym zostały wykresy utworzone. Można więc zrezygnować z perla i tego skryptu, ręcznie generując wykresy wg własnych parametrów.
Cykliczne generowanie wykresów
Mając już skrypt służący do generowania danych można go wykonać cyklicznie w
cronie. np.
# echo "*/10 * * * * collectd2html.pl" >> /etc/crontabs/root
# /etc/init.d/cron enable
# /etc/init.d/cron start
Zakończenie
Przy odrobinie znajomości HTML można utworzyć lub przerobić samodzielnie plik indeksu, robić inne tytuły, kolory wykresów, szablon strony itd. Należy pamiętać że generowanie wykresów trwa parę sekund i może obciążać system, szczególnie jeżeli danych do obróbki jest dość dużo.
LuCI
Jeżeli mamy środowisko graficzne LuCI to nie należy zapominać że mamy dostępne statystki bazujące na collectd. Wszystko co musimy zrobić to zainstalować odpowiedni aplet
# opkg install luci-app-statistics
A następnie zresetować lub uruchomić generator pliku konfiguracyjnego
# /etc/init.d/luci_statistics start
Same wykresy dostępne są w zakładce Statistics/Graphs i zawierają predefiniowane wykresy dla pamięci, procsora, sieci bezprzewodowej, obciążenia systemu oraz interfejsów.