Kehitämme maailman kätevintä käyttöliittymää* lokien katseluun

Kehitämme maailman kätevintä käyttöliittymää* lokien katseluun Jos olet joskus käyttänyt verkkokäyttöliittymiä lokien katseluun, olet todennäköisesti huomannut, että nämä käyttöliittymät ovat yleensä hankalia ja (usein) eivät kovin käteviä ja reagoivia. Joihinkin voi tottua, jotkut ovat aivan kauheita, mutta minusta näyttää siltä, ​​​​että syy kaikkiin ongelmiin on se, että lähestymme lokien katselutehtävää väärin: yritämme luoda verkkokäyttöliittymän, jossa CLI (command line interface) toimii paremmin. Olen henkilökohtaisesti erittäin mukava työskennellä tail-, grep-, awk- ja muiden kanssa, ja siksi minulle ihanteellinen käyttöliittymä lokien kanssa työskentelemiseen olisi jotain tail- ja grep-tyyppistä, mutta sitä voitaisiin käyttää myös monilta palvelimilta tulevien lokien lukemiseen. Tämä on tietysti, lue ne ClickHousesta!

*habran käyttäjän henkilökohtaisen mielipiteen mukaan sinä rokkaat

Tapaa logscli

En keksinyt käyttöliittymälleni nimeä, ja rehellisesti sanottuna se on pikemminkin olemassa prototyypin muodossa, mutta jos haluat nähdä lähdekoodin heti, olet tervetullut: https://github.com/YuriyNasretdinov/logscli (350 riviä valittua Go-koodia).

Kyvyt

Tavoitteenani oli tehdä käyttöliittymä, joka tuntuisi tutulta tail/grepiin tottuneille, eli tukemaan seuraavia asioita:

  1. Näytä kaikki lokit ilman suodatusta.
  2. Jätä rivit, jotka sisältävät kiinteän osamerkkijonon (lippu -F у grep).
  3. Jätä rivit, jotka vastaavat säännöllistä lauseketta (lippu -E у grep).
  4. Oletusarvoisesti katselu tapahtuu käänteisessä kronologisessa järjestyksessä, koska viimeisimmät lokit kiinnostavat yleensä ensin.
  5. Näytä konteksti jokaisen rivin vieressä (valinnat -A, -B и -C у grep, tulostaa N riviä kunkin vastaavan rivin eteen, jälkeen ja ympärille).
  6. Tarkastele saapuvia lokeja reaaliajassa, suodatuksella tai ilman (pääasiassa tail -f | grep).
  7. Käyttöliittymän on oltava yhteensopiva less, head, tail ja muut - oletusarvoisesti tulokset tulee palauttaa ilman rajoituksia niiden lukumäärälle; rivit tulostetaan virtana niin kauan kuin käyttäjä on kiinnostunut vastaanottamaan ne; signaali SIGPIPE pitäisi hiljaa keskeyttää lokin suoratoisto, aivan kuten he tekevät tail, grep ja muut UNIX-apuohjelmat.

Реализация

Oletan, että tiedät jo jotenkin kuinka toimittaa lokit ClickHouselle. Jos ei, suosittelen kokeilemaan lsd и kissanpentuJa tämä artikkeli tukkitoimituksesta.

Ensin sinun on päätettävä perusjärjestelmästä. Koska yleensä haluat vastaanottaa lokit ajan mukaan lajiteltuina, näyttää loogiselta tallentaa ne tällä tavalla. Jos lokikategorioita on useita ja ne ovat kaikki samaa tyyppiä, voit tehdä lokiluokan ensisijaisen avaimen ensimmäiseksi sarakkeeksi - tämä mahdollistaa yhden taulukon useiden sijasta, mikä on iso plussa, kun lisääminen ClickHouseen (palvelimissa, joissa on kovalevy, suositellaan syöttämään tietoja enintään ~1 kertaa sekunnissa koko palvelimelle).

Eli tarvitsemme suunnilleen seuraavan taulukkokaavion:

CREATE TABLE logs(
    category LowCardinality(String), -- категория логов (опционально)
    time DateTime, -- время события
    millis UInt16, -- миллисекунды (могут быть и микросекунды, и т.д.): рекомендуется хранить, если событий много, чтобы было легче различать события между собой
    ..., -- ваши собственные поля, например имя сервера, уровень логирования, и так далее
    message String -- текст сообщения
) ENGINE=MergeTree()
ORDER BY (category, time, millis)

