Мо интерфейси кулайтаринро дар ҷаҳон* барои дидани гузоришҳо таҳия карда истодаем

Мо интерфейси кулайтаринро дар ҷаҳон* барои дидани гузоришҳо таҳия карда истодаем Агар шумо боре аз веб-интерфейсҳо барои дидани гузоришҳо истифода карда бошед, пас шумо эҳтимол пай бурдед, ки чӣ тавр ин интерфейсҳо чун қоида душворанд ва (аксар вақт) чандон қулай ва ҷавобгӯ нестанд. Баъзеҳо шумо метавонед ба онҳо одат кунед, баъзеҳо комилан даҳшатноканд, аммо ба назарам, сабаби ҳамаи мушкилот дар он аст, ки мо ба вазифаи дидани гузоришҳо нодуруст муносибат мекунем: мо кӯшиш мекунем, ки веб-интерфейси CLI (интерфейси сатри фармон) эҷод кунем. бехтар кор мекунад. Ман шахсан барои кор бо tail, grep, awk ва дигарон хеле бароҳат ҳастам ва аз ин рӯ, барои ман интерфейси беҳтарин барои кор бо гузоришҳо як чизи шабеҳи tail ва grep хоҳад буд, аммо онро метавон барои хондани гузоришҳои аз бисёр серверҳо истифода бурд. Ин аст, албатта, онҳоро аз ClickHouse хонед!

*аз руи фикри шахсии корбари хабра youROCK

Вохӯред logscli

Ман барои интерфейси худ номе пайдо накардаам ва росташро гӯям, он дар шакли прототип вуҷуд дорад, аммо агар шумо хоҳед, ки фавран рамзи сарчашмаро бубинед, хуш омадед: https://github.com/YuriyNasretdinov/logscli (350 сатри рамзи Go интихобшуда).

Хусусиятҳои

Ҳадафи ман эҷод кардани интерфейсе буд, ки ба онҳое, ки ба tail/grep одат кардаанд, шинос шавад, яъне дастгирӣ кардани чизҳои зерин:

  1. Ҳама гузоришҳоро бидуни филтр дидан.
  2. Сатрҳоро тарк кунед, ки дорои зерсатри собит (парчам -F у grep).
  3. Хатҳоеро тарк кунед, ки ба ифодаи муқаррарӣ мувофиқат кунанд (парчам -E у grep).
  4. Бо нобаёнӣ, тамошо бо тартиби баръакси хронологӣ сурат мегирад, зеро гузоришҳои охирин одатан аввал таваҷҷӯҳ доранд.
  5. Дар паҳлӯи ҳар як сатр контекстро нишон диҳед (параметрҳо -A, -B и -C у grep, чопи N сатрҳо мутаносибан пеш, баъд ва дар атрофи ҳар як хати мувофиқ).
  6. Намоиши гузоришҳои воридотӣ дар вақти воқеӣ бо филтр ё бидуни филтр (аслан tail -f | grep).
  7. Интерфейс бояд бо он мувофиқ бошад less, head, tail ва дигарон - бо нобаёнӣ, натиҷаҳо бояд бидуни маҳдудияти шумораи онҳо баргардонида шаванд; сатрҳо ҳамчун ҷараён чоп карда мешаванд, то даме ки корбар ба гирифтани онҳо таваҷҷӯҳ дорад; сигнал SIGPIPE бояд бесадо ҷараёнро қатъ кунад, ҳамон тавре ки онҳо мекунанд tail, grep ва дигар утилитҳои UNIX.

Реализация

Ман тахмин мекунам, ки шумо аллакай медонед, ки чӣ гуна гузоришҳоро ба ClickHouse интиқол диҳед. Агар не, ман тавсия медиҳам, ки онро санҷед lsd и гурбахона, инчунин ин мақола дар бораи интиқоли гузориш.

