Ak ste niekedy používali webové rozhrania na prezeranie protokolov, pravdepodobne ste si všimli, že tieto rozhrania sú spravidla ťažkopádne a (často) nie príliš pohodlné a citlivé. Na niektoré sa dá zvyknúť, niektoré sú úplne hrozné, ale zdá sa mi, že dôvodom všetkých problémov je, že nesprávne pristupujeme k úlohe prezerania protokolov: snažíme sa vytvoriť webové rozhranie, v ktorom je CLI (rozhranie príkazového riadku) funguje lepšie. Mne osobne veľmi vyhovuje práca s tail, grep, awk a ďalšími, a preto by pre mňa bolo ideálne rozhranie pre prácu s logami niečo podobné ako tail a grep, ktoré by sa však dalo použiť aj na čítanie logov, ktoré prišli z mnohých serverov. To je, samozrejme, prečítajte si ich z ClickHouse!
*podľa osobného názoru používateľa habra
Zoznámte sa s logscli
Názov pre svoje rozhranie som nevymyslel a, úprimne povedané, existuje skôr vo forme prototypu, ale ak chcete okamžite vidieť zdrojový kód, ste vítaní: (350 riadkov zvoleného Go kódu).
Možnosti
Mojím cieľom bolo vytvoriť rozhranie, ktoré by sa zdalo známe tým, ktorí sú zvyknutí na tail/grep, teda na podporu nasledujúcich vecí:
- Zobraziť všetky denníky bez filtrovania.
- Ponechajte riadky obsahujúce pevný podreťazec (príznak
-Fуgrep). - Nechajte riadky, ktoré zodpovedajú regulárnemu výrazu (príznak
-Eуgrep). - V predvolenom nastavení je prezeranie v obrátenom chronologickom poradí, pretože ako prvé sú zvyčajne zaujímavé najnovšie protokoly.
- Zobraziť kontext vedľa každého riadku (možnosti
-A,-Bи-Cуgreptlač N riadkov pred, za a okolo každého zodpovedajúceho riadku). - Prezerajte si prichádzajúce denníky v reálnom čase, s filtrovaním alebo bez filtrovania (v podstate
tail -f | grep). - Rozhranie musí byť kompatibilné s
less,head,taila iné - štandardne by sa výsledky mali vracať bez obmedzenia ich počtu; riadky sa tlačia ako prúd, pokiaľ má používateľ záujem o ich príjem; signálSIGPIPEby mali ticho prerušiť streamovanie denníka, rovnako ako onitail,grepa ďalšie nástroje UNIX.
Реализация
Budem predpokladať, že už nejako viete, ako doručiť protokoly do ClickHouse. Ak nie, odporúčam vyskúšať и a .
Najprv sa musíte rozhodnúť pre základnú schému. Keďže zvyčajne chcete dostávať protokoly zoradené podľa času, zdá sa logické ich uchovávať týmto spôsobom. Ak existuje veľa kategórií denníkov a všetky sú rovnakého typu, potom môžete vytvoriť kategóriu denníka ako prvý stĺpec primárneho kľúča – to vám umožní mať jednu tabuľku namiesto niekoľkých, čo bude veľké plus, keď vkladanie do ClickHouse (na serveroch s pevnými diskami sa odporúča vkladať dáta nie viac ako ~1-krát za sekundu pre celý server).
To znamená, že potrebujeme približne nasledujúcu schému tabuľky:
CREATE TABLE logs(
category LowCardinality(String), -- категория логов (опционально)
time DateTime, -- время события
millis UInt16, -- миллисекунды (могут быть и микросекунды, и т.д.): рекомендуется хранить, если событий много, чтобы было легче различать события между собой
..., -- ваши собственные поля, например имя сервера, уровень логирования, и так далее
message String -- текст сообщения
) ENGINE=MergeTree()
ORDER BY (category, time, millis)Žiaľ, nemohol som okamžite nájsť žiadne otvorené zdroje s realistickými protokolmi, ktoré by som mohol chytiť a stiahnuť, takže som namiesto toho vzal toto ako príklad . Samozrejme, ich štruktúra nie je úplne rovnaká ako štruktúra textových protokolov, ale pre ilustráciu to nie je dôležité.
pokyny na nahrávanie recenzií Amazonu do ClickHouse
Vytvorme si tabuľku:
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=8192V súbore údajov Amazonu je len dátum na kontrolu, ale nie je tam presný čas, takže vyplňte tieto údaje náhodne.
Nemusíte sťahovať všetky súbory tsv a obmedzovať sa na prvých ~10-20, aby ste získali pomerne veľký súbor údajov, ktoré sa nezmestia do 16 GB pamäte RAM. Na nahranie súborov TSV som použil nasledujúci príkaz:
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'
doneNa štandardný perzistentný disk (čo je HDD) v Google Cloud s veľkosťou 1000 GB (túto veľkosť som bral hlavne preto, aby bola rýchlosť trochu vyššia, aj keď možno SSD požadovanej veľkosti by bolo lacnejšie) upload rýchlosť bola približne ~ 75 MB/s na 4 jadrách.
- Musím si rezervovať, že pracujem v Google, ale použil som osobný účet a tento článok nemá nič spoločné s mojou prácou v spoločnosti
Vyrobím všetky ilustrácie s týmto konkrétnym súborom údajov, pretože toto je všetko, čo som mal po ruke.
Zobraziť priebeh skenovania údajov
Keďže v ClickHouse použijeme úplné skenovanie tabuľky s protokolmi a táto operácia môže trvať veľa času a nemusí dlho prinášať žiadne výsledky, ak sa nájde málo zhôd, odporúča sa mať možnosť zobraziť priebeh dotazu až do prijatia prvých riadkov s výsledkom. Na tento účel je v rozhraní HTTP parameter, ktorý vám umožňuje odosielať priebeh v hlavičkách HTTP: send_progress_in_http_headers=1. Žiaľ, štandardná knižnica Go nedokáže čítať hlavičky tak, ako sú prijímané, ale rozhranie HTTP 1.0 (nezamieňať s 1.1!) je podporované službou ClickHouse, takže môžete otvoriť surové pripojenie TCP do ClickHouse a odoslať ho tam. GET /?query=... HTTP/1.0nn a prijímať hlavičky a telo odpovede bez akéhokoľvek escapovania alebo šifrovania, takže v tomto prípade ani nemusíme používať štandardnú knižnicu.
Streamovanie protokolov z ClickHouse
ClickHouse má optimalizáciu pre dopyty s ORDER BY relatívne dlho (od roku 2019?), takže dopyt ako
SELECT time, millis, message
FROM logs
WHERE message LIKE '%something%'
ORDER BY time DESC, millis DESCOkamžite začne vracať riadky, ktoré majú v správe podreťazec „niečo“, bez čakania na dokončenie skenovania.
Tiež by bolo veľmi výhodné, keby ClickHouse sám zrušil požiadavku, keď bolo pripojenie k nemu uzavreté, ale toto nie je predvolené správanie. Pomocou voľby je možné povoliť automatické zrušenie požiadavky cancel_http_readonly_queries_on_client_close=1.
Správna manipulácia so SIGPIPE v režime Go
Keď vykonáte, povedzme, príkaz some_cmd | head -n 10, presne ako príkaz some_cmd zastaví vykonávanie, keď head odčítal 10 riadkov? Odpoveď je jednoduchá: kedy head skončí, potrubie sa uzavrie a stdout príkazu some_cmd začne podmienečne ukazovať „nikam“. Kedy some_cmd pokúša sa písať do uzavretej trubice, .
V Go sa to tiež deje štandardne, ale obslužný program signálu SIGPIPE tiež na konci vypíše „signál: SIGPIPE“ alebo podobnú správu a na vymazanie tejto správy stačí, aby sme si so SIGPIPE sami zaobchádzali tak, ako chceme, teda len potichu. VÝCHOD:
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGPIPE)
go func() {
<-ch
os.Exit(0)
}()Zobraziť kontext správy
Často chcete vidieť kontext, v ktorom sa vyskytla nejaká chyba (napríklad, ktorá požiadavka spôsobila paniku alebo aké súvisiace problémy boli viditeľné pred pádom) a grep To sa vykonáva pomocou volieb -A, -B a -C, ktoré zobrazujú zadaný počet riadkov za, pred a okolo správy.
Bohužiaľ som nenašiel jednoduchý spôsob, ako urobiť to isté v ClickHouse, takže na zobrazenie kontextu sa na každý riadok výsledku odošle dodatočná požiadavka, ako je táto (podrobnosti závisia od zoradenia a od toho, či je kontext zobrazený pred alebo potom):
SELECT time,millis,review_body FROM amazon
WHERE (time = 'ВРЕМЯ_СОБЫТИЯ' AND millis < МИЛЛИСЕКУНДЫ_СОБЫТИЯ) OR (time < 'ВРЕМЯ_СОБЫТИЯ')
ORDER BY time DESC, millis DESC
LIMIT КОЛИЧЕСТВО_СТРОК_КОНТЕКСТА
SETTINGS max_threads=1Keďže požiadavka je odoslaná takmer okamžite po tom, čo ClickHouse vráti príslušný riadok, skončí vo vyrovnávacej pamäti a vo všeobecnosti je požiadavka vykonaná pomerne rýchlo a spotrebuje trochu CPU (zvyčajne žiadosť trvá asi ~6 ms na mojom virtuálnom počítači).
Zobrazte nové správy v reálnom čase
Aby sme mohli zobraziť prichádzajúce správy v (takmer) reálnom čase, jednoducho vykonáme požiadavku každých pár sekúnd, pričom si pamätáme poslednú časovú pečiatku, s ktorou sme sa predtým stretli.
Príklady príkazov
Ako vyzerajú typické príkazy logscli v praxi?
Ak ste si stiahli súbor údajov Amazon, ktorý som spomenul na začiatku článku, môžete spustiť nasledujúce príkazy:
# Показать строки, где встречается слово 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' -tailfreferencie
Pomocný kód (bez dokumentácie) je dostupný na github na adrese . Bol by som rád, keby ste si vypočuli váš názor na môj nápad na konzolové rozhranie na prezeranie protokolov založených na ClickHouse.
Zdroj: hab.com
