diff --git a/articles/2016/netdata.md b/articles/2016/netdata.md index 85b4e24358afb3d08f0e29c9653f8803bcc3faf5..24e614faf96bd189fb904a15e0606888cea1ac91 100644 --- a/articles/2016/netdata.md +++ b/articles/2016/netdata.md @@ -2,7 +2,7 @@ title = "netdata" perex = "Netdata je skvÄ›lĂ˝ program, kterĂ˝ sloužà k monitorovnánĂ Vašeho serveru v reálnĂ©m ÄŤase, ve Vašem prohlĂĹľeÄŤi s minimem nastavovánĂ tak, Ĺľe uĹľ nebudete chtĂt nic jinĂ©ho." -tags = ["ÄŚlánky","ProgramovánĂ","Nástroje"] +tags = ["ÄŚlánky","ProgramovánĂ","Nástroje","netdata"] image = "lead.jpg" lang = "bash" diff --git a/articles/2017/vlastni-plugin-pro-netdata.md b/articles/2017/vlastni-plugin-pro-netdata.md new file mode 100644 index 0000000000000000000000000000000000000000..d515d0e020d8f608350ecf0eab82f67d4fd9fd7f --- /dev/null +++ b/articles/2017/vlastni-plugin-pro-netdata.md @@ -0,0 +1,207 @@ +``` +title = "VlastnĂ plugin pro netdata" +tags = ["ProgramovánĂ","netdata"] +image = "lead.jpg" + +``` + +O nástroji pro monitorovánĂ serveru v reálnĂ©m ÄŤase jsem jiĹľ psal v ÄŤlánku o [netdata](clanek/2016/netdata). Dnes budu popisovat, jak si mĹŻĹľete naprogramovat vlastnĂ plugin, kterĂ˝ Vám bude v netdata vykreslovat napĹ™Ăklad teplotu a vlhkost z ÄŤidla, kterĂ© máte pĹ™ipojeno k Raspberry. + + + +Plugin je moĹľnĂ© naprogramovat v jakĂ©mkoliv jazyce, pokud vĂ˝slednĂ˝ program dokáže vypisovat na standardnĂ vĂ˝stup (*stdout*). Dále je moĹľnĂ© vyuĹľĂt modulárnĂ pluginy pro BASH, Python a Node.js, kterĂ© majĂ unadnit nastavenĂ a vykreslovánĂ grafĹŻ. + +API netdata je popsáno na [wiki projektu](https://github.com/firehol/netdata/wiki/External-Plugins) a myslĂm si, Ĺľe je popsáno ne ĂşplnÄ› šťastnĂ˝m zpĹŻsobem. PĹ™i programovánĂ mĂ©ho pluginu jsem tedy hlavnÄ› zkoumal, co do netdata posĂlajĂ ostatnĂ pluginy, kterĂ© jsou umĂstÄ›nĂ© v: +- StandardnĂ - `/usr/libexec/netdata/plugins.d/` +- Bash - `/usr/libexec/netdata/charts.d/` +- Python - `/usr/libexec/netdata/python.d/` +- Node.js - `/usr/libexec/netdata/node.d/` + +<br> +Pro svĹŻj plugin jsem vyuĹľil standardnĂ API netdata a programovacĂ jazyk C++. Budu tedy popisovat hlavnÄ› mĂ© zkušenosti s touto kombinacĂ. + +# API netdata +StandardnĂ pluginy, kterĂ© vyuĹľĂvajĂ API netdata, fungujĂ tak, Ĺľe netdata pĹ™i startu spouštÄ›jĂ všechny spustitelnĂ© soubory, kterĂ© se nacházejĂ v `/usr/libexec/netdata/plugins.d/` a pĹ™edávajĂ jim jeden parametr, kterĂ˝ Ĺ™Ăká, po kolika sekundách má plugin aktualizovat data. Je tedy takĂ© nutnĂ© poÄŤĂtat s tĂm, Ĺľe se pluginy spouštĂ pod uĹľivatelem netdata, kterĂ˝ nemusĂ mĂt všechna potĹ™ebná práva. Plugin po spuštÄ›nĂ nastavĂ grafy, do kterĂ˝ch chce posĂlat data a potĂ© uĹľ v pravidelnĂ˝ch intervalech odesĂlá naměřenĂ© hodnoty. + +Komunikace pluginu s netdata probĂhá pĹ™es standardnĂ vĂ˝stup `stdout`. Zpráva se skládá z ĂşvodnĂho klĂÄŤovĂ©ho slova (**CHART, DIMENSION, SET, ...**), dále následujĂ parametry a zpráva je ukonÄŤena znakem novĂ©ho řádku `\n`. + +Plugin mĹŻĹľe vypisovat chyby na chybovĂ˝ vĂ˝stup `stderr`, kterĂ˝ je pĹ™esmÄ›rován do logu netdata, pokud je logovánĂ povoleno. + +Parametry je nutno uvádÄ›t do jednoduchĂ˝ch uvozovek `'parametr'`, pokud obsajĂ nepovolenĂ© znaky (mezera) a pokud je parametr vynechán, tak se odešlou jen prázdnĂ© uvozovky `''`. Parametry mohou obsahovat znaky s diakritikou, ale v netdata se nezobrazĂ správnÄ›. + +## NastavenĂ grafu +Nejprve se musĂ vytvoĹ™it graf, do kterĂ©ho se potĂ© vykreslujĂ data. K tomu sloužà zpráva **CHART**, která má následujĂcĂ formát: +``` +CHART type.id name title units [family [context [charttype [priority [update_every]]]]] +``` + +**type.id**<br> +UnikátnĂ název grafu, na kterĂ˝ se dále odkazuje z dalšĂch pĹ™ĂkazĹŻ. `type` oznaÄŤuje kategorii v menu. + +**name**<br> +Je pouĹľito pro komunikaci s uĹľivatelem jako název grafu. Pokud nenĂ vyplnÄ›no, tak se pouĹľije **id**. + +**title**<br> +Popis, kterĂ˝ se zobrazuje nad grafem. + +**units**<br> +Jednotky hodnot, kterĂ© jsou vykresleny v grafu. + +**family**<br> +Sloužà pro seskupovánĂ grafĹŻ pod submenu v grafu. Všechny grafy, kterĂ© vykreslujĂ teplotu by mÄ›ly mĂt **family** nastaveno napĹ™Ăklad na `'Teplota'`. + +**context**<br> +Seskupuje grafy, kterĂ© majĂ stejnĂ˝ **context**, aby mÄ›ly stejnĂ˝ vizuálnĂ styl. + +**charttype**<br> +Nastavuje typ grafu. MoĹľnĂ© hodnoty jsou *line*, *area*, *stacked*. Pokud chybĂ, tak je pouĹľit typ *line*. + +**priority**<br> +Udává pozici v menu. Menšà čĂslo znamená vÄ›tšà prioritu a grafy se tak zobrazĂ výše na stránce. 10000 nastavuje prioritu tak, Ĺľe se grafy zobrazĂ pod grafy vyuĹľitĂ procesoru. + +**update_every**<br> +PĹ™episuje periodu aktualizace, která je nastavena serverem. MÄ›la by odpovĂdat periodÄ›, s kterou se doopravdy odesĂlajĂ data. + +### **PĹ™Ăklad** +NastavenĂ grafĹŻ, pro zobrazenĂ venkonvĂ i vnitĹ™nĂ teploty a vlhkosti by mohlo vypadat následovnÄ›: +``` +CHART Meteostanice.temperature_outside 'Venkovni teplota' '°C' teploty '' line 10000 1 +CHART Meteostanice.temperature_inside 'Vnitrni teplota' '°C' teploty '' line 10001 1 +CHART Meteostanice.humidity 'Vlhkost' '%' vlhkosti '' line 10002 1 +``` + +## NastavenĂ dimenzĂ +Pro kaĹľdĂ˝ graf se musĂ nastavit dimenze (data), kterĂ© se v nÄ›m zobrazujĂ a graf jich mĹŻĹľe mĂt vĂce. K tomu sloužà zpráva **DIMENSION** s formátem: +``` +DIMENSION id [name [algorithm [multiplier [divisor [hidden]]]]] +``` + +NastavenĂ dimenzĂ musĂ probÄ›hnout hned po nadefinovánĂ konkrĂ©tnĂho grafu, do kterĂ©ho majĂ nastavovanĂ© dimenze patĹ™it. + +**id**<br> +JmĂ©no dimenze, na kterĂ© se odkazuje pĹ™i odesĂlánĂ dat. NemÄ›lo by obsahovat znak `.`. + +**name**<br> +JmĂ©no dimenze, kterĂ© se zobrazuje uĹľivateli. + +**algorithm**<br> +Nastavuje algoritmus pro zpracovánĂ pĹ™ijatĂ˝ch dat. MĹŻĹľe bĂ˝t napĹ™Ăklad *absolute*, kdy se data zobrazujĂ tak, jak byla pĹ™ijata, nebo napĹ™Ăklad *incremental*, kdy se k zobrazovanĂ© hodnotÄ› pĹ™iÄŤĂtajĂ pĹ™ijatá data. + +**multiplier**<br> +Hodnota (celĂ© ÄŤĂslo), kterou se násobĂ pĹ™ijatá data. + +**divisor**<br> +Hodnota (celĂ© ÄŤĂslo), kterĂ˝m se dÄ›lĂ pĹ™ijatá data. + +**hidden**<br> +KlĂÄŤovĂ© slovo *hidden* schová dimenzi, ale ta bude stále vyuĹľita pĹ™i vĂ˝poÄŤtech ostatnĂch. + +### **PĹ™Ăklad** +Grafy teploty majĂ jen jednu dimenzi, graf vlhkosti má dimenze dvÄ›. +``` +DIMENSION temperature_outside Teplota absolute 1 100 +DIMENSION temperature_inside Teplota absolute 1 100 +DIMENSION humidity_SHT15 SHT15 absolute 1 100 +DIMENSION humidity_SHT25 SHT25 absolute 1 100 +``` + +## OdesĂlánĂ dat +Pro odesĂlánĂ naměřenĂ˝ch dat sloužà trojice zpráv *BEGIN*, *SET* a *END*. + +Začátek dat oznaÄŤuje *BEGIN* s formátem: +``` +BEGIN type.id [microseconds] +``` + +**type.id**<br> +Udává, do kterĂ©ho grafu patřà odesĂlaná data. + +**microseconds**<br> +Udává poÄŤet mikrosekund, kterĂ˝ uplynul od poslednĂ aktualizace grafu. Je to nepovinná hodnota, která zpĹ™esnĂ vykreslenĂ dat, pokud by na velmi vytĂĹľenĂ©m systĂ©mu docházelo ke zpomalovánĂ pĹ™enosu dat. + +Jednotlivá data jsou uvozena zprávou *SET* s formátem: +``` +SET id = value +``` + +**id**<br> +ID dimenze, do kterĂ© patřà data, která udává value. Netdata pĹ™ijĂmajĂ jen celá ÄŤĂsla a pokud se majĂ zobrazovat desetinná, tak je potĹ™eba data pĹ™ed odeslánĂm vynásobit a nastavit **divisor** na odpovĂdajĂcĂ hodnotu. + +Konec dat je singnalizován zprávou *END*, která nemá žádnĂ© parametry. + +### **PĹ™Ăklad** +OdeslánĂ naměřenĂ˝ch teplot a vlhkostĂ. +``` +BEGIN Meteostanice.temperature_outside +SET temperature_outside = 2055 +END + +BEGIN Meteostanice.temperature_inside +SET temperature_inside = 2178 +END + +BEGIN Meteostanice.humidity +SET humidity_SHT15 = 8012 +SET humidity_SHT25 = 7982 +END +``` + +## ShrnutĂ +Pro nastavenĂ grafĹŻ meteostanice a následnĂ© odesĂlánĂ dat sloužà následujĂcĂ pĹ™Ăkazy, v danĂ©m poĹ™adĂ, kterĂ© náš plugin vypisuje na `stdout`. +``` +#Inicializace grafĹŻ +CHART Meteostanice.temperature_outside 'Venkovni teplota' '°C' teploty '' line 1000 1 +DIMENSION temperature_outside Teplota absolute 1 100 + +CHART Meteostanice.temperature_inside 'Vnitrni teplota' '°C' teploty '' line 1001 1 +DIMENSION temperature_inside Teplota absolute 1 100 + +CHART Meteostanice.humidity 'Vlhkost' '%' vlhkosti '' line 1002 1 +DIMENSION humidity_SHT15 SHT15 absolute 1 100 +DIMENSION humidity_SHT25 SHT25 absolute 1 100 + +#OdesĂlánĂ dat +BEGIN Meteostanice.temperature_outside +SET temperature_outside = 2055 +END + +BEGIN Meteostanice.temperature_inside +SET temperature_inside = 2178 +END + +BEGIN Meteostanice.humidity +SET humidity_SHT15 = 8012 +SET humidity_SHT25 = 7982 +END +``` + +VĂ˝ledek bude vypadat takto: + + + +# DebugovánĂ +Pro debugovánĂ pluginu ho staÄŤĂ pouze spustit a jelikoĹľ vypisuje na standardnĂ vĂ˝stup, tak je kontrola velmi snadná. + +Pro kontrolu, Ĺľe plugin běžà správnÄ›, kdyĹľ je spuštÄ›n pĹ™es netdata, lze pouĹľĂt následujĂcĂ postup: +```bash +#ZĂskánĂ PID procesu, pod kterĂ˝m plugin běžà +ps ax | grep muj.plugin + +10537 ? R 0:27 /usr/libexec/netdata/plugins.d/muj.plugin 2 + +#PĹ™ipojenĂ se na stdout tohoto procesoru +sudo strace -p10537 -s9999 -e write +``` + +# C++ problĂ©m s std::cout +KdyĹľ jsem programval svĹŻj plugin, tak jsem narazil na problĂ©m, kdy se v grafech odesĂlanĂ© hodnoty chvĂly zobrazovaly a chvĂli se naopak nezobrazovaly, ale pĹ™i testovánĂ mi plugin korektnÄ› kaĹľdou 1s vypisoval odesĂlánĂ dat. ProblĂ©m jsem vyĹ™ešil potĂ©, co jsem se podĂval na vĂ˝stup pluginu, kdyĹľ byl spuštÄ›n pĹ™es netdata. Zde jsem vidÄ›l, Ĺľe se data neodesĂlajĂ kaĹľdou vteĹ™inu, ale odeslalo se jich naráz nÄ›kolik za nÄ›kolik sekund. ProblĂ©m byl v tom, Ĺľe data vypisuji následovnÄ›: +```c++ +cout << "BEGIN Stojan.temperatures" << '\n'; +cout << "SET RPi = " << temperatures.RPi*100 << '\n'; +cout << "SET Interface = " << temperatures.interface*100 << '\n'; +cout << "END" << '\n'; +``` +A vĂ˝stup na `cout` se provádĂ z bufferu a nenĂ zaruÄŤeno, Ĺľe se vĂ˝pis provede hned. Jedno Ĺ™ešenĂ je mĂsto `\n` pouĹľĂvat `std::endl`, kterĂ˝ pošle znak novĂ©ho řádku a vyprázdnĂ buffer. NevĂ˝hodou tohoto Ĺ™ešenĂ je, Ĺľe vyprazdĹovánĂ bufferu zpomaluje program. Druhou moĹľnostĂ, kterou jsem vyuĹľil, je zavolánĂ `std::cout << std::flush;` na konci odesĂlánĂ dat, ÄŤĂmĹľ dojde k vyprázdnÄ›nĂ bufferu a okamĹľitĂ©mu vĂ˝pisu dat na obrazovku. + +# Dejte nám vÄ›dÄ›t! +Naprogramovali jste si vlastnĂ plugin pro netdata? Pochlubte se na na našem [fĂłrum](http://forum.ok1kvk.cz/).