Domoticz cz. 5: Grafana, Influxdb oraz Telegraf – łatwe w implementacji i piękne wykresy!

Domoticz cz. 5: Grafana, Influxdb oraz Telegraf – łatwe w implementacji i piękne wykresy!

Grafana to odpowiedź na nurtujące nas od lat pytanie – jak prosto szybko i ładnie przedstawić dane z naszych urządzeń. InfluxDB to z kolei baza danych, która jest tak łatwa i prosta w obsłudze, że idealnie nadaje się do naszych zastosowań. Pokażę Wam jak prosto i szybko przenieść nasze dane z domoticza, oraz innych urządzeń do InfluxDB, a następnie używając Grafany wyświetlić je w taki sposób aby można było z nich dostać znacznie więcej niż z wykresów domoticza – staną się bardzo użyteczne.
wyrozniacz-grafana
Aktualizacja: 2019-07-10: PhantomJS i Grafana 5/6.x na ARM

Czego będziemy potrzebować?

Software

  • InfluxDB
  • Grafana
  • własne skrypty w bash’u

Hardware

  • Rekomendowane: Raspberry Pi wersja 4,
  • ALBO: Raspberry Pi 2/3/4 A/B/B+ lub Zero (armv6)
  • ALBO: mini komputer z ARM innych producentów (np: OrangePi PC z oficjalnego sklepu z CPU H3/H2/H5) – zwykle są tańsze, Może być to też maszyna x86 z Debianem, ale żadna jednak nie będzie nas kosztować 4-6W jak te oparte o ARMy. W tym przykładzie użyłem najpierw Raspberry Pi 2, ale potem postanowiłem przetestować Orange Pi Pc z ostatnim armbianem.

Instalacja

InfluxDB

Pobieramy z https://www.influxdata.com/downloads/ najnowszą wersję InfluxDB (w chwili pisania 1.0.2) dla „Standalone Linux Binaries (ARM)”:

cd /tmp
wget https://dl.influxdata.com/influxdb/releases/influxdb-1.0.2_linux_armhf.tar.gz

Następnie tworzymy użytkownika influxdb w systemie

sudo adduser influxdb

Odpowiadamy twierdząco na pytania, możemy podać dane, hasło lub nie.
Sprawdzamy, czy użytkownik istnieje:

id influxdb

W odpowiedzi powinniśmy otrzymać podobnie jak tutaj:

uid=1001(influxdb) gid=1001(influxdb) grupy=1001(influxdb)

Teraz instalujemy z pliku binarnego influxdb:

sudo tar xzf influxdb-1.0.2_linux_armhf.tar.gz 
cd influxdb-1.0.2-1
cp -R * /
sudo chown influxdb:influxdb -R /etc/influxdb
sudo chown influxdb:influxdb -R /var/log/influxdb
sudo mkdir -p /var/lib/influxdb
sudo chown influxdb:influxdb -R /var/lib/influxdb
sudo cp /usr/lib/influxdb/scripts/init.sh /etc/init.d/influxdb
sudo chmod 755 /etc/init.d/influxdb
sudo cp /usr/lib/influxdb/scripts/influxdb.service /etc/systemd/system

Jeśli wszystko przebiegło pomyślnie możemy uruchomić InfluxDB:

/etc/init.d/influxdb start

Jeśli baza działa, to możemy skonfigurować, aby uruchamiała się po restarcie systemu; tym razem – zróbmy to inaczej – instalujemy

 sudo apt-get install rcconf

uruchamiamy i zaznaczamy spacją „*” przy influxdb.

Grafana

Tym razem – trochę prościej, a budowanie jest opcjonalne – korzystamy z pakietów (odpowiednio dla wersji Raspberry Pi 2 i 3 lub A/B/B+, Zero) https://github.com/fg2it/grafana-on-raspberry.
Przykład pakietu dla Raspberry Pi 2 lub 3, wybierz właściwą wersję i pobierz wget’em.

