Skupljanje trupaca iz Lokija

Skupljanje trupaca iz Lokija

U Badoou stalno pratimo nove tehnologije i procjenjujemo isplati li se koristiti u našem sustavu. Željeli bismo podijeliti jednu od ovih studija sa zajednicom. Posvećen je Lokiju, sustavu združivanja dnevnika.

Loki je rješenje za pohranjivanje i pregled logova, a ovaj skup također pruža fleksibilan sustav za njihovu analizu i slanje podataka Prometeju. U svibnju je objavljeno još jedno ažuriranje, koje kreatori aktivno promoviraju. Zanimalo nas je što Loki može, koje mogućnosti pruža i u kojoj mjeri može djelovati kao alternativa ELK-u, stogu koji sada koristimo.

Što je Loki

Grafana Loki je skup komponenti za cjeloviti sustav za rad s trupcima. Za razliku od drugih sličnih sustava, Loki se temelji na ideji indeksiranja samo metapodataka dnevnika – oznaka (isto kao u Prometheusu), te komprimiranja samih logova u zasebne dijelove.

Početna stranica, GitHub

Prije nego što uđemo u ono što možete učiniti s Lokijem, želim pojasniti što mislimo pod "idejom indeksiranja samo metapodataka." Usporedimo Loki pristup i pristup indeksiranju u tradicionalnim rješenjima kao što je Elasticsearch, koristeći primjer retka iz nginx dnevnika:

172.19.0.4 - - [01/Jun/2020:12:05:03 +0000] "GET /purchase?user_id=75146478&item_id=34234 HTTP/1.1" 500 8102 "-" "Stub_Bot/3.0" "0.001"

Tradicionalni sustavi analiziraju cijeli red, uključujući polja s velikim brojem jedinstvenih vrijednosti user_id i item_id, i pohranjuju sve u velikim indeksima. Prednost ovog pristupa je što možete brzo pokrenuti složene upite, budući da su gotovo svi podaci u indeksu. Ali to ima svoju cijenu jer indeks postaje velik, što se prevodi u zahtjeve za memorijom. Kao rezultat toga, indeks dnevnika punog teksta usporediv je po veličini sa samim zapisnicima. Za brzo pretraživanje, indeks mora biti učitan u memoriju. Što je više zapisa, indeks brže raste i zauzima više memorije.

Lokijev pristup zahtijeva da se samo potrebni podaci izvuku iz niza, čiji je broj vrijednosti mali. Na taj način dobivamo mali indeks i možemo pretraživati ​​podatke filtrirajući ih prema vremenu i indeksiranim poljima, a zatim skenirajući ostatak regularnim izrazima ili pretraživanjem podnizova. Proces se ne čini baš najbržim, ali Loki dijeli zahtjev na nekoliko dijelova i izvršava ih paralelno, obrađujući veliku količinu podataka u kratkom vremenu. Broj shardova i paralelnih zahtjeva u njima je konfigurabilan; stoga količina podataka koja se može obraditi po jedinici vremena linearno ovisi o količini osiguranih resursa.

Ovaj kompromis između velikog, brzog indeksa i malog, paralelnog brute-force indeksa omogućuje Lokiju da kontrolira cijenu sustava. Može se fleksibilno konfigurirati i proširivati ​​prema potrebama.

Loki stack se sastoji od tri komponente: Promtail, Loki, Grafana. Promtail prikuplja zapise, obrađuje ih i šalje Lokiju. Loki ih čuva. A Grafana može tražiti podatke od Lokija i prikazati ih. Općenito, Loki se može koristiti ne samo za pohranu zapisa i njihovo pretraživanje. Cijeli skup pruža velike mogućnosti za obradu i analizu dolaznih podataka koristeći Prometheus način.
Možete pronaći opis postupka instalacije здесь.

Pretraživanje dnevnika

Dnevnike možete pretraživati ​​u posebnom Grafana sučelju - Exploreru. Upiti koriste jezik LogQL, koji je vrlo sličan PromQL-u koji se koristi u Prometheusu. U načelu, to se može smatrati distribuiranim grepom.

Sučelje pretraživanja izgleda ovako:

Skupljanje trupaca iz Lokija

