Ne po zhvillojmë ndërfaqen më të përshtatshme në botë* për shikimin e regjistrave

Ne po zhvillojmë ndërfaqen më të përshtatshme në botë* për shikimin e regjistrave Nëse keni përdorur ndonjëherë ndërfaqe në internet për të parë regjistrat, atëherë me siguri keni vënë re se si, si rregull, këto ndërfaqe janë të rënda dhe (shpesh) jo shumë të përshtatshme dhe të përgjegjshme. Disa me të cilat mund të mësoheni, disa janë absolutisht të tmerrshme, por mua më duket se arsyeja për të gjitha problemet është se ne po i afrohemi detyrës së shikimit të regjistrave gabimisht: ne po përpiqemi të krijojmë një ndërfaqe në internet ku CLI (linja e komandës ndërfaqja) funksionon më mirë. Unë personalisht jam shumë rehat duke punuar me tail, grep, awk dhe të tjera, dhe për këtë arsye për mua ndërfaqja ideale për të punuar me logs do të ishte diçka e ngjashme me tail dhe grep, por që mund të përdoret gjithashtu për të lexuar regjistrat që vinin nga shumë serverë. Kjo është, sigurisht, lexoni ato nga ClickHouse!

*sipas mendimit personal të përdoruesit të habra je fantastik

Njihuni me logscli

Unë nuk dola me një emër për ndërfaqen time, dhe, për të qenë i sinqertë, ai ekziston më tepër në formën e një prototipi, por nëse doni të shihni menjëherë kodin burimor, atëherë jeni të mirëpritur: https://github.com/YuriyNasretdinov/logscli (350 rreshta të kodit të zgjedhur Go).

Aftësitë

Qëllimi im ishte të krijoja një ndërfaqe që do t'u dukej e njohur për ata që janë mësuar me bisht/grep, domethënë të mbështeste gjërat e mëposhtme:

  1. Shikoni të gjitha regjistrat, pa filtrim.
  2. Lini linjat që përmbajnë një nënvarg fiks (flamur -F у grep).
  3. Lini rreshta që përputhen me shprehjen e rregullt (flamur -E у grep).
  4. Si parazgjedhje, shikimi është në rend të kundërt kronologjik, pasi regjistrat më të fundit zakonisht janë me interes fillimisht.
  5. Trego kontekstin pranë çdo rreshti (opsionet -A, -B и -C у grep, duke shtypur N rreshta para, pas dhe rreth çdo rreshti që përputhet, përkatësisht).
  6. Shikoni regjistrat hyrës në kohë reale, me ose pa filtrim (në thelb tail -f | grep).
  7. Ndërfaqja duhet të jetë e pajtueshme me less, head, tail dhe të tjerët - si parazgjedhje, rezultatet duhet të kthehen pa kufizime në numrin e tyre; linjat printohen si një transmetim për sa kohë që përdoruesi është i interesuar t'i marrë ato; sinjal SIGPIPE duhet të ndërpresin në heshtje transmetimin e regjistrave, ashtu siç bëjnë ata tail, grep dhe shërbime të tjera të UNIX.

Zbatimi

Unë do të supozoj se ju tashmë dini disi se si të dorëzoni regjistrat në ClickHouse. Nëse jo, unë rekomandoj ta provoni LSD и shtëpi koteleshDhe ky artikull në lidhje me dorëzimin e regjistrave.

Së pari ju duhet të vendosni për skemën bazë. Meqenëse zakonisht dëshironi të merrni regjistra të renditur sipas kohës, duket logjike t'i ruani ato në këtë mënyrë. Nëse ka shumë kategori regjistrash dhe të gjitha janë të të njëjtit lloj, atëherë mund të bëni një kategori regjistrash si kolona e parë e çelësit kryesor - kjo do t'ju lejojë të keni një tabelë në vend të disa, gjë që do të jetë një plus i madh kur duke futur në ClickHouse (në serverët me hard disk, rekomandohet të futni të dhëna jo më shumë se ~ 1 herë në sekondë për të gjithë serverin).

Kjo do të thotë, ne kemi nevojë përafërsisht skemën e mëposhtme të tabelës:

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

Fatkeqësisht, nuk munda të gjeja menjëherë ndonjë burim të hapur me regjistra realistë që mund të kapja dhe shkarkoja, kështu që e mora këtë si shembull rishikime të produkteve nga Amazon deri në vitin 2015. Sigurisht, struktura e tyre nuk është saktësisht e njëjtë me atë të regjistrave të tekstit, por për qëllime ilustrimi kjo nuk është e rëndësishme.

udhëzime për ngarkimin e komenteve të Amazon në ClickHouse

Le të krijojmë një tabelë:

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

Në grupin e të dhënave të Amazon ka vetëm një datë për një rishikim, por nuk ka kohë të saktë, kështu që le t'i plotësojmë këto të dhëna me një rast.

Ju nuk duhet të shkarkoni të gjithë skedarët tsv dhe të kufizoni veten në ~ 10-20 të parët në mënyrë që të merrni një grup mjaft të madh të dhënash që nuk do të përshtaten në 16 GB RAM. Për të ngarkuar skedarët TSV përdora komandën e mëposhtme:

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

