A világ legkényelmesebb felületét* fejlesztjük a naplók megtekintéséhez

A világ legkényelmesebb felületét* fejlesztjük a naplók megtekintéséhez Ha valaha is használt webes felületeket a naplók megtekintéséhez, akkor valószínűleg észrevette, hogy ezek a felületek általában nehézkesek és (gyakran) nem túl kényelmesek és érzékenyek. Néhányat meg lehet szokni, van, amelyik teljesen szörnyű, de számomra úgy tűnik, hogy minden probléma oka az, hogy helytelenül közelítjük meg a naplók megtekintésének feladatát: megpróbálunk létrehozni egy webes felületet, ahol a CLI (parancssori felület) jobban működik. Én személy szerint nagyon kényelmesen tudok dolgozni a tail-el, grep-pel, awk-kal és másokkal, ezért számomra az ideális interfész a naplókkal való munkához valami hasonló lenne a tail-hoz és a grep-hez, de ez is használható számos szerverről származó naplók olvasására. Ez persze olvassa el őket a ClickHouse-ból!

*a habra használó személyes véleménye szerint király vagy

Ismerje meg a logscli-t

Nem én találtam ki nevet a felületemnek, és hogy őszinte legyek, inkább prototípus formájában létezik, de ha azonnal látni szeretnéd a forráskódot, akkor szívesen látod: https://github.com/YuriyNasretdinov/logscli (350 sor kiválasztott Go kód).

Képességek

Célom az volt, hogy egy olyan felületet készítsek, ami ismerősnek tűnik a tail/grep-hez szokottak számára, vagyis az alábbi dolgokat támogatja:

  1. Az összes napló megtekintése szűrés nélkül.
  2. Hagyja meg a rögzített részkarakterláncot tartalmazó sorokat (jelző -F у grep).
  3. Hagyjon meg olyan sorokat, amelyek megfelelnek a reguláris kifejezésnek (jelző -E у grep).
  4. Alapértelmezés szerint a megtekintés fordított időrendben történik, mivel általában a legfrissebb naplók érdekesek először.
  5. Kontextus megjelenítése az egyes sorok mellett (opciók -A, -B и -C у grep, N sort nyomtat az egyes egyező sorok elé, utána és köré).
  6. Megtekintheti a bejövő naplókat valós időben, szűréssel vagy anélkül (lényegében tail -f | grep).
  7. Az interfésznek kompatibilisnek kell lennie less, head, tail és mások - alapértelmezés szerint az eredményeket a számuk korlátozása nélkül kell visszaküldeni; a sorokat adatfolyamként nyomtatják ki, amíg a felhasználót érdekli a fogadás; jel SIGPIPE csendben meg kell szakítaniuk a naplózást, ahogy ők teszik tail, grep és egyéb UNIX segédprogramok.

Реализация

Feltételezem, hogy valamilyen módon már tudja, hogyan kell naplókat eljuttatni a ClickHouse-hoz. Ha nem, akkor azt javaslom, próbálja ki LSD и cicaházÉs ez a cikk a rönkszállításról.

Először el kell döntenie az alaprendszert. Mivel általában idő szerint rendezett naplókat szeretne kapni, logikusnak tűnik, hogy így tárolja őket. Ha sok naplókategória van, és mindegyik azonos típusú, akkor létrehozhat egy naplókategóriát az elsődleges kulcs első oszlopaként - ez lehetővé teszi, hogy több helyett egy tábla legyen, ami nagy előnyt jelent, ha beszúrás a ClickHouse-ba (merevlemezes szervereken legfeljebb ~1 alkalommal ajánlott beszúrni az adatokat másodpercenként az egész szerverre).

Vagyis hozzávetőlegesen a következő táblázatsémára van szükségünk:

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

Sajnos nem találtam azonnal nyílt forráskódot valósághű naplókkal, amelyeket meg tudtam fogni és letölteni, ezért inkább ezt vettem példaként vélemények az Amazon termékeiről 2015 előtt. Felépítésük természetesen nem teljesen megegyezik a szöveges naplókéval, de szemléltetési szempontból ez nem fontos.

utasítások az Amazon-vélemények ClickHouse-ba való feltöltéséhez

Hozzunk létre egy táblázatot:

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

Az Amazon adathalmazában csak egy áttekintés dátuma van, de pontos idő nincs, ezért töltsük ki ezeket az adatokat véletlenszerűen.

Nem kell letöltenie az összes tsv fájlt, és az első ~ 10-20-ra korlátozni magát ahhoz, hogy meglehetősen nagy adathalmazt kapjon, amely nem fér bele a 16 GB RAM-ba. A TSV-fájlok feltöltéséhez a következő parancsot használtam:

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

Egy szabványos Persistent Disk-en (ami egy HDD) a Google Cloudban 1000 GB-os méretben (ezt a méretet főleg azért vettem, hogy kicsit nagyobb legyen a sebesség, bár talán olcsóbb lett volna egy megfelelő méretű SSD) a feltöltés a sebesség körülbelül ~ 75 MB/sec volt 4 magon.

  • Le kell foglalnom, hogy a Google-nál dolgozom, de személyes fiókot használtam, és ennek a cikknek semmi köze a cégnél végzett munkámhoz