Sam zahtjev se sastoji od dva dijela: selektor i filter. Selektor je pretraživanje pomoću indeksiranih metapodataka (oznaka) koji su dodijeljeni zapisnicima, a filtar je niz za pretraživanje ili regularni izraz koji filtrira zapise definirane selektorom. U navedenom primjeru: U vitičastim zagradama nalazi se selektor, sve poslije je filtar.

{image_name="nginx.promtail.test"} |= "index"

Zbog načina na koji Loki radi, ne možete postavljati upite bez selektora, ali oznake mogu biti općenite koliko želite.

Selektor je vrijednost ključ/vrijednost u vitičastim zagradama. Možete kombinirati selektore i odrediti različite uvjete pretraživanja koristeći operatore =, != ili regularne izraze:

{instance=~"kafka-[23]",name!="kafka-dev"} 
// Найдёт логи с лейблом instance, имеющие значение kafka-2, kafka-3, и исключит dev 

Filtar je tekst ili regularni izraz koji će filtrirati sve podatke koje primi selektor.

Moguće je dobiti ad-hoc grafikone na temelju primljenih podataka u metričkom načinu rada. Na primjer, možete saznati koliko se često unos koji sadrži indeks niza pojavljuje u nginx zapisnicima:

Skupljanje trupaca iz Lokija

Potpuni opis mogućnosti možete pronaći u dokumentaciji LogQL.

Raščlanjivanje dnevnika

Postoji nekoliko načina prikupljanja zapisa:

  • Korištenje Promtail-a, standardne komponente steka za prikupljanje zapisa.
  • Izravno iz docker spremnika pomoću Loki Docker upravljački program za bilježenje.
  • Koristite Fluentd ili Fluent Bit, koji mogu slati podatke Lokiju. Za razliku od Promtaila, oni imaju gotove parsere za gotovo sve vrste dnevnika i također mogu rukovati višelinijskim zapisnicima.

Obično se Promtail koristi za raščlanjivanje. Radi tri stvari:

  • Pronalazi izvore podataka.
  • Pričvršćuje im naljepnice.
  • Šalje podatke Lokiju.

Trenutno Promtail može čitati zapise iz lokalnih datoteka i iz systemd dnevnika. Mora biti instaliran na svakom stroju s kojeg se prikupljaju dnevnici.

Postoji integracija s Kubernetesom: Promtail automatski, putem Kubernetes REST API-ja, prepoznaje stanje klastera i prikuplja zapise iz čvora, usluge ili poda, odmah objavljujući oznake na temelju metapodataka iz Kubernetesa (naziv poda, naziv datoteke itd.) .

Također možete objesiti oznake na temelju podataka iz dnevnika pomoću Cjevovoda. Promtail cjevovoda može se sastojati od četiri vrste stupnjeva. Više detalja u službena dokumentacija, odmah ću primijetiti neke nijanse.

  1. Faze raščlanjivanja. Ovo je faza RegEx i JSON. U ovoj fazi ekstrahiramo podatke iz dnevnika u takozvanu ekstrahiranu kartu. Možemo ekstrahirati iz JSON-a jednostavnim kopiranjem polja koja su nam potrebna u ekstrahiranu mapu ili putem regularnih izraza (RegEx), gdje se imenovane grupe "mapiraju" u ekstrahiranu mapu. Ekstrahirana mapa je pohrana ključ-vrijednost, gdje je ključ naziv polja, a vrijednost njegova vrijednost iz zapisa.
  2. Faze transformacije. Ova faza ima dvije opcije: transform, gdje postavljamo pravila transformacije, i izvor - izvor podataka za transformaciju iz ekstrahirane karte. Ako u ekstrahiranoj karti nema takvog polja, ono će se stvoriti. Na ovaj način moguće je kreirati oznake koje se ne temelje na ekstrahiranoj karti. U ovoj fazi možemo manipulirati podacima u izdvojenoj karti koristeći prilično moćan Predložak Golang. Osim toga, moramo imati na umu da se ekstrahirana mapa učitava u cijelosti tijekom parsiranja, što omogućuje, na primjer, provjeru vrijednosti u njoj: “{{if .tag}tag value exists{end}}”. Predložak podržava uvjete, petlje i neke funkcije niza kao što su Zamijeni i Skrati.
  3. Faze djelovanja. U ovom trenutku možete učiniti nešto s izdvojenim sadržajem:
    • Napravite oznaku iz ekstrahiranih podataka, koje će Loki indeksirati.
    • Promijenite ili postavite vrijeme događaja iz zapisnika.
    • Promijenite podatke (tekst dnevnika) koji će ići Lokiju.
    • Stvorite metriku.
  4. Faze filtriranja. Faza podudaranja, gdje možemo poslati unose koji nam nisu potrebni u /dev/null ili ih proslijediti na daljnju obradu.