Në një disk standard të qëndrueshëm (i cili është një HDD) në Google Cloud me një madhësi prej 1000 GB (e mora këtë madhësi kryesisht në mënyrë që shpejtësia të ishte pak më e lartë, megjithëse ndoshta një SSD e madhësisë së kërkuar do të ishte më e lirë) ngarkimi shpejtësia ishte afërsisht ~ 75 MB/sek në 4 bërthama.

  • Duhet të bëj një rezervim që punoj në Google, por kam përdorur një llogari personale dhe ky artikull nuk ka të bëjë fare me punën time në kompani

Unë do të prodhoj të gjitha ilustrimet me këtë grup të dhënash të veçantë, pasi kjo është gjithçka që kisha në dorë.

Trego progresin e skanimit të të dhënave

Meqenëse në ClickHouse ne do të përdorim një skanim të plotë në një tabelë me regjistra dhe ky operacion mund të marrë një sasi të konsiderueshme kohe dhe mund të mos japë rezultate për një kohë të gjatë nëse gjenden pak ndeshje, këshillohet që të jeni në gjendje të tregoni ecuria e pyetjes derisa të merren rreshtat e parë me rezultatin. Për ta bërë këtë, ekziston një parametër në ndërfaqen HTTP që ju lejon të dërgoni përparimin në titujt HTTP: send_progress_in_http_headers=1. Fatkeqësisht, biblioteka standarde Go nuk mund t'i lexojë titujt ashtu siç merren, por ndërfaqja HTTP 1.0 (për të mos u ngatërruar me 1.1!) mbështetet nga ClickHouse, kështu që ju mund të hapni një lidhje të papërpunuar TCP me ClickHouse dhe ta dërgoni atje GET /?query=... HTTP/1.0nn dhe merrni titujt dhe trupin e përgjigjes pa asnjë ikje ose enkriptim, kështu që në këtë rast nuk kemi nevojë as të përdorim bibliotekën standarde.

Transmetimi i regjistrave nga ClickHouse

ClickHouse ka pasur optimizim për pyetjet me ORDER BY për një kohë relativisht të gjatë (që nga viti 2019?), kështu që një pyetje si

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

Menjëherë do të fillojë të kthejë linjat që kanë nënvargun "diçka" në mesazhin e tyre, pa pritur që skanimi të përfundojë.

Gjithashtu, do të ishte shumë i përshtatshëm nëse vetë ClickHouse do ta anulonte kërkesën kur lidhja me të u mbyll, por kjo nuk është sjellja e paracaktuar. Anulimi automatik i kërkesës mund të aktivizohet duke përdorur opsionin cancel_http_readonly_queries_on_client_close=1.

Trajtimi i saktë i SIGPIPE në Go

Kur ekzekutoni, le të themi, komandën some_cmd | head -n 10, saktësisht si komanda some_cmd ndalon ekzekutimin kur head zbriten 10 rreshta? Përgjigja është e thjeshtë: kur head përfundon, tubi mbyllet dhe stdout i komandës some_cmd fillon të tregojë, me kusht, "në askund". Kur some_cmd përpiqet të shkruajë në një tub të mbyllur, ai merr një sinjal SIGPIPE, i cili në heshtje përfundon programin si parazgjedhje.

Në Go kjo ndodh gjithashtu si parazgjedhje, por mbajtësi i sinjalit SIGPIPE gjithashtu printon "sinjal: SIGPIPE" ose një mesazh të ngjashëm në fund, dhe për të pastruar këtë mesazh, thjesht duhet ta trajtojmë vetë SIGPIPE ashtu siç duam, domethënë në heshtje. dalje:

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

Trego kontekstin e mesazhit

Shpesh ju dëshironi të shihni kontekstin në të cilin ndodhi ndonjë gabim (për shembull, cila kërkesë shkaktoi panik, ose cilat probleme të lidhura ishin të dukshme përpara përplasjes) dhe në grep Kjo bëhet duke përdorur opsionet -A, -B dhe -C, të cilat tregojnë numrin e caktuar të rreshtave përkatësisht pas, para dhe rreth mesazhit.

Fatkeqësisht, nuk kam gjetur një mënyrë të thjeshtë për të bërë të njëjtën gjë në ClickHouse, kështu që për të shfaqur kontekstin, një kërkesë shtesë si kjo dërgohet në secilën rresht të rezultatit (detajet varen nga renditja dhe nëse konteksti shfaqet më parë ose pas):

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

Meqenëse kërkesa dërgohet pothuajse menjëherë pasi ClickHouse të kthejë linjën përkatëse, ajo përfundon në cache dhe në përgjithësi kërkesa ekzekutohet mjaft shpejt dhe konsumon pak CPU (zakonisht kërkesa merr rreth ~6 ms në makinën time virtuale).

Shfaq mesazhe të reja në kohë reale

Për të shfaqur mesazhet hyrëse në (pothuajse) kohë reale, ne thjesht e ekzekutojmë kërkesën një herë në disa sekonda, duke kujtuar vulën e fundit kohore që kemi hasur më parë.

Shembuj të komandave

Si duken komandat tipike logscli në praktikë?

Nëse keni shkarkuar grupin e të dhënave të Amazon që përmenda në fillim të artikullit, mund të ekzekutoni komandat e mëposhtme:

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

Referencat

Kodi i shërbimeve (pa dokumentacion) është i disponueshëm në github në https://github.com/YuriyNasretdinov/logscli. Do të isha i lumtur të dëgjoja mendimet tuaja për idenë time për një ndërfaqe tastierë për shikimin e regjistrave bazuar në ClickHouse.

Burimi: www.habr.com

Shto një koment