Az összes illusztrációt ezzel a konkrét adatkészlettel készítem, mivel csak ez volt a kezemben.

Az adatok szkennelésének folyamatának megjelenítése

Mivel a ClickHouse-ban teljes vizsgálatot fogunk végezni egy naplókkal ellátott táblázaton, és ez a művelet jelentős időt vehet igénybe, és hosszú ideig nem hoz eredményt, ha kevés egyezést találunk, célszerű megmutatni a a lekérdezés előrehaladását, amíg meg nem érkezik az eredményt tartalmazó első sor. Ehhez a HTTP-felületen van egy paraméter, amely lehetővé teszi a HTTP-fejlécekben történő előrehaladást: send_progress_in_http_headers=1. Sajnos a szabványos Go könyvtár nem tudja beolvasni a fejléceket a beérkezésükkor, de a HTTP 1.0 felületet (nem tévesztendő össze az 1.1-gyel!) támogatja a ClickHouse, így nyers TCP-kapcsolatot nyithat a ClickHouse-hoz és elküldheti oda. GET /?query=... HTTP/1.0nn és megkapjuk a válaszfejléceket és a törzset mindenféle menekülés vagy titkosítás nélkül, így ebben az esetben nem is kell a szabványos könyvtárat használnunk.

Naplók streamelése a ClickHouse-ból

A ClickHouse viszonylag hosszú ideje (2019 óta?) optimalizálja a lekérdezéseket az ORDER BY-val, így egy olyan lekérdezés, mint pl.

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

Azonnal elkezdi visszaadni azokat a sorokat, amelyek üzenetében a "valami" részkarakterlánc szerepel, anélkül, hogy megvárná a vizsgálat befejezését.

Ezenkívül nagyon kényelmes lenne, ha a ClickHouse maga törölné a kérést, amikor a kapcsolat megszakadt, de ez nem az alapértelmezett viselkedés. A kérés automatikus törlése az opcióval engedélyezhető cancel_http_readonly_queries_on_client_close=1.

A SIGPIPE helyes kezelése Go-ban

Amikor végrehajtja, mondjuk, a parancsot some_cmd | head -n 10, pontosan hogyan a parancs some_cmd leállítja a végrehajtást, amikor head kivont 10 sort? A válasz egyszerű: mikor head véget ér, a cső bezárul, és a some_cmd parancs stdoutja feltételesen a „semmibe” kezd mutatni. Amikor some_cmd zárt csőre próbál írni, SIGPIPE jelet kap, ami alapesetben csendben leállítja a programot.

A Go-ban ez is megtörténik alapból, de a SIGPIPE jelkezelő a "signal: SIGPIPE" vagy hasonló üzenetet is kiírja a végére, és ennek az üzenetnek a törléséhez csak magunknak kell kezelnünk a SIGPIPE-ot úgy, ahogy akarjuk, vagyis csak csendben. kijárat:

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

Üzenetkörnyezet megjelenítése

Gyakran szeretné látni azt a kontextust, amelyben valamilyen hiba történt (például melyik kérés okozott pánikot, vagy milyen kapcsolódó problémák voltak láthatók az összeomlás előtt), és grep Ez az -A, -B és -C opciókkal történik, amelyek az üzenet után, előtt és körül megadott sorok számát mutatják.

Sajnos nem találtam egyszerű módot erre a ClickHouse-ban, ezért a kontextus megjelenítéséhez az eredmény minden sorába egy ehhez hasonló kérést küldenek (a részletek a rendezéstől és a kontextus megjelenítésétől függenek vagy utána):

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

Mivel a kérés szinte azonnal elküldésre kerül, miután a ClickHouse visszaadja a megfelelő sort, így a gyorsítótárba kerül, és általában a kérés elég gyorsan végrehajtódik, és kevés CPU-t fogyaszt (általában a kérés kb. 6 ms-t vesz igénybe a virtuális gépemen).

Jelenítse meg az új üzeneteket valós időben

Annak érdekében, hogy a bejövő üzeneteket (majdnem) valós időben jelenítsük meg, egyszerűen néhány másodpercenként végrehajtjuk a kérést, emlékezve a legutóbbi időbélyegzőre, amellyel korábban találkoztunk.

Parancspéldák

Hogyan néznek ki a tipikus logscli parancsok a gyakorlatban?

Ha letöltötte a cikk elején említett Amazon adatkészletet, akkor a következő parancsokat futtathatja:

# Показать строки, где встречается слово 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

referenciák

A segédprogram kódja (dokumentáció nélkül) elérhető a githubon a címen https://github.com/YuriyNasretdinov/logscli. Örömmel venném a véleményét a ClickHouse alapú naplók megtekintésére szolgáló konzolfelületre vonatkozó ötletemről.

Forrás: will.com

Hozzászólás