Valitettavasti en heti löytänyt avoimia lähteitä realistisilla lokeilla, joita voisin napata ja ladata, joten otin tämän sen sijaan esimerkkinä Amazonin tuotteiden arvostelut vuoteen 2015 asti. Niiden rakenne ei tietenkään ole aivan sama kuin tekstilokien, mutta havainnollistamistarkoituksessa tämä ei ole tärkeää.

ohjeet Amazon-arvostelujen lataamiseen ClickHouseen

Luodaan taulukko:

CREATE TABLE amazon(
   review_date Date,
   time DateTime DEFAULT toDateTime(toUInt32(review_date) * 86400 + rand() % 86400),
   millis UInt16 DEFAULT rand() % 1000,
   marketplace LowCardinality(String),
   customer_id Int64,
   review_id String,
   product_id LowCardinality(String),
   product_parent Int64,
   product_title String,
   product_category LowCardinality(String),
   star_rating UInt8,
   helpful_votes UInt32,
   total_votes UInt32,
   vine FixedString(1),
   verified_purchase FixedString(1),
   review_headline String,
   review_body String
)
ENGINE=MergeTree()
ORDER BY (time, millis)
SETTINGS index_granularity=8192

Amazon-tietojoukossa on vain tarkastelun päivämäärä, mutta tarkkaa aikaa ei ole, joten täytä tämä tieto satunnaisella.

Sinun ei tarvitse ladata kaikkia tsv-tiedostoja ja rajoittua ensimmäisiin ~10-20 saadaksesi melko suuren tietojoukon, joka ei mahdu 16 Gt RAM-muistiin. TSV-tiedostojen lataamiseen käytin seuraavaa komentoa:

for i in *.tsv; do
    echo $i;
    tail -n +2 $i | pv |
    clickhouse-client --input_format_allow_errors_ratio 0.5 --query='INSERT INTO amazon(marketplace,customer_id,review_id,product_id,product_parent,product_title,product_category,star_rating,helpful_votes,total_votes,vine,verified_purchase,review_headline,review_body,review_date) FORMAT TabSeparated'
done

Google Cloudin tavallisella Pysyvällä levyllä (joka on HDD) kooltaan 1000 Gt (otin tämän koon lähinnä siksi, että nopeus olisi hieman suurempi, vaikka ehkä tarvittavan kokoinen SSD olisi ollut halvempi) nopeus oli noin ~ 75 MB/s 4 ytimellä.

  • Minun on tehtävä varaus, että työskentelen Googlella, mutta käytin henkilökohtaista tiliä, eikä tällä artikkelilla ole mitään tekemistä työni kanssa yrityksessä

Tuotan kaikki kuvat tällä tiedolla, koska tämä on kaikki, mitä minulla oli käsillä.

Näytä tietojen skannauksen edistyminen

Koska ClickHousessa käytämme täydellistä skannausta taulukossa, jossa on lokit, ja tämä toiminto voi viedä huomattavasti aikaa eikä välttämättä tuota tuloksia pitkään aikaan, jos vain vähän osumia löytyy, on suositeltavaa pystyä näyttämään kyselyn edistymistä, kunnes ensimmäiset tuloksen sisältävät rivit on vastaanotettu. Tätä varten HTTP-rajapinnassa on parametri, jonka avulla voit lähettää edistymisen HTTP-otsikoissa: send_progress_in_http_headers=1. Valitettavasti tavallinen Go-kirjasto ei voi lukea otsikoita vastaanotettaessa, mutta ClickHouse tukee HTTP 1.0 -käyttöliittymää (ei pidä sekoittaa 1.1:een!), joten voit avata raaka-TCP-yhteyden ClickHouselle ja lähettää sen sinne GET /?query=... HTTP/1.0nn ja vastaanottaa vastausotsikot ja rungon ilman pakottamista tai salausta, joten tässä tapauksessa meidän ei tarvitse edes käyttää vakiokirjastoa.

Lokien suoratoisto ClickHousesta

ClickHousella on ollut optimointia kyselyille ORDER BY:llä suhteellisen pitkään (vuodesta 2019?), joten kyselyn kuten esim.

SELECT time, millis, message
FROM logs
WHERE message LIKE '%something%'
ORDER BY time DESC, millis DESC

Se alkaa välittömästi palauttaa rivejä, joiden viestissä on alimerkkijono "jotain", odottamatta skannauksen päättymistä.