Аввал шумо бояд дар бораи нақшаи асосӣ қарор қабул кунед. Азбаски шумо одатан мехоҳед гузоришҳоро аз рӯи вақт ҷудо кунед, нигоҳ доштани онҳо мантиқӣ ба назар мерасад. Агар категорияҳои зиёди гузоришҳо вуҷуд дошта бошанд ва ҳамаашон як навъ бошанд, пас шумо метавонед ҳамчун сутуни якуми калиди ибтидоӣ категорияи гузоришҳо созед - ин ба шумо имкон медиҳад, ки ба ҷои якчанд ҷадвал як ҷадвал дошта бошед, вақте ки ин як плюси калон хоҳад буд. ворид кардани ClickHouse (дар серверҳои дорои дискҳои сахт тавсия дода мешавад, ки маълумот дар як сония на бештар аз ~1 маротиба ворид карда шавад. барои тамоми сервер).

Яъне, ба мо тақрибан схемаи ҷадвали зерин лозим аст:

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

Мутаассифона, ман дарҳол манбаи кушодаи дорои гузоришҳои воқеиро пайдо карда натавонистам, ки онҳоро гирифта ва зеркашӣ карда метавонам, бинобар ин ман инро ҳамчун намуна гирифтам. баррасиҳои маҳсулот аз Amazon то соли 2015. Албатта, сохтори онҳо бо сохтори сабтҳои матнӣ комилан якхела нест, аммо барои мисол ин муҳим нест.

дастурҳо барои бор кардани баррасиҳои Amazon ба ClickHouse

Биёед ҷадвал эҷод кунем:

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 танҳо санаи барраси мавҷуд аст, аммо вақти дақиқ вуҷуд надорад, аз ин рӯ биёед ин маълумотро бо рандон пур кунем.

Ба шумо лозим нест, ки ҳама файлҳои tsv-ро зеркашӣ кунед ва худро бо аввалин ~ 10-20 маҳдуд кунед, то маҷмӯи хеле калони маълумоте, ки ба 16 ГБ RAM мувофиқат намекунад. Барои бор кардани файлҳои TSV ман фармони зеринро истифода кардам:

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

Дар диски стандартии доимӣ (ки HDD аст) дар Google Cloud бо андозаи 1000 ГБ (ман ин андозаро асосан барои он гирифтам, ки суръат каме баландтар бошад, гарчанде ки шояд SSD-и андозаи лозима арзонтар мебуд) боргузорӣ суръат дар 75 ядро ​​​​тақрибан ~ 4 МБ / сония буд.

  • Ман бояд фармоиш диҳам, ки ман дар Google кор мекунам, аммо ман ҳисоби шахсиро истифода кардам ва ин мақола ба кори ман дар ширкат рабте надорад

Ман ҳама тасвирҳоро бо ин маҷмӯаи мушаххас таҳия мекунам, зеро ин ҳама чизест, ки ман дар даст доштам.

Пешрафти сканкунии маълумотро нишон диҳед

Азбаски дар ClickHouse мо сканкунии пурраро дар ҷадвали дорои гузоришҳо истифода хоҳем кард ва ин амалиёт метавонад вақти зиёдро талаб кунад ва дар сурати пайдо шудани якчанд мувофиқатҳо дар муддати тӯлонӣ ягон натиҷа надиҳад, тавсия дода мешавад, ки нишон дода тавонистани пешрафти дархост то гирифтани сатрҳои аввал бо натиҷа. Барои ин, дар интерфейси HTTP як параметр мавҷуд аст, ки ба шумо имкон медиҳад пешрафтро дар сарлавҳаҳои HTTP ирсол кунед: send_progress_in_http_headers=1. Мутаассифона, китобхонаи стандартии Go сарлавҳаҳоро ҳангоми қабули онҳо хонда наметавонад, аммо интерфейси HTTP 1.0 (бо 1.1 омехта нашавад!) аз ҷониби ClickHouse дастгирӣ карда мешавад, аз ин рӯ шумо метавонед пайвасти хоми TCP-ро ба ClickHouse кушоед ва ба он ҷо фиристед. GET /?query=... HTTP/1.0nn ва сарлавҳаҳо ва баданро бидуни фирор ё рамзгузорӣ қабул кунед, бинобар ин дар ин ҳолат ба мо ҳатто лозим нест, ки китобхонаи стандартиро истифода барем.

Ҷараёни гузоришҳо аз ClickHouse