sudo apt-get install adduser libfontconfig
wget https://github.com/fg2it/grafana-on-raspberry/releases/download/v3.1.1-wheezy-jessie/grafana_3.1.1-1472506485_armhf.deb 
sudo dpkg -i grafana_3.1.1-1472506485_armhf.deb

Pakiet podpowiada nam po instalacji aby dodać grafanę do skryptów i uruchamiać przy starcie tak:

sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable grafana-server

Uruchamiamy grafanę:

sudo /bin/systemctl start grafana-server

Konfiguracja

Aktualne wersje InfluxDB zarządzamy poprzez linię komend (CLI):

pi@host:~$ influx 
Connected to http://localhost:8086 version 1.2.2
InfluxDB shell version: 1.2.2

Aby stworzyć bazę danych wystarczy:

create DATABASE domoticz
quit
pi@host:~$

Starsze wersje InfluxDB mają standardowo interfejs po adresem naszego Raspberry Pi, na porcie 8083. Standardowa konfiguracja pozwala od razu na dostęp, bez autoryzacji, przez http. Po połączeniu zobaczymy interfejs:
influxdb-1
a więc – po prostu z menu wybieramy „Create Database”, nasza pierwsza baza będzie nazywała się „domoticz”:
influxdb-2
To praktycznie… wszystko. Baza jest gotowa – obojętnie czy stworzona przez interfejs http czy przez cli – nie trzeba tworzyć zmienny etc. wystarczy po prostu do niej pisać.

Przesyłanie danych z Domoticza do InfluxDB

W Domoticzu wybieramy z menu „HTTP”:
http-connection-768x769
Wybieramy zmienną, którą chcemy umieścić w bazie – w przykładzie będzie to ciśnienie atmosferyczne:
http-data-pl-1
Jak to się odbywa? Wybieramy zmienną – czyli mierzoną już przez Domoticz dowolną wartość z menu „Nazwa urządzenia”. Następnie nadajemy jej numer – zwykle dla porządku, jest to numer IDX urządzenia w domoticz – w tym przypadku jest to „1450”. Zaznaczamy „Połączenie aktywne”, a po prawej stronie podajemy URL za pomocą którego będziemy pisać do bazy – adres, port – tym razem 8086, bo tam InfluxDB czeka na dane, nazwę bazy jaką stworzyliśmy, użytkownika/hasło (nie używamy tego jeszcze, więc jak rumianek – nie przeszkadza ale i nie pomaga), oraz precyzję danych.
Metoda to HTTP POST, uwierzytelnienie zostawiamy na później.
Najważniejsza część do „Dane:” tutaj podajemy faktycznie zmienną jaką potem będziemy z bazy czytać – oraz jej wartość i czas. Jak się domyślacie zmienna w bazie będzie się nazywa „device_1450” potem będzie jej wartość i czas. Można to sobie podejrzeć tshark’iem, jeśli ktoś jest ciekawy. I to wszystko – dane będą od teraz umieszczne w bazie „domoticz”, nie trzeba tworzyć ich ani nadawać im typów, nowoczesne podejście, prawda?

Przesyłanie danych z dowolnego urządzenia

InfluxDB jest tak przyjazny, że od razu rodzą się pomysły jak wykorzystać go do innych zadań. Skoro rozmawiamy z nim po HTTP, to oznacza, że możemy sami zapisywać w nim dane, lub w prosty sposób te dane tam przenosić. Wystarczy… curl, popularny program obecny w każdej dystrybucji:

apt-get install curl

Składnia i sposób jest następujący – na przykładzie prostego skryptu:

#!/bin/bash
predkosc_in=25000
predkosc_out=11000
curl -i -XPOST 'http://10.1.1.1:8086/write?db=snmp' --data-binary "inwisp,host=wisp value=${predkosc_in}"
curl -i -XPOST 'http://10.1.1.1:8086/write?db=snmp' --data-binary "ouwisp,host=wisp value=${predkosc_out}"