Lisäksi olisi erittäin kätevää, jos ClickHouse itse peruuttaisi pyynnön, kun yhteys siihen suljettiin, mutta tämä ei ole oletuskäyttäytyminen. Pyynnön automaattinen peruutus voidaan ottaa käyttöön vaihtoehdolla cancel_http_readonly_queries_on_client_close=1.

SIGPIPE:n oikea käsittely Goissa

Kun suoritat vaikka komennon some_cmd | head -n 10, täsmälleen miten komento some_cmd lopettaa suorituksen, kun head vähennetty 10 riviä? Vastaus on yksinkertainen: milloin head päättyy, putki sulkeutuu ja some_cmd-komennon stdout alkaa osoittaa, ehdollisesti, "ei minnekään". Kun some_cmd yrittää kirjoittaa suljettuun putkeen, se vastaanottaa SIGPIPE-signaalin, joka oletusarvoisesti lopettaa ohjelman äänettömästi.

Go:ssa tämä myös tapahtuu oletusarvoisesti, mutta SIGPIPE-signaalin käsittelijä tulostaa loppuun myös "signal: SIGPIPE" tai vastaavan viestin, ja tämän viestin poistamiseksi tarvitsemme vain käsitellä SIGPIPEa itse haluamallamme tavalla, eli vain hiljaa. poistu:

ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGPIPE)
go func() {
    <-ch
    os.Exit(0)
}()

Näytä viestin konteksti

Usein haluat nähdä kontekstin, jossa jokin virhe tapahtui (esimerkiksi mikä pyyntö aiheutti paniikkia tai mitä siihen liittyviä ongelmia oli näkyvissä ennen kaatumista) ja grep Tämä tehdään käyttämällä valintoja -A, -B ja -C, jotka näyttävät määritetyn määrän rivejä viestin jälkeen, ennen ja ympärillä, vastaavasti.

Valitettavasti en ole löytänyt helppoa tapaa tehdä samaa ClickHousessa, joten kontekstin näyttämiseksi jokaiselle tuloksen riville lähetetään tällainen lisäpyyntö (yksityiskohdat riippuvat lajittelusta ja näkyykö konteksti ennen tai sen jälkeen):

SELECT time,millis,review_body FROM amazon
WHERE (time = 'ВРЕМЯ_СОБЫТИЯ' AND millis < МИЛЛИСЕКУНДЫ_СОБЫТИЯ) OR (time < 'ВРЕМЯ_СОБЫТИЯ')
ORDER BY time DESC, millis DESC
LIMIT КОЛИЧЕСТВО_СТРОК_КОНТЕКСТА
SETTINGS max_threads=1

Koska pyyntö lähetetään lähes välittömästi ClickHouse palauttaa vastaavan rivin, se päätyy välimuistiin ja yleensä pyyntö suoritetaan melko nopeasti ja kuluttaa vähän prosessoria (yleensä pyyntö vie virtuaalikoneellani noin ~6 ms).

Näytä uudet viestit reaaliajassa

Saapuvien viestien näyttämiseksi (melkein) reaaliajassa suoritamme pyynnön kerran muutaman sekunnin välein, muistaen viimeksi havaitsemamme aikaleiman.

Esimerkkejä komentoista

Miltä tyypilliset logscli-komennot näyttävät käytännössä?

Jos latasit artikkelin alussa mainitsemani Amazon-tietojoukon, voit suorittaa seuraavat komennot:

# Показать строки, где встречается слово walmart
$ logscli -F 'walmart' | less

# Показать самые свежие 10 строк, где встречается "terrible"
$ logscli -F terrible -limit 10

# То же самое без -limit:
$ logscli -F terrible | head -n 10

# Показать все строки, подходящие под /times [0-9]/, написанные для vine и у которых высокий рейтинг
$ logscli -E 'times [0-9]' -where="vine='Y' AND star_rating>4" | less

# Показать все строки со словом "panic" и 3 строки контекста вокруг
$ logscli -F 'panic' -C 3 | less

# Непрерывно показывать новые строки со словом "5-star"
$ logscli -F '5-star' -tailf

viittaukset

Apuohjelmakoodi (ilman asiakirjoja) on saatavilla githubista osoitteessa https://github.com/YuriyNasretdinov/logscli. Haluaisin mielelläni kuulla ajatuksesi ideastani konsolikäyttöliittymästä ClickHouse-pohjaisten lokien katseluun.

Lähde: will.com

Lisää kommentti