Koristeći primjer obrade uobičajenih nginx zapisa, pokazat ću kako možete analizirati zapise pomoću Promtaila.

Za test, uzmimo kao nginx-proxy modificiranu nginx sliku jwilder/nginx-proxy:alpine i mali demon koji se može pitati putem HTTP-a. Demon ima nekoliko krajnjih točaka, kojima može dati odgovore različitih veličina, s različitim HTTP statusima i s različitim kašnjenjima.

Sakupljat ćemo zapise iz docker kontejnera, koji se mogu pronaći duž staze /var/lib/docker/containers/ / -json.log

U docker-compose.yml konfiguriramo Promtail i navodimo put do konfiguracije:

promtail:
  image: grafana/promtail:1.4.1
 // ...
 volumes:
   - /var/lib/docker/containers:/var/lib/docker/containers:ro
   - promtail-data:/var/lib/promtail/positions
   - ${PWD}/promtail/docker.yml:/etc/promtail/promtail.yml
 command:
   - '-config.file=/etc/promtail/promtail.yml'
 // ...

Dodajte stazu do zapisa u promtail.yml (postoji opcija “docker” u konfiguraciji, koja radi istu stvar u jednom retku, ali ne bi bilo tako jasno):

scrape_configs:
 - job_name: containers

   static_configs:
       labels:
         job: containerlogs
         __path__: /var/lib/docker/containers/*/*log  # for linux only

Kada je ova konfiguracija omogućena, zapisnici iz svih spremnika bit će poslani u Loki. Da bismo to izbjegli, mijenjamo postavke testnog nginxa u docker-compose.yml - dodajte polje oznake za prijavu:

proxy:
 image: nginx.test.v3
//…
 logging:
   driver: "json-file"
   options:
     tag: "{{.ImageName}}|{{.Name}}"

Uređivanje promtail.yml i postavljanje Pipelinea. Ulaz uključuje zapisnike sljedeće vrste:

{"log":"u001b[0;33;1mnginx.1    | u001b[0mnginx.test 172.28.0.3 - - [13/Jun/2020:23:25:50 +0000] "GET /api/index HTTP/1.1" 200 0 "-" "Stub_Bot/0.1" "0.096"n","stream":"stdout","attrs":{"tag":"nginx.promtail.test|proxy.prober"},"time":"2020-06-13T23:25:50.66740443Z"}
{"log":"u001b[0;33;1mnginx.1    | u001b[0mnginx.test 172.28.0.3 - - [13/Jun/2020:23:25:50 +0000] "GET /200 HTTP/1.1" 200 0 "-" "Stub_Bot/0.1" "0.000"n","stream":"stdout","attrs":{"tag":"nginx.promtail.test|proxy.prober"},"time":"2020-06-13T23:25:50.702925272Z"}

Faza cjevovoda:

 - json:
     expressions:
       stream: stream
       attrs: attrs
       tag: attrs.tag

Ekstrahiramo polja stream, attrs, attrs.tag (ako postoje) iz dolaznog JSON-a i stavljamo ih u ekstrahiranu mapu.

 - regex:
     expression: ^(?P<image_name>([^|]+))|(?P<container_name>([^|]+))$
     source: "tag"

Ako smo uspjeli staviti polje oznake u ekstrahiranu mapu, tada pomoću regexp izdvajamo nazive slike i spremnika.

 - labels:
     image_name:
     container_name:

Dodjeljujemo oznake. Ako se ključevi image_name i container_name nalaze u izdvojenim podacima, tada će njihove vrijednosti biti dodijeljene odgovarajućim oznakama.

 - match:
     selector: '{job="docker",container_name="",image_name=""}'
     action: drop

Odbacujemo sve zapisnike koji nemaju instalirane oznake image_name i container_name.

  - match:
     selector: '{image_name="nginx.promtail.test"}'
     stages:
       - json:
           expressions:
             row: log

Za sve zapise čiji je image_name nginx.promtail.test, ekstrahirajte polje dnevnika iz izvornog dnevnika i stavite ga u ekstrahiranu mapu pomoću ključa reda.

  - regex:
         # suppress forego colors
         expression: .+nginx.+|.+[0m(?P<virtual_host>[a-z_.-]+) +(?P<nginxlog>.+)
         source: logrow

Brišemo redak unosa regularnim izrazima i izvlačimo nginx virtualni host i redak nginx dnevnika.

     - regex:
         source: nginxlog
         expression: ^(?P<ip>[w.]+) - (?P<user>[^ ]*) [(?P<timestamp>[^ ]+).*] "(?P<method>[^ ]*) (?P<request_url>[^ ]*) (?P<request_http_protocol>[^ ]*)" (?P<status>[d]+) (?P<bytes_out>[d]+) "(?P<http_referer>[^"]*)" "(?P<user_agent>[^"]*)"( "(?P<response_time>[d.]+)")?

Raščlanite nginx zapisnik pomoću regularnih izraza.

    - regex:
           source: request_url
           expression: ^.+.(?P<static_type>jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$
     - regex:
           source: request_url
           expression: ^/photo/(?P<photo>[^/?.]+).*$
       - regex:
           source: request_url
           expression: ^/api/(?P<api_request>[^/?.]+).*$

Analizirajmo request_url. Pomoću regexpa određujemo svrhu zahtjeva: na statičke podatke, na fotografije, na API i postavljamo odgovarajući ključ u ekstrahiranoj karti.

       - template:
           source: request_type
           template: "{{if .photo}}photo{{else if .static_type}}static{{else if .api_request}}api{{else}}other{{end}}"

Koristeći uvjetne operatore u Predlošku, provjeravamo instalirana polja u ekstrahiranoj karti i postavljamo potrebne vrijednosti za polje request_type: photo, static, API. Dodijeli drugo ako ne uspije. request_type sada sadrži tip zahtjeva.

       - labels:
           api_request:
           virtual_host:
           request_type:
           status:

Oznake api_request, virtual_host, request_type i status (HTTP status) postavljamo na temelju onoga što smo uspjeli staviti u ekstrahiranu mapu.

       - output:
           source: nginx_log_row

Promjena izlaza. Sada očišćeni nginx zapis iz ekstrahirane karte ide Lokiju.

Skupljanje trupaca iz Lokija

Nakon pokretanja gornje konfiguracije, možete vidjeti da su svakom unosu dodijeljene oznake na temelju podataka iz dnevnika.

Jedna stvar koju treba imati na umu je da dohvaćanje oznaka s velikim brojem vrijednosti (kardinalnost) može značajno usporiti Lokija. To jest, ne biste trebali staviti, na primjer, user_id u indeks. Više o tome pročitajte u članku “Kako oznake u Lokiju mogu ubrzati i olakšati upite dnevnika" Ali to ne znači da ne možete pretraživati ​​po user_id bez indeksa. Prilikom pretraživanja trebate koristiti filtre ("zgrabiti" podatke), a indeks ovdje djeluje kao identifikator toka.

Vizualizacija logova

Skupljanje trupaca iz Lokija

Loki može djelovati kao izvor podataka za Grafana grafove koristeći LogQL. Podržane su sljedeće značajke:

  • brzina — broj zapisa u sekundi;
  • brojanje tijekom vremena — broj zapisa u navedenom rasponu.

Tu su i funkcije zbrajanja Sum, Prosjek i druge. Možete izgraditi prilično složene grafikone, na primjer grafikon broja HTTP pogrešaka:

Skupljanje trupaca iz Lokija

Standardni izvor podataka Loki donekle je smanjene funkcionalnosti u usporedbi s izvorom podataka Prometheus (na primjer, ne možete promijeniti legendu), ali Loki se može povezati kao izvor s tipom Prometheus. Nisam siguran je li to dokumentirano ponašanje, ali sudeći po odgovoru programera “Kako konfigurirati Loki kao Prometheus izvor podataka? · Izdanje #1222 · grafana/loki”, na primjer, potpuno je legalan, a Loki je potpuno kompatibilan s PromQL-om.

Dodajte Loki kao izvor podataka s tipom Prometheus i dodajte URL /loki:

Skupljanje trupaca iz Lokija

I možemo napraviti grafikone, kao da radimo s metrikom iz Prometeja:

Skupljanje trupaca iz Lokija

Mislim da je razlika u funkcionalnosti privremena i programeri će to ispraviti u budućnosti.

Skupljanje trupaca iz Lokija

Metrika

Loki pruža mogućnost izvlačenja numeričke metrike iz zapisa i slanja ih Prometeju. Na primjer, nginx log sadrži broj bajtova po odgovoru, kao i, uz određene izmjene standardnog formata dnevnika, vrijeme u sekundama koje je bilo potrebno za odgovor. Ovi se podaci mogu izdvojiti i poslati Prometeju.

Dodajte još jedan odjeljak u promtail.yml:

- match:
   selector: '{request_type="api"}'
   stages:
     - metrics:
         http_nginx_response_time:
           type: Histogram
           description: "response time ms"
           source: response_time
           config:
             buckets: [0.010,0.050,0.100,0.200,0.500,1.0]
- match:
   selector: '{request_type=~"static|photo"}'
   stages:
     - metrics:
         http_nginx_response_bytes_sum:
           type: Counter
           description: "response bytes sum"
           source: bytes_out
           config:
             action: add
         http_nginx_response_bytes_count:
           type: Counter
           description: "response bytes count"
           source: bytes_out
           config:
             action: inc

Opcija vam omogućuje definiranje i ažuriranje metrike na temelju podataka iz izdvojene karte. Ove se metrike ne šalju Lokiju - pojavljuju se u krajnjoj točki Promtail /metrics. Prometheus mora biti konfiguriran za primanje primljenih podataka u ovoj fazi. U gornjem primjeru, za request_type=“api” prikupljamo metriku histograma. S ovom vrstom metrike prikladno je dobiti percentile. Za statiku i fotografiju prikupljamo zbroj bajtova i broj redaka u kojima smo primili bajtove kako bismo izračunali prosjek.

Pročitajte više o mjernim podacima здесь.

Otvorite port na Promtailu:

promtail:
     image: grafana/promtail:1.4.1
     container_name: monitoring.promtail
     expose:
       - 9080
     ports:
       - "9080:9080"

Provjerite pojavljuju li se mjerni podaci s prefiksom promtail_custom:

Skupljanje trupaca iz Lokija

Postavljanje Prometeja. Dodajte promtail posla:

- job_name: 'promtail'
 scrape_interval: 10s
 static_configs:
   - targets: ['promtail:9080']

I crtamo graf:

Skupljanje trupaca iz Lokija

Na taj način možete saznati, na primjer, četiri najsporija upita. Također možete postaviti nadzor za ove metrike.

Skaliranje

Loki može biti u pojedinačnom binarnom načinu ili u razdijeljenom načinu (vodoravno skalabilni način). U drugom slučaju može spremati podatke u oblak, a dijelovi i indeks pohranjuju se odvojeno. Verzija 1.5 uvodi mogućnost pohranjivanja na jednom mjestu, ali se još ne preporučuje korištenje u proizvodnji.

Skupljanje trupaca iz Lokija

Dijelovi se mogu pohraniti u S3-kompatibilnu pohranu, a horizontalno skalabilne baze podataka mogu se koristiti za pohranjivanje indeksa: Cassandra, BigTable ili DynamoDB. Ostali dijelovi Lokija - Distributors (za pisanje) i Querier (za upite) - nemaju status i također se skaliraju vodoravno.

Na konferenciji DevOpsDays Vancouver 2019, jedan od sudionika Callum Styan objavio je da s Lokijem njegov projekt ima petabajte zapisa s indeksom manjim od 1% ukupne veličine: “Kako Loki povezuje metriku i zapisnike — i štedi vaš novac".

Usporedba Lokija i ELK-a

Veličina indeksa

Kako bih testirao rezultirajuću veličinu indeksa, uzeo sam zapise iz nginx spremnika za koji je gore konfiguriran Pipeline. Datoteka dnevnika sadržavala je 406 624 redaka ukupne veličine 109 MB. Dnevnici su generirani unutar jednog sata, otprilike 100 unosa u sekundi.

Primjer dva retka iz dnevnika:

Skupljanje trupaca iz Lokija

Kada ga je indeksirao ELK, ovo je dalo veličinu indeksa od 30,3 MB:

Skupljanje trupaca iz Lokija

U slučaju Lokija, to je rezultiralo s približno 128 KB indeksa i približno 3,8 MB podataka u komadima. Vrijedno je napomenuti da je zapisnik umjetno generiran i da nije sadržavao veliku raznolikost podataka. Jednostavan gzip na izvornom Docker JSON logu s podacima dao je kompresiju od 95,4%, a uzimajući u obzir činjenicu da je samo očišćeni nginx log poslan samom Lokiju, kompresija do 4 MB je razumljiva. Ukupan broj jedinstvenih vrijednosti za Loki oznake bio je 35, što objašnjava malu veličinu indeksa. Za ELK zapisnik je također očišćen. Tako je Loki komprimirao izvorne podatke za 96%, a ELK za 70%.

Potrošnja memorije

Skupljanje trupaca iz Lokija

Ako usporedimo cijeli Prometheus i ELK stack, onda Loki "jede" nekoliko puta manje. Jasno je da Go servis troši manje od Java servisa i da je usporedba veličine JVM Heap Elasticsearcha i dodijeljene memorije za Loki netočna, no unatoč tome vrijedi napomenuti da Loki koristi mnogo manje memorije. Njegova CPU prednost nije toliko očita, ali je također prisutna.

Ubrzati

Loki brže "proždire" cjepanice. Brzina ovisi o mnogim čimbenicima - kakve su zapisi, koliko smo sofisticirani u njihovom parsiranju, mreži, disku itd. - ali je definitivno veća od ELK-a (u mom testu - otprilike dvostruko). To se objašnjava činjenicom da Loki stavlja mnogo manje podataka u indeks i, sukladno tome, troši manje vremena na indeksiranje. Kod brzine pretraživanja situacija je suprotna: Loki osjetno usporava na podacima većim od nekoliko gigabajta, dok kod ELK-a brzina pretraživanja ne ovisi o veličini podataka.

Pretraživanje dnevnika

Loki je značajno inferioran u odnosu na ELK u smislu mogućnosti pretraživanja dnevnika. Grep s regularnim izrazima je moćan, ali je inferioran zreloj bazi podataka. Nedostatak upita raspona, agregacija samo po oznakama, nemogućnost pretraživanja bez oznaka - sve nas to ograničava u traženju informacija od interesa u Lokiju. To ne znači da se pomoću Lokija ništa ne može pronaći, ali definira tijek rada s zapisnicima kada prvi put pronađete problem u Prometheusovim kartama, a zatim pomoću tih oznaka potražite što se dogodilo u zapisnicima.

sučelje

Prije svega, prekrasan je (oprostite, nisam mogao odoljeti). Grafana ima lijepo sučelje, ali Kibana je mnogo bogatija značajkama.

Prednosti i mane Lokija

Jedna od prednosti je ta što se Loki integrira s Prometheusom, tako da dobivamo metriku i uzbunjivanje izvan okvira. Pogodan je za prikupljanje zapisa i njihovo pohranjivanje iz Kubernetes Pods, jer ima otkrivanje usluge naslijeđeno od Prometheusa i automatski prilaže oznake.

Loša strana je slaba dokumentacija. Neke stvari, na primjer, značajke i mogućnosti Promtaila, otkrio sam tek u procesu proučavanja koda, na sreću, otvorenog je koda. Drugi nedostatak su slabe mogućnosti parsiranja. Na primjer, Loki ne može analizirati višeredne zapisnike. Drugi nedostatak je što je Loki relativno mlada tehnologija (izdanje 1.0 bilo je u studenom 2019.).

Zaključak

Loki je 100% zanimljiva tehnologija koja je prikladna za male i srednje projekte, omogućuje vam rješavanje mnogih problema agregacije dnevnika, pretraživanja dnevnika, praćenja i analize dnevnika.

Ne koristimo Lokija na Badoou jer imamo ELK stack koji nam odgovara i koji je tijekom godina obrastao raznim prilagođenim rješenjima. Za nas je kamen spoticanja traženje balvana. Uz gotovo 100 GB zapisa dnevno, važno nam je da možemo pronaći sve i malo više i to brzo. Za crtanje i praćenje koristimo druga rješenja koja su prilagođena našim potrebama i međusobno integrirana. Loki stack ima opipljive prednosti, ali nam neće dati više nego što već imamo, a njegove prednosti sigurno neće nadmašiti troškove migracije.

I iako je nakon istraživanja postalo jasno da ne možemo koristiti Loki, nadamo se da će vam ovaj post pomoći u izboru.

Repozitorij s kodom korištenim u članku se nalazi ovdje.

Izvor: www.habr.com

Dodajte komentar