Przykład pokazuje uproszczoną wersję prostego skryptu, który odczytuje przez SNMP prędkość interfejsu bezprzewodowego do ISP, a więc pokazuje aktualne obciążenie łącza do internetu. curl odpowiada za wysłanie tych danych do bazy „snmp”, zmienną jest inwisp dla ruchu do i outwisp do ruchu od, a dodatkowo przy zmiennej jest parametr host (opcjonalny), celem późniejszego grupowania urządzeń. Następnie jako value – podawana jest prędkość. Nie ma informacji o czasie (zostanie użyty czas wysłania).
Cały skrypt – jeśli ktoś chciałby czytać interfejs rutera wygląda tak (zapewne lepiej użyć telegrafa, ale mam mały sentyment do MRTG i jego sposobu zbierania danych – zatem prezentuję właściwie 17-letni skrypt w bashu). Intencją jest uruchomienie go na screenie, podczas startu systemu – tak samo jak we wpisie o Flightradar i SDR.

 #!/bin/bash
#Skrypt odczytuje prędkość interfejsów w bitach z liczników 32-bit
#Licencja: GPL v2
#Autor: [email protected]
#Historia:
#1999-06-22/23 - Inicjalna wersja skryptu do testowania jak działa MRTG
#2016-11-12 - Przystosowanie do wpisu o grafanie jako przyklad, male zmiany pod aktualnego bash'a
#Ustawiamy zmienne
#Numer monitorowanego interfejsu - można poznać z snmpwalka
numer_interfejsu=5
#Nazwa community SNMP, zwykle public
community=public_secret
#Adres IP urządzenia jakie pytamy
ip_rutera=10.1.1.45
#Co ile sekund sprawdzamy predkosc lacza - najlepiej co 300 czyli 5 minut
co_ile_sekund=300
#Lacze - maksymalne wartosci - potrzebne do odsiania bledow - domyslnie 25/4
max_possible_in=25000000000
max_possible_out=4000000000
#Glowna petla - czytamy wartosci czekamy zadany czas i czytamy je znowu - odejmujemy od siebie aby wyznaczyc predkosc (tam na dole petli)
while [ 1 -eq 1 ]
do
 octety_wtedy_in=$(snmpget -v1 -c $community $ip_rutera 1.3.6.1.2.1.2.2.1.10.$numer_interfejsu | awk '{print $4}')
 octety_wtedy_out=$(snmpget -v1 -c $community $ip_rutera 1.3.6.1.2.1.2.2.1.16.$numer_interfejsu | awk '{print $4}')
 sleep $co_ile_sekund
 octety_teraz_in=$(snmpget -v1 -c $community $ip_rutera 1.3.6.1.2.1.2.2.1.10.$numer_interfejsu | awk '{print $4}')
 octety_teraz_out=$(snmpget -v1 -c $community $ip_rutera 1.3.6.1.2.1.2.2.1.16.$numer_interfejsu | awk '{print $4}')
#Najpierw sprawdzamy czy czasem nie będziemy dzielić przez zero, oraz czy się licznik nie przepełnił... Jesli cos jest nie tak to wartosc na 1
 if [ $octety_wtedy_in -eq $octety_teraz_in ]
 then
  octety_teraz_in=$((octety_teraz_in+1))
 fi
 if  [ $octety_wtedy_in -gt $octety_teraz_in ]
 then
  octety_wtedy_in=$((octety_teraz_in+1))
 fi
 if [ $octety_wtedy_out -eq $octety_teraz_out ]
 then
  octety_teraz_out=$((octety_teraz_out+1))
 fi
 if  [ $octety_wtedy_out -gt $octety_teraz_out ]
 then
  octety_wtedy_out=$((octety_teraz_out+1))
 fi
 #Maly debug - wyswietlamy ile nam wyszlo
 echo Wtedy In: $octety_wtedy_in
 echo Wtedy Out: $octety_wtedy_out
 echo Teraz In: $octety_teraz_in
 echo Teraz Out: $octety_teraz_out
 #Liczymy roznice
 roznica_in=$((octety_teraz_in-octety_wtedy_in))
 roznica_out=$((octety_teraz_out-octety_wtedy_out))
 #Jeszcze raz sprawdzamy czy nie mamy zlego wyniku (poprzednie nie wylapia jednej sytuacji... no jakiej?) 
 if [ $roznica_in -lt 0 ]
 then
  roznica_in=1
 fi
 if [ $roznica_out -lt 0 ]
 then
  roznica_out=1
 fi
 if [ $roznica_in -gt $max_possible_in ]
 then
  roznica_in=1
 fi
 if [ $roznica_out -gt $max_possible_out ]
 then
  roznica_out=1
 fi
 #Mamy nasza predkosc
 predkosc_in=$(((($roznica_in)/$co_ile_sekund)*8/1000))
 predkosc_out=$(((($roznica_out)/$co_ile_sekund)*8/1000))
 clear
 #Czyscimy kosnsole aby usunac poprzednie wyniki
 echo "Prędkość IN: "${predkosc_in}"kbps"
 echo "Prędkość OUT: "${predkosc_out}"kbps"
 #Zapis do InfluxDB
 curl -i -XPOST 'http://10.1.1.1:8086/write?db=snmp' --data-binary "inwisp,host=wisp value=${predkosc_in}"
 curl -i -XPOST 'http://10.1.1.1:8086/write?db=snmp' --data-binary "ouwisp,host=wisp value=${predkosc_out}"
done

Jeśli dane trafiły do bazy, w odpowiedzi z wywołania curl’a powinniśmy otrzymać:

HTTP/1.1 204 No Content
Request-Id: a11318b7-a590-11e6-cea7-000000000000
X-Influxdb-Version: 0.11.0
Date: Sun, 13 Nov 2016 11:02:39 GMT

Inną drogą aby sprawdzić czy nasze dane trafiają do bazy – to wywołanie z menu InfluxDB – SHOW MEASUREMENTS:
influx-measure-1

Grafana – wreszcie zapowiedziane wykresy!

Grafana oczekuje na nas na porcie 3000, logujemy się domyślnie admin/admin i przechodzimy z menu w lewym rogu do Data Sources. Wybieramy Add Source i wypełniamy – Type, URL, Access pozostawiamy na proxy, użytkwonik i hasło do bazy:
grafana-add
Mamy więc źródło danych, przejdźmy od razu do stworzenia swojego pierwszego „Dahsboard” czyli ekranu z wykresami:
new-dashboard
Następnie dodajemy pierwszy wykres:
grafana-add-graph
Otrzymamy domyślny panel z jedną serią danych do wykreślenie. Wygląda ładnie, ale nie zawiera jeszcze danych z naszej bazy:
grafana-panel-1
W kolejnym kroku wybieramy naszą bazę – na dole z Panel data source – zmieniamy z -Grafana- na SNMP. „A” czyli nasza seria danych będzie teraz wyglądać następująco:
grafana-toggle-edit-mode
grafana-add
Zielony wykres zniknął, ponieważ musimy wprowadzić odpowiednie dane do wykreślenia. Zaczynamy jak w przykładzie po prawej stronie – przełączamy się w tryb edycji bezpośredniej naszej kwerendy dla typu „A” i wypełniamy tak jak na przykładzie poniżej, następnie wybieramy przy bazie SNMP „+ Data query” i wypełniamy serię „B” – zmiany są aktualizowane na bieżąco:
grafana-inwifi-out-wifi
Teraz z menu „Axes” – wybieramy właściwy typ danych – box „Unit”, „data rate” > „kilobits/sec”. Dla porządku w „General” nazwijmy panel Internet i … gotowe. Ikona dyskietki zapisuje nasz panel do „dashboard’u”:
grafana-ready-graph
Następnie polecam zainstalować w grafanie dodatkowe wtyczki – które dają nam dodatkowe typy wykresów, oraz inne dodatki: https://grafana.net/plugins

Telegraf

