Difference between revisions of "Metrics and Monitoring in swarm"
(→Bevezető) |
(→Mi az a metrika) |
||
Line 29: | Line 29: | ||
Mi innentől kezdve csak a Prometheus-ra fogunk fókuszálni. | Mi innentől kezdve csak a Prometheus-ra fogunk fókuszálni. | ||
+ | |||
+ | =Metrika a Prometheus-ban= | ||
+ | ==Címkék, plusz dimenziók== | ||
+ | A Prometheus szabványú metrikában további dimenziókat lehet bevezetni minden metrikához úgynevezett metrika címkékkel, amiket a metrikát szolgáltató rendszer (pl egy apache) hozzáfűz a metrika nevéhez. A címkék tehát tovább specializálnak egy metrikát, pl egy http proxy a ''proxy_http_request_total'' nevű metrikával mondhatja meg, hogy a lekérdezési időpontjáig hány kérés érkezett a proxy-hoz. De ezt tovább specializálhatja címkék bevezetésével. Az alábbi példában a '''method''' és a '''status''' címéket használta a proxy a ''proxy_http_request_total'' metrika finomításához. Az alábbi példában tehát a metrika értéke nem az összes request-re vonatkozik, csak azokra amiket GET-el kértek le, és amiknek 200-as volt a státusza. | ||
+ | proxy_http_request_total{method="GET", status="200"} 13 | ||
+ | |||
+ | |||
+ | A valóságban ez úgy nézne ki a metrikát szolgáltató rendszer által gyárott metrika listában, hogy sorba jönne az összes variáció egymás után, pl: | ||
+ | <pre> | ||
+ | ... | ||
+ | proxy_http_request_total{method="GET", status="200"} 13 | ||
+ | proxy_http_request_total{method="GET", status="500"} 12 | ||
+ | proxy_http_request_total{method="POST", status="200"} 30 | ||
+ | proxy_http_request_total{method="POST", status="300"} 20 | ||
+ | ... | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Fontos, hogy a címkének is a metrikát szolgáltató rendszer ad jelentést, a time-series adatbázis kezelő számra (a mi esetünkben Prometheus) a metrika és a benne lévő címkék is csak név érték párok. Azonban a címke és annak az értéke is részei a metrika nevének. Tehát a metrikát az összes címéjével együtt felfoghatjuk egy string-nek, aminek van egy értéke. A time-series adatbázisokban a címkék segítségével nagyon trükkös lekérdezéseket lehet felírni, amiket a time-series adatbázis nagyon hatékonyan meg tud keresni. | ||
+ | |||
+ | |||
+ | ==Honnan jön a metrika== | ||
+ | Metrikát magáról nagyon sok rendszer tud szolgáltatni, pl a ''Traefik'' reverse proxy, vagy ahogy azt majd látni fogjuk, akár a docker daemon is képes metrikákat szolgáltatni saját magáról. Általában a metrika lekérdezésére egy http interfészt biztosít a metrikát adó rendszer, amit a '''/metrics''' URL-en lehet elérni. A http interfészek esetében PULL metrika begyűjtésről beszélünk, vagyis a Prometheus (vagy bármelyik másik TSDB) a konfigurációja alapján periodikusan (pár másodpercenként) meghívja a megfelelő URL-t, ahol visszakapja az aktuális metrika listát (név-érték párokat), amit beír az adatbázisba. | ||
+ | Léteik PUSH alapú metrika gyújtés is. | ||
+ | |||
+ | |||
+ | A Prometheus 4 nyelven is ad API-t metrika szolgáltatás írására: '''Go, Java, Python, Ruby'''. | ||
+ | <br>https://prometheus.io/docs/instrumenting/clientlibs/ | ||
+ | |||
+ | Tehát továbbra sem a Prometheus szolgáltatja metrikát, a Prometheus csak összegyűjti azt, de a kezünkbe ad egy API-t, amivel a saját rendszerünkbe nagyon könnyen építhetünk metrika szolgáltató interfészt. | ||
+ | |||
+ | |||
+ | Java-ban nagyon egyszerűen szolgáltathatunk metrikákat az alkalmazásunkból a Prometheus client library-val. Van hozzá Maven dependency. Abba az osztályba, ami a dependenciát szolgáltatja, majd egy statikus konstruktorral inicializáljuk a Prometheus metrika gyűjtőt. Az alábbi példában inicializálnunk egy '''my_library_request_total''' metrikát, ami fölé a http metrika lekérdezésben egy #-val oda lesz írva a help szöveg: "Total request" (ezt nem veszi figyelembe a prometheus). A metrikához hozzáadtunk a '''method''' nevű címét. | ||
+ | <source lang="java"> | ||
+ | class YourClass { | ||
+ | static final Counter requests = Counter.build() | ||
+ | .name("my_library_requests_total").help("Total requests.") | ||
+ | .labelNames("method").register(); | ||
+ | |||
+ | void processGetRequest() { | ||
+ | requests.labels("get").inc(); | ||
+ | // Your code here. | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | Ahányszor meghívjuk a '''processGetRequest()''' metódust, a fenti '''method="get"''' megcímkézett változatához hozzá fog adni egyet. | ||
+ | |||
+ | |||
+ | A lekérdezésben így nézne ki: | ||
+ | <pre> | ||
+ | #Total requests. | ||
+ | my_library_requests_total{method="get"} 23 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | Aztán meg pl egy HTTP servlet-el tudjuk szolgáltatni a metrikát: | ||
+ | <source lang="java"> | ||
+ | Server server = new Server(1234); | ||
+ | ServletContextHandler context = new ServletContextHandler(); | ||
+ | context.setContextPath("/"); | ||
+ | server.setHandler(context); | ||
+ | |||
+ | context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics"); | ||
+ | </source> | ||
+ | |||
+ | ==Metrika típusok== | ||
+ | A Prometheus 4 féle metrika típust definál, de ezek csak az API szinten vannak megkülönböztetve, a Prometheus-ban már nincsenek, ott nekünk kell tudni, hogy értelmes e amit felírunk szabály az adott metrikára. (https://prometheus.io/docs/concepts/metric_types/) | ||
+ | |||
+ | |||
+ | ===Gauge''' (mérő)=== | ||
+ | A Gauge a legegyszerűbb metrika a Prometheus-ban, ez egy egyszerű mérőszám, aminek fel és le is mehet az értéke, pl memória használat. | ||
+ | |||
+ | |||
+ | ===Counter=== | ||
+ | A számláló a második legegyszerűbb metrika fajta. A számlálónak csak nőhet az értéke, vagy reset-kor visszavált 0-ra. Persze ennek betartását a Prometheus nem ellenőrzi, számára ugyan olyan név-érték pár a számláló típusú metrika is mint bármelyik másik. Ha a hivatalos Java API-t használjuk az alkalmazásunkban, akkor ez az API biztosítja ennek a betartását. Pl: | ||
+ | <pre> | ||
+ | # TYPE builder_builds_failed_total counter | ||
+ | builder_builds_failed_total{reason="build_canceled"} 0 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | ===Histogram=== | ||
+ | http://linuxczar.net/blog/2017/06/15/prometheus-histogram-2/<br> | ||
+ | https://statistics.laerd.com/statistical-guides/understanding-histograms.php<br> | ||
+ | http://www.leanforum.hu/index.php/szocikkek/167-hisztogram-2<br> | ||
+ | distribution=eloszlás<br> | ||
+ | latency=eltelt idő az input és az output között bármilyen rendszerben <br> | ||
+ | |||
+ | |||
+ | '''Elsőként nézzük meg mi az a metrika:'''<br> | ||
+ | A Hisztogram a gyakoriság eloszlást mutatja meg a mintának, amivel sokszor sokkal többre lehet menni, mint a hagyományos pl érték-idő diagramokból. A hisztogram egy minta elemzését segítő egyszerű statisztikai eszköz, amely a gyűjtött adatok (minta) alapján következtetések levonására ad lehetőséget. A hisztogram tulajdonképpen egy oszlopdiagram, amely X-tengelyén a tulajdonság osztályok (egy változó különböző értékei), Y-tengelyén pedig az előfordulási gyakoriságok találhatók. A hisztogram megmutatja az eloszlás alakját, középértékét és terjedelmét. | ||
+ | |||
+ | Nézzünk egy példát, hogy hogyan készül a hisztogram. Ha van egy mintám, amiben emberek korai vannak benne: | ||
+ | <pre> | ||
+ | 36 25 38 46 55 68 72 55 36 38 | ||
+ | 67 45 22 48 91 46 52 61 58 55 | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | '''Summary:'''<br> | ||
+ | |||
+ | |||
+ | Egy részletes leírás a Historam-ról és Summary-ről itt: https://prometheus.io/docs/practices/histograms/ | ||
+ | |||
+ | |||
+ | - Histogram : időegységenként összegzet értéke pl request kiszolgáltási idők: | ||
+ | etcd_disk_wal_fsync_duration_seconds_bucket{le="0.001"} 1 | ||
+ | etcd_disk_wal_fsync_duration_seconds_bucket{le="0.002"} 1331 | ||
+ | etcd_disk_wal_fsync_duration_seconds_bucket{le="0.004"} 1767 | ||
+ | etcd_disk_wal_fsync_duration_seconds_bucket{le="0.008"} 1803 | ||
+ | etcd_disk_wal_fsync_duration_seconds_bucket{le="0.016"} 1878 | ||
+ | |||
+ | itt ez a base neve a metrikának: etcd_disk_wal_fsync_duration_seconds ehhez jön hozzá a _bucket név, jelezve, hogy ez histogram, majd a címke mindig le=<összegzett idő> | ||
+ | |||
+ | ehhez mindig tartok egy <base_nave>_sum és egy <base_nev>_count nevű metrkia is, | ||
+ | - sum: az eddigi összes megfigyelés értéke, amióta a rendszer elindult | ||
+ | - count: az eddig összes megfigyelés darabszáma (vagyis az összes ugyan olyan _bucket-es sorok száma, amitóa a rendszer elindult) | ||
+ | |||
+ | - Summary: A címke neve mindig "quantile", és a base név után nincs semmi. | ||
+ | |||
+ | <basename>{quantile="<φ>"} | ||
+ | |||
+ | go_gc_duration_seconds{quantile="0"} 2.2683e-05 | ||
+ | go_gc_duration_seconds{quantile="0.25"} 2.784e-05 | ||
+ | go_gc_duration_seconds{quantile="0.5"} 3.3507e-05 | ||
+ | |||
+ | |||
+ | |||
+ | A job-okra és intanciákra vannak beépített metrikák, amiekt a prometheus magától gyárt le: https://prometheus.io/docs/concepts/jobs_instances/ | ||
+ | |||
+ | up{job="<job-name>", instance="<instance-id>"}: 1 if the instance is healthy, i.e. reachable, or 0 if the scrape failed. | ||
+ | scrape_duration_seconds{job="<job-name>", instance="<instance-id>"}: duration of the scrape. | ||
+ | scrape_samples_post_metric_relabeling{job="<job-name>", instance="<instance-id>"}: the number of samples remaining after metric relabeling was applied. | ||
+ | scrape_samples_scraped{job="<job-name>", instance="<instance-id>"}: the number of samples the target exposed. | ||
+ | |||
+ | tehát az up+ job név label-t nem a intance küldi magáról, hanem a prométheus gyártja le az alapján hogy mikor elérhető vagy mikor nem az instancia. | ||
+ | |||
+ | ===Prometheus architektúra=== | ||
=Metrika a Prometheus-ban= | =Metrika a Prometheus-ban= |
Revision as of 21:18, 12 August 2018
Contents
Mi az a metrika
A metrika egy fajta speciális loggolás, amit a metrikát szolgáltató rendszer nem egy log fájlba ír, hanem biztosít egy HTTP API-t, amin keresztül a metrikát feldolgozó szolgáltatás le tudja azt periodikusan kérdezni. A metrika név-érték párok listája, aminek a jelentése bármi lehet ami időben változik. A metrika listában minden egyes metrika jelentését a metrikát szolgáltató rendszernek kell definiálnia. Pl egy node-on lévő elérhető maradék memóriát jelképezheti a következő metrika:
node_memory_MemAvailable 210
A metrika értéke lehet szám, string vagy logikai érték is.
A metrikákat minden rendszerben, szervezetben vagy swarm cluster-ben egy központi egység kérdezi le és gyűjti össze a saját adatbázisában. A metrikát összegyűjtő rendszerben aztán lekérdezéseket írhatunk fel a metrikákra, aminek az eredménye alapján aztán automatizált folyamatokat indíthatunk be, mint pl a swarm cluster méretének megváltoztatása, alert küldése sms-ben, emailben. Tehát a metrikák a hagyományos log fájlokkal ellentétben a baj valós idejű detektálására, vagy sokkal inkább a baj elkerülésére szolgálnak. Ebből kifolyólag a logokkal ellentétben a metrikák élettartalma nagyon rövid, tipikusan olyan lekérdezéseket szoktunk írni, ahol a lekérdezett metrikák kora nem több mint 10 perc, de inkább pár perc, hiszen itt mindig valaminek az időben történő változására vagyunk kíváncsiak. Így nem olyan kritikus a metrikák elvesztése mint a hagyományos log fájloké, amik tipikusan offline elemzésre szolgálnak, ha a baj már bekövetkezett.
A metrikákat úgynevezett time-series (idősor) adatbázisban kell letárolni (TSDB), vagyis egy adott metrikához nyilván van tartva minden lekérdezéshez az akkor kapott érték. Ez a speciális struktúra ugyan letárolható lenne hagyományos adatbázis kezelőkben is, de nagyon nem lenne hatékony a bennük való keresés. Léteznek direkt erre a speciális adatmodellre készült adatbáziskezelők, amik rettentő hatékonyan tudnak keresni a time-series adatokban. Egy adott metrika tárolását egy listaként lehet elképzelni, ahol a lista elemek az időbélyegekkel vannak indexelve, és a listaelem tárolja az adott időpillanathoz (amikor a lekérdezés történt) a metrika értékét. A főbb time-series db-k:
- InfluxDB:
- Prometheus
- Graphite
- OpenTSDB
- KairosDB
...
Fontos, hogy a time-series db számára a metrika csak egy név-érték pár (egy string amihez tartozik egy érték), tehát a TSDB nem értelmezi a kapott metrikát, a lekérdezéseket úgy kell megírni, hogy legyen értelme a háttérrendszerre vonatkozóan. Tehát mikor megtervezzük a lekérdezéseinket a TSDB-ben, akkor elsőként a metrikát szolgáltató rendszer specifikációját kell megnézni, hogy az milyen metrikákat szolgáltat magáról, és melyiknek pontosan mi a jelentése.
A time-series adatbáziskezelő (TSDB) folyamatosan gyűjti a különböző komponensek metrikáit, és minden egyes begyűjtés után ki fogja értékelni a különböző metrikákra felírt lekérdezéseket, amik általában abból állnak, hogy egy time-series lekérdezés eredményét összeveti egy értékkel vagy logika változóval, és a végeredmény vagy igaz vagy hamis. Ha a végeredmény igaz, akkor a time-series adatbáziskezelő riasztást fog generálni (beindít egy automatizált folyamatot), ha a kiértékelés hamis, akkor meg nem fog semmit csinálni. A riasztás hatására küldhetünk emial-t, végrehajthatunk egy bash script-et... stb.
TSDB használatával lehet a swarm cluster egészségét automatizált módon monitorozni vagy akár dinamikusan változtatni a worker node-ok mennyiségét. Pl felírhatunk különböző szabályokat a node-ok leterheltségére. Ha a node-ok valamilyen metrika mentén túlságosan leterheltek, akkor újabb node-okat állítunk automatikusan üzembe, ha meg a terhelés túl alacsony ugyan ezen metrika alapján, akkor meg bizonyos node-okat megszüntetünk.
Mi innentől kezdve csak a Prometheus-ra fogunk fókuszálni.
Metrika a Prometheus-ban
Címkék, plusz dimenziók
A Prometheus szabványú metrikában további dimenziókat lehet bevezetni minden metrikához úgynevezett metrika címkékkel, amiket a metrikát szolgáltató rendszer (pl egy apache) hozzáfűz a metrika nevéhez. A címkék tehát tovább specializálnak egy metrikát, pl egy http proxy a proxy_http_request_total nevű metrikával mondhatja meg, hogy a lekérdezési időpontjáig hány kérés érkezett a proxy-hoz. De ezt tovább specializálhatja címkék bevezetésével. Az alábbi példában a method és a status címéket használta a proxy a proxy_http_request_total metrika finomításához. Az alábbi példában tehát a metrika értéke nem az összes request-re vonatkozik, csak azokra amiket GET-el kértek le, és amiknek 200-as volt a státusza.
proxy_http_request_total{method="GET", status="200"} 13
A valóságban ez úgy nézne ki a metrikát szolgáltató rendszer által gyárott metrika listában, hogy sorba jönne az összes variáció egymás után, pl:
... proxy_http_request_total{method="GET", status="200"} 13 proxy_http_request_total{method="GET", status="500"} 12 proxy_http_request_total{method="POST", status="200"} 30 proxy_http_request_total{method="POST", status="300"} 20 ...
Fontos, hogy a címkének is a metrikát szolgáltató rendszer ad jelentést, a time-series adatbázis kezelő számra (a mi esetünkben Prometheus) a metrika és a benne lévő címkék is csak név érték párok. Azonban a címke és annak az értéke is részei a metrika nevének. Tehát a metrikát az összes címéjével együtt felfoghatjuk egy string-nek, aminek van egy értéke. A time-series adatbázisokban a címkék segítségével nagyon trükkös lekérdezéseket lehet felírni, amiket a time-series adatbázis nagyon hatékonyan meg tud keresni.
Honnan jön a metrika
Metrikát magáról nagyon sok rendszer tud szolgáltatni, pl a Traefik reverse proxy, vagy ahogy azt majd látni fogjuk, akár a docker daemon is képes metrikákat szolgáltatni saját magáról. Általában a metrika lekérdezésére egy http interfészt biztosít a metrikát adó rendszer, amit a /metrics URL-en lehet elérni. A http interfészek esetében PULL metrika begyűjtésről beszélünk, vagyis a Prometheus (vagy bármelyik másik TSDB) a konfigurációja alapján periodikusan (pár másodpercenként) meghívja a megfelelő URL-t, ahol visszakapja az aktuális metrika listát (név-érték párokat), amit beír az adatbázisba. Léteik PUSH alapú metrika gyújtés is.
A Prometheus 4 nyelven is ad API-t metrika szolgáltatás írására: Go, Java, Python, Ruby.
https://prometheus.io/docs/instrumenting/clientlibs/
Tehát továbbra sem a Prometheus szolgáltatja metrikát, a Prometheus csak összegyűjti azt, de a kezünkbe ad egy API-t, amivel a saját rendszerünkbe nagyon könnyen építhetünk metrika szolgáltató interfészt.
Java-ban nagyon egyszerűen szolgáltathatunk metrikákat az alkalmazásunkból a Prometheus client library-val. Van hozzá Maven dependency. Abba az osztályba, ami a dependenciát szolgáltatja, majd egy statikus konstruktorral inicializáljuk a Prometheus metrika gyűjtőt. Az alábbi példában inicializálnunk egy my_library_request_total metrikát, ami fölé a http metrika lekérdezésben egy #-val oda lesz írva a help szöveg: "Total request" (ezt nem veszi figyelembe a prometheus). A metrikához hozzáadtunk a method nevű címét.
class YourClass {
static final Counter requests = Counter.build()
.name("my_library_requests_total").help("Total requests.")
.labelNames("method").register();
void processGetRequest() {
requests.labels("get").inc();
// Your code here.
}
}
Ahányszor meghívjuk a processGetRequest() metódust, a fenti method="get" megcímkézett változatához hozzá fog adni egyet.
A lekérdezésben így nézne ki:
#Total requests. my_library_requests_total{method="get"} 23
Aztán meg pl egy HTTP servlet-el tudjuk szolgáltatni a metrikát:
Server server = new Server(1234);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
server.setHandler(context);
context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics");
Metrika típusok
A Prometheus 4 féle metrika típust definál, de ezek csak az API szinten vannak megkülönböztetve, a Prometheus-ban már nincsenek, ott nekünk kell tudni, hogy értelmes e amit felírunk szabály az adott metrikára. (https://prometheus.io/docs/concepts/metric_types/)
Gauge (mérő)
A Gauge a legegyszerűbb metrika a Prometheus-ban, ez egy egyszerű mérőszám, aminek fel és le is mehet az értéke, pl memória használat.
Counter
A számláló a második legegyszerűbb metrika fajta. A számlálónak csak nőhet az értéke, vagy reset-kor visszavált 0-ra. Persze ennek betartását a Prometheus nem ellenőrzi, számára ugyan olyan név-érték pár a számláló típusú metrika is mint bármelyik másik. Ha a hivatalos Java API-t használjuk az alkalmazásunkban, akkor ez az API biztosítja ennek a betartását. Pl:
# TYPE builder_builds_failed_total counter builder_builds_failed_total{reason="build_canceled"} 0
Histogram
http://linuxczar.net/blog/2017/06/15/prometheus-histogram-2/
https://statistics.laerd.com/statistical-guides/understanding-histograms.php
http://www.leanforum.hu/index.php/szocikkek/167-hisztogram-2
distribution=eloszlás
latency=eltelt idő az input és az output között bármilyen rendszerben
Elsőként nézzük meg mi az a metrika:
A Hisztogram a gyakoriság eloszlást mutatja meg a mintának, amivel sokszor sokkal többre lehet menni, mint a hagyományos pl érték-idő diagramokból. A hisztogram egy minta elemzését segítő egyszerű statisztikai eszköz, amely a gyűjtött adatok (minta) alapján következtetések levonására ad lehetőséget. A hisztogram tulajdonképpen egy oszlopdiagram, amely X-tengelyén a tulajdonság osztályok (egy változó különböző értékei), Y-tengelyén pedig az előfordulási gyakoriságok találhatók. A hisztogram megmutatja az eloszlás alakját, középértékét és terjedelmét.
Nézzünk egy példát, hogy hogyan készül a hisztogram. Ha van egy mintám, amiben emberek korai vannak benne:
36 25 38 46 55 68 72 55 36 38 67 45 22 48 91 46 52 61 58 55
Summary:
Egy részletes leírás a Historam-ról és Summary-ről itt: https://prometheus.io/docs/practices/histograms/
- Histogram : időegységenként összegzet értéke pl request kiszolgáltási idők:
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.001"} 1
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.002"} 1331
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.004"} 1767
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.008"} 1803
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.016"} 1878
itt ez a base neve a metrikának: etcd_disk_wal_fsync_duration_seconds ehhez jön hozzá a _bucket név, jelezve, hogy ez histogram, majd a címke mindig le=<összegzett idő>
ehhez mindig tartok egy <base_nave>_sum és egy <base_nev>_count nevű metrkia is, - sum: az eddigi összes megfigyelés értéke, amióta a rendszer elindult - count: az eddig összes megfigyelés darabszáma (vagyis az összes ugyan olyan _bucket-es sorok száma, amitóa a rendszer elindult)
- Summary: A címke neve mindig "quantile", és a base név után nincs semmi.
<basename>{quantile="<φ>"}
go_gc_duration_seconds{quantile="0"} 2.2683e-05 go_gc_duration_seconds{quantile="0.25"} 2.784e-05 go_gc_duration_seconds{quantile="0.5"} 3.3507e-05
A job-okra és intanciákra vannak beépített metrikák, amiekt a prometheus magától gyárt le: https://prometheus.io/docs/concepts/jobs_instances/
up{job="<job-name>", instance="<instance-id>"}: 1 if the instance is healthy, i.e. reachable, or 0 if the scrape failed. scrape_duration_seconds{job="<job-name>", instance="<instance-id>"}: duration of the scrape. scrape_samples_post_metric_relabeling{job="<job-name>", instance="<instance-id>"}: the number of samples remaining after metric relabeling was applied. scrape_samples_scraped{job="<job-name>", instance="<instance-id>"}: the number of samples the target exposed.
tehát az up+ job név label-t nem a intance küldi magáról, hanem a prométheus gyártja le az alapján hogy mikor elérhető vagy mikor nem az instancia.
Prometheus architektúra
Metrika a Prometheus-ban
Címkék, plusz dimenziók
A Prometheus szabványú metrikában további dimenziókat lehet bevezetni minden metrikához úgynevezett metrika címkékkel, amiket a metrikát szolgáltató rendszer (pl egy apache) hozzáfűz a metrika nevéhez. A címkék tehát tovább specializálnak egy metrikát, pl egy http proxy a proxy_http_request_total nevű metrikával mondhatja meg, hogy a lekérdezési időpontjáig hány kérés érkezett a proxy-hoz. De ezt tovább specializálhatja címkék bevezetésével. Az alábbi példában a method és a status címéket használta a proxy a proxy_http_request_total metrika finomításához. Az alábbi példában tehát a metrika értéke nem az összes request-re vonatkozik, csak azokra amiket GET-el kértek le, és amiknek 200-as volt a státusza.
proxy_http_request_total{method="GET", status="200"} 13
A valóságban ez úgy nézne ki a metrikát szolgáltató rendszer által gyárott metrika listában, hogy sorba jönne az összes variáció egymás után, pl:
... proxy_http_request_total{method="GET", status="200"} 13 proxy_http_request_total{method="GET", status="500"} 12 proxy_http_request_total{method="POST", status="200"} 30 proxy_http_request_total{method="POST", status="300"} 20 ...
Fontos, hogy a címkének is a metrikát szolgáltató rendszer ad jelentést, a time-series adatbázis kezelő számra (a mi esetünkben Prometheus) a metrika és a benne lévő címkék is csak név érték párok. Azonban a címke és annak az értéke is részei a metrika nevének. Tehát a metrikát az összes címéjével együtt felfoghatjuk egy string-nek, aminek van egy értéke. A time-series adatbázisokban a címkék segítségével nagyon trükkös lekérdezéseket lehet felírni, amiket a time-series adatbázis nagyon hatékonyan meg tud keresni.
Honnan jön a metrika
Metrikát magáról nagyon sok rendszer tud szolgáltatni, pl a Traefik reverse proxy, vagy ahogy azt majd látni fogjuk, akár a docker daemon is képes metrikákat szolgáltatni saját magáról. Általában a metrika lekérdezésére egy http interfészt biztosít a metrikát adó rendszer, amit a /metrics URL-en lehet elérni. A http interfészek esetében PULL metrika begyűjtésről beszélünk, vagyis a Prometheus (vagy bármelyik másik TSDB) a konfigurációja alapján periodikusan (pár másodpercenként) meghívja a megfelelő URL-t, ahol visszakapja az aktuális metrika listát (név-érték párokat), amit beír az adatbázisba. Léteik PUSH alapú metrika gyújtés is.
A Prometheus 4 nyelven is ad API-t metrika szolgáltatás írására: Go, Java, Python, Ruby.
https://prometheus.io/docs/instrumenting/clientlibs/
Tehát továbbra sem a Prometheus szolgáltatja metrikát, a Prometheus csak összegyűjti azt, de a kezünkbe ad egy API-t, amivel a saját rendszerünkbe nagyon könnyen építhetünk metrika szolgáltató interfészt.
Java-ban nagyon egyszerűen szolgáltathatunk metrikákat az alkalmazásunkból a Prometheus client library-val. Van hozzá Maven dependency. Abba az osztályba, ami a dependenciát szolgáltatja, majd egy statikus konstruktorral inicializáljuk a Prometheus metrika gyűjtőt. Az alábbi példában inicializálnunk egy my_library_request_total metrikát, ami fölé a http metrika lekérdezésben egy #-val oda lesz írva a help szöveg: "Total request" (ezt nem veszi figyelembe a prometheus). A metrikához hozzáadtunk a method nevű címét.
class YourClass {
static final Counter requests = Counter.build()
.name("my_library_requests_total").help("Total requests.")
.labelNames("method").register();
void processGetRequest() {
requests.labels("get").inc();
// Your code here.
}
}
Ahányszor meghívjuk a processGetRequest() metódust, a fenti method="get" megcímkézett változatához hozzá fog adni egyet.
A lekérdezésben így nézne ki:
#Total requests. my_library_requests_total{method="get"} 23
Aztán meg pl egy HTTP servlet-el tudjuk szolgáltatni a metrikát:
Server server = new Server(1234);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
server.setHandler(context);
context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics");
Metrika típusok
A Prometheus 4 féle metrika típust definál, de ezek csak az API szinten vannak megkülönböztetve, a Prometheus-ban már nincsenek, ott nekünk kell tudni, hogy értelmes e amit felírunk szabály az adott metrikára. (https://prometheus.io/docs/concepts/metric_types/)
Gauge (mérő)
A Gauge a legegyszerűbb metrika a Prometheus-ban, ez egy egyszerű mérőszám, aminek fel és le is mehet az értéke, pl memória használat.
Counter
A számláló a második legegyszerűbb metrika fajta. A számlálónak csak nőhet az értéke, vagy reset-kor visszavált 0-ra. Persze ennek betartását a Prometheus nem ellenőrzi, számára ugyan olyan név-érték pár a számláló típusú metrika is mint bármelyik másik. Ha a hivatalos Java API-t használjuk az alkalmazásunkban, akkor ez az API biztosítja ennek a betartását. Pl:
# TYPE builder_builds_failed_total counter builder_builds_failed_total{reason="build_canceled"} 0
Histogram
http://linuxczar.net/blog/2017/06/15/prometheus-histogram-2/
https://statistics.laerd.com/statistical-guides/understanding-histograms.php
http://www.leanforum.hu/index.php/szocikkek/167-hisztogram-2
distribution=eloszlás
latency=eltelt idő az input és az output között bármilyen rendszerben
Elsőként nézzük meg mi az a metrika:
A Hisztogram a gyakoriság eloszlást mutatja meg a mintának, amivel sokszor sokkal többre lehet menni, mint a hagyományos pl érték-idő diagramokból. A hisztogram egy minta elemzését segítő egyszerű statisztikai eszköz, amely a gyűjtött adatok (minta) alapján következtetések levonására ad lehetőséget. A hisztogram tulajdonképpen egy oszlopdiagram, amely X-tengelyén a tulajdonság osztályok (egy változó különböző értékei), Y-tengelyén pedig az előfordulási gyakoriságok találhatók. A hisztogram megmutatja az eloszlás alakját, középértékét és terjedelmét.
Nézzünk egy példát, hogy hogyan készül a hisztogram. Ha van egy mintám, amiben emberek korai vannak benne:
36 25 38 46 55 68 72 55 36 38 67 45 22 48 91 46 52 61 58 55
Summary:
Egy részletes leírás a Historam-ról és Summary-ről itt: https://prometheus.io/docs/practices/histograms/
- Histogram : időegységenként összegzet értéke pl request kiszolgáltási idők:
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.001"} 1
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.002"} 1331
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.004"} 1767
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.008"} 1803
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.016"} 1878
itt ez a base neve a metrikának: etcd_disk_wal_fsync_duration_seconds ehhez jön hozzá a _bucket név, jelezve, hogy ez histogram, majd a címke mindig le=<összegzett idő>
ehhez mindig tartok egy <base_nave>_sum és egy <base_nev>_count nevű metrkia is, - sum: az eddigi összes megfigyelés értéke, amióta a rendszer elindult - count: az eddig összes megfigyelés darabszáma (vagyis az összes ugyan olyan _bucket-es sorok száma, amitóa a rendszer elindult)
- Summary: A címke neve mindig "quantile", és a base név után nincs semmi.
<basename>{quantile="<φ>"}
go_gc_duration_seconds{quantile="0"} 2.2683e-05 go_gc_duration_seconds{quantile="0.25"} 2.784e-05 go_gc_duration_seconds{quantile="0.5"} 3.3507e-05
A job-okra és intanciákra vannak beépített metrikák, amiekt a prometheus magától gyárt le: https://prometheus.io/docs/concepts/jobs_instances/
up{job="<job-name>", instance="<instance-id>"}: 1 if the instance is healthy, i.e. reachable, or 0 if the scrape failed. scrape_duration_seconds{job="<job-name>", instance="<instance-id>"}: duration of the scrape. scrape_samples_post_metric_relabeling{job="<job-name>", instance="<instance-id>"}: the number of samples remaining after metric relabeling was applied. scrape_samples_scraped{job="<job-name>", instance="<instance-id>"}: the number of samples the target exposed.
tehát az up+ job név label-t nem a intance küldi magáról, hanem a prométheus gyártja le az alapján hogy mikor elérhető vagy mikor nem az instancia.
Prometheus architektúra
Prometheus telepítése
... # HELP builder_builds_failed_total Number of failed image builds # TYPE builder_builds_failed_total counter builder_builds_failed_total{reason="build_canceled"} 0 builder_builds_failed_total{reason="build_target_not_reachable_error"} 0 builder_builds_failed_total{reason="command_not_supported_error"} 0 builder_builds_failed_total{reason="dockerfile_empty_error"} 0 builder_builds_failed_total{reason="dockerfile_syntax_error"} 0
A metrika bármi lehet, egy név=érték pár. Van egy string, aminek van egy értéke. Pl: builder_builds_failed_total{reason="build_canceled"} 0
Hol a builder_builds_failed_total{reason="build_canceled"} a név, és az értéke 0.
Ami a {} között van az a metrika címéje vagy címkéji, ha több is van. A címkéket vesszővel kell elválasztani, ha több is van. A címke finomhangolja a metrika jelentését, úgymond sepcifikálja. Vagy inább egy plusz dimenzió a metrikában. Ezen a metrikán a reason címke van rajta, aminek az értéke "build_cancell". Ez is bármi lehet, szintén név érték párok. Azt hiszem hogy van két beépetett címke: