Біз журналдарды қарауға арналған әлемдегі* ең ыңғайлы интерфейсті жасап жатырмыз

Біз журналдарды қарауға арналған әлемдегі* ең ыңғайлы интерфейсті жасап жатырмыз Егер сіз журналдарды қарау үшін веб-интерфейстерді бұрыннан пайдаланған болсаңыз, онда сіз әдетте бұл интерфейстердің қаншалықты ауыр және (көбінесе) өте ыңғайлы және сезімтал емес екенін байқаған боларсыз. Кейбіреулеріне үйреніп кетуге болады, кейбіреулері мүлдем қорқынышты, бірақ менің ойымша, барлық проблемалардың себебі біз журналдарды қарау міндетіне дұрыс емес қараймыз: біз CLI (пәрмен жолы интерфейсі) болатын веб-интерфейс жасауға тырысамыз. жақсырақ жұмыс істейді. Мен tail, grep, awk және басқалармен жұмыс істеуге өте ыңғайлымын, сондықтан мен үшін журналдармен жұмыс істеу үшін тамаша интерфейс tail және grep сияқты нәрсе болар еді, бірақ оны көптеген серверлерден келген журналдарды оқу үшін де қолдануға болады. Бұл, әрине, оларды ClickHouse сайтынан оқыңыз!

*хабра қолданушының жеке пікірі бойынша youROCK

logscli танысыңыз

Мен интерфейсімнің атауын ойлап таппадым, шынымды айтсам, ол прототип түрінде бар, бірақ бастапқы кодты бірден көргіңіз келсе, қош келдіңіз: https://github.com/YuriyNasretdinov/logscli (Таңдалған Go кодының 350 жолы).

Ерекшеліктері

Менің мақсатым 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-қа қалай жеткізу керектігін білесіз. Егер жоқ болса, мен оны сынап көруге кеңес беремін лсд и котенка, және де журналды жеткізу туралы осы мақала.

Алдымен сіз базалық схеманы шешуіңіз керек. Әдетте уақыт бойынша сұрыпталған журналдарды алғыңыз келетіндіктен, оларды осылай сақтау қисынды болып көрінеді. Егер журнал санаттары көп болса және олардың барлығы бір типті болса, онда сіз журнал санатын негізгі кілттің бірінші бағанына айналдыра аласыз - бұл бірнеше кестенің орнына бір кестеге ие болуға мүмкіндік береді, бұл үлкен плюс ClickHouse ішіне енгізу (қатты дискілері бар серверлерде деректерді секундына ~1 реттен көп емес енгізу ұсынылады. бүкіл сервер үшін).

Яғни, бізге шамамен келесі кесте схемасы қажет:

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

Өкінішке орай, мен басып алуға және жүктеп алуға болатын нақты журналдары бар ашық көздерді бірден таба алмадым, сондықтан мен оны мысал ретінде алдым. 2015 жылға дейінгі Amazon өнімдеріне шолулар. Әрине, олардың құрылымы мәтіндік журналдармен бірдей емес, бірақ иллюстрация үшін бұл маңызды емес.

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 деректер жинағында тек шолу күні бар, бірақ нақты уақыт жоқ, сондықтан бұл деректерді рандонмен толтырайық.

10 ГБ жедел жадыға сыймайтын деректердің жеткілікті үлкен жинағын алу үшін барлық tsv файлдарын жүктеп алып, алғашқы ~20-16-мен шектелудің қажеті жоқ. 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

Google Cloud жүйесіндегі 1000 ГБ өлшемі бар стандартты тұрақты дискіде (бұл HDD болып табылады) (мен бұл өлшемді негізінен жылдамдық сәл жоғарырақ болу үшін алдым, бірақ қажет өлшемдегі SSD арзанырақ болар еді) жүктеп салу жылдамдығы 75 ядрода шамамен ~ 4 МБ/сек болды.

  • Мен Google-да жұмыс істейтінімді брондауым керек, бірақ мен жеке есептік жазбаны пайдаландым және бұл мақаланың компаниядағы жұмысыма ешқандай қатысы жоқ.

Мен барлық иллюстрацияларды осы нақты деректер жиынтығымен жасаймын, өйткені бұл менің қолымда болған нәрсе.

Деректерді сканерлеу барысын көрсету

ClickHouse бағдарламасында біз журналдары бар кестеде толық сканерлеуді қолданатындықтан және бұл операция айтарлықтай уақытты алуы мүмкін және бірнеше сәйкестік табылса, ұзақ уақыт нәтиже бермеуі мүмкін болғандықтан, нәтижесі бар бірінші жолдар алынғанша сұраудың орындалу барысы. Мұны істеу үшін HTTP интерфейсінде HTTP тақырыптарында прогресті жіберуге мүмкіндік беретін параметр бар: send_progress_in_http_headers=1. Өкінішке орай, стандартты Go кітапханасы тақырыптарды қабылданған кезде оқи алмайды, бірақ HTTP 1.0 интерфейсін (1.1 нұсқасымен шатастырмау керек!) ClickHouse қолдайды, сондықтан ClickHouse қолданбасына өңделмеген TCP қосылымын ашып, оны сол жерге жіберуге болады. 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.

Go жүйесінде SIGPIPE дұрыс өңдеу

Сіз орындаған кезде, айталық, команда some_cmd | head -n 10, дәл қалай команда some_cmd орындалуды тоқтатады head 10 жолды шегерді? Жауап қарапайым: қашан head аяқталады, құбыр жабылады және some_cmd пәрменінің stdout шартты түрде «ешқайда» дегенді көрсете бастайды. Қашан 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 негізінде журналдарды қарауға арналған консоль интерфейсі туралы менің идеям туралы ойларыңызды естуге қуаныштымын.

Ақпарат көзі: www.habr.com

пікір қалдыру