Ostatni ciekawy program związany z wykresami to Telegraf. Niezwykle rozbudowany program monitorujący aplikacje, interfejsy sieciowe, procesor naszego komputera – pracuje pod Linuksem. Prosta instalacja łączy się z prostą obsługą.

Po pierwsze – zróbmy sobie dodatkową bazę – „telegrafPI” w InfluxdB, ale z linii komend:

pi@orangepipic-grafana:~$ influx
Visit https://enterprise.influxdata.com to register for updates, InfluxDB server management, and monitoring.
Connected to http://localhost:8086 version 1.1.0
InfluxDB shell version: 1.1.0
create database telegrafPI

Teraz instalujemy telegraf:
Tym razem możemy dodać źródło pakietów:

deb https://repos.influxdata.com/debian jessie stable

do

/etc/apt/sources.list

albo pobrać odpowiedni pakiet ręcznie poprzez

wget https://dl.influxdata.com/telegraf/releases/telegraf-1.1.2_linux_armhf.tar.gz
tar xvfz telegraf-1.1.2_linux_armhf.tar.gz

czy wreszcie pobrać

wget https://repos.influxdata.com/debian/pool/stable/t/telegraf/telegraf_1.1.1-1_armhf.deb
dpkg -i telegraf_1.1.1-1_armhf.deb

Konfiguracja jest niezwykle prosta – program sam stworzy plik konfiguracyjny, który należy skopiować do

/etc/telegraf

Dobry przykład na początek to CPU:

sudo mkdir -p /etc/telegraf
sudo telegraf --config telegraf.conf -input-filter cpu:mem -output-filter influxdb > /etc/telegraf/telegraf.conf/

Zakładając, że jest to ten sam host/komputer na jakim działa influxdB – nie wszystko zadziała od razu – a jeśli nie, to weryfikujemy link w konfiguracji z nazwą/IP hosta z bazą.
W Grafanie, po dodaniu nowego źródła tworzymy taki wykres, z seriami oraz zaznaczamy stacked:

A: SELECT last("usage_idle") FROM "cpu" WHERE $timeFilter GROUP BY time(1m) fill(none)
B: SELECT last("usage_user") FROM "cpu" WHERE $timeFilter GROUP BY time(1m) fill(none)
C: SELECT last("usage_system") FROM "cpu" WHERE $timeFilter GROUP BY time(1m) fill(none)
D: SELECT last("usage_guest") FROM "cpu" WHERE $timeFilter GROUP BY time(1m) fill(none)
E: SELECT last("usage_irq") FROM "cpu" WHERE $timeFilter GROUP BY time(1m) fill(none)

Co da nam taki rezultat, o ile wybierzecie „Stacked” w zakładce Display:
grafana-telegraf-example

Własne projekty

Grafana z InfluxDB jest też wykrozystywna w projektach mierzenia SMOGu.

Grafana 5.x oraz 6.x oraz PhantomJS
Czy spotkałeś się z problemem niedziałających screenshotów? Ponieważ nowsze wersje Grafany nie zawierają biblioteki PhantomJS – nie można poprawnie stworzyć zrzutu ekratu z danego wykresu do pliku *.PNG.

Przykładowe błędy:

Jun 10 19:12:01 grafana grafana-server[268]: 2019/07/10 19:12:01 [render.go:41 RenderToPng()] [E] Failed to render to png:
 fork/exec /var/lib/grafana/vendor/phantomjs/phantomjs: no such file or directory 

albo

lvl=eror msg="executable not found" logger=rendering executable=/usr/share/grafana/tools/phantomjs/phantomjs
lvl=eror msg="Rendering failed - PhantomJS isn't included in arm build per default" logger=context userId=1 orgId=1 uname=admin error="PhantomJS executable not found"

Czy też po prostu:
grafana_error
Aby przywrócić działanie należy

Powinno to przywrócić działanie screenshot/zrzutu ekranu.
To już koniec, miłego kreślenia pięknych wykresów!

Previous Post Next Post