ClickHouse барои пурсишҳо бо ORDER BY муддати нисбатан тӯлонӣ оптимизатсия дошт (аз соли 2019?), Пас дархост ба монанди

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

Он фавран баргардонидани сатрҳоеро оғоз мекунад, ки дар паёмашон зерсатри "чизе" доранд, бидуни интизории анҷоми скан.

Инчунин, хеле қулай мебуд, агар худи ClickHouse дархостро ҳангоми баста шудани пайвастшавӣ ба он бекор кунад, аммо ин рафтори пешфарз нест. Бо истифода аз опсия бекоркунии автоматии дархостро фаъол кардан мумкин аст cancel_http_readonly_queries_on_client_close=1.

Муносибати дурусти SIGPIPE дар Go

Вақте ки шумо иҷро мекунед, бигӯед, ки фармон some_cmd | head -n 10, махз чй тавр фармон some_cmd вақте ки иҷроишро қатъ мекунад head 10 сатр тар карда шуд? Ҷавоб оддӣ аст: кай head ба охир мерасад, қубур баста мешавад ва stdout-и фармони some_cmd ба шартан "ба ҳеҷ ҷо" ишора мекунад. Кай some_cmd кӯшиш мекунад, ки ба қубури пӯшида нависад, он сигнали SIGPIPE -ро қабул мекунад, ки барномаро бо нобаёнӣ хомӯшона қатъ мекунад.

Дар Go ин низ ба таври нобаёнӣ рух медиҳад, аммо коркардкунандаи сигнали SIGPIPE инчунин дар охир "сигнал: SIGPIPE" ё паёми шабеҳро чоп мекунад ва барои тоза кардани ин паём мо бояд танҳо SIGPIPE-ро худамон тавре, ки мехоҳем, иҷро кунем, яъне танҳо хомӯшона. Баромадгоҳ:

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

Контексти паёмро нишон диҳед

Аксар вақт шумо мехоҳед контекстеро бинед, ки дар он хатогӣ рух додааст (масалан, кадом дархост боиси воҳима шудааст ё кадом мушкилоти марбут пеш аз садама намоён буданд) ва дар grep Ин бо истифода аз имконоти -A, -B ва -C анҷом дода мешавад, ки шумораи муайяни сатрҳоро мутаносибан пас аз, пеш ва атрофи паём нишон медиҳанд.

Мутаассифона, ман роҳи осони иҷрои ҳамин корро дар ClickHouse наёфтам, аз ин рӯ барои намоиш додани контекст дархости иловагӣ ба монанди ин ба ҳар як сатри натиҷа фиристода мешавад (тафсилот аз ҷудокунӣ ва оё контекст қаблан нишон дода шудааст, вобаста аст) ё баъд аз):

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

Азбаски дархост қариб дарҳол пас аз баргардонидани ClickHouse сатри мувофиқ фиристода мешавад, он дар кэш ба охир мерасад ва дар маҷмӯъ дархост хеле зуд иҷро мешавад ва каме CPU-ро сарф мекунад (одатан дархост дар мошини виртуалии ман тақрибан ~6 мс мегирад).

Паёмҳои навро дар вақти воқеӣ нишон диҳед

Барои нишон додани паёмҳои воридотӣ дар (қариб) дар вақти воқеӣ, мо танҳо як маротиба дар як чанд сония дархостро иҷро мекунем ва тамғаи охиринро, ки қаблан дучор шуда будем, ба ёд меорем.

Намунаҳои фармон

Фармонҳои маъмулии logscli дар амал чӣ гунаанд?

Агар шумо маҷмӯаи маълумоти Amazon-ро, ки ман дар аввали мақола зикр кардам, зеркашӣ карда бошед, шумо метавонед фармонҳои зеринро иҷро кунед:

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

мурожиат

Рамзи хидматрасонӣ (бе ҳуҷҷатҳо) дар github дастрас аст https://github.com/YuriyNasretdinov/logscli. Ман шодам, ки андешаҳои шуморо дар бораи идеяи ман дар бораи интерфейси консол барои дидани гузоришҳо дар асоси ClickHouse бишнавам.

Манбаъ: will.com

Илова Эзоҳ