Biz jurnallarni ko'rish uchun dunyodagi eng qulay interfeysni* ishlab chiqmoqdamiz

Biz jurnallarni ko'rish uchun dunyodagi eng qulay interfeysni* ishlab chiqmoqdamiz Agar siz hech qachon jurnallarni ko'rish uchun veb-interfeyslardan foydalangan bo'lsangiz, ehtimol siz ushbu interfeyslar qanday qilib noqulay va (ko'pincha) juda qulay va sezgir emasligini payqadingiz. Ba'zilariga ko'nikishingiz mumkin, ba'zilari esa mutlaqo dahshatli, lekin menimcha, barcha muammolarning sababi biz jurnallarni ko'rish vazifasiga noto'g'ri yondashamiz: biz CLI (buyruqlar qatori interfeysi) mavjud bo'lgan veb-interfeysni yaratishga harakat qilamiz. yaxshiroq ishlaydi. Shaxsan men tail, grep, awk va boshqalar bilan ishlashda juda qulayman, shuning uchun men uchun jurnallar bilan ishlash uchun ideal interfeys tail va grepga o'xshash narsa bo'ladi, lekin u ko'plab serverlardan kelgan jurnallarni o'qish uchun ham ishlatilishi mumkin. Bu, albatta, ularni ClickHouse-dan o'qing!

*habra foydalanuvchisining shaxsiy fikriga ko'ra youROCK

logscli bilan tanishing

Men interfeysim uchun nom topmadim va rostini aytsam, u prototip ko'rinishida mavjud, ammo agar siz manba kodini darhol ko'rishni istasangiz, xush kelibsiz: https://github.com/YuriyNasretdinov/logscli (tanlangan Go kodining 350 qatori).

Xususiyatlar

Mening maqsadim tail/grepga odatlanganlarga tanish bo'lib tuyuladigan interfeys yaratish, ya'ni quyidagi narsalarni qo'llab-quvvatlash edi:

  1. Barcha jurnallarni filtrlashsiz ko'ring.
  2. Ruxsat etilgan pastki qatorni o'z ichiga olgan qatorlarni qoldiring (bayroq -F у grep).
  3. Oddiy iboraga mos keladigan qatorlarni qoldiring (bayroq -E у grep).
  4. Odatiy bo'lib, ko'rish teskari xronologik tartibda amalga oshiriladi, chunki eng so'nggi jurnallar odatda birinchi navbatda qiziqish uyg'otadi.
  5. Har bir satr yonida kontekstni ko'rsatish (variantlar -A, -B и -C у grep, mos ravishda har bir mos keladigan satrdan oldin, keyin va atrofida N qatorni chop etish).
  6. Kiruvchi jurnallarni real vaqtda filtrlash yoki filtrlashsiz ko'rish (asosan tail -f | grep).
  7. Interfeys mos bo'lishi kerak less, head, tail va boshqalar - sukut bo'yicha natijalar ularning soni bo'yicha cheklovlarsiz qaytarilishi kerak; foydalanuvchi ularni qabul qilishdan manfaatdor ekan, chiziqlar oqim sifatida chop etiladi; signal SIGPIPE xuddi ular kabi, jurnal oqimini jimgina to'xtatishi kerak tail, grep va boshqa UNIX utilitlari.

Реализация

O'ylaymanki, siz qandaydir tarzda ClickHouse-ga jurnallarni qanday etkazib berishni bilasiz. Agar yo'q bo'lsa, men sinab ko'rishni maslahat beraman lsd и mushukchalar uyi, shuningdek jurnalni yetkazib berish haqida ushbu maqola.

Avval siz asosiy sxema haqida qaror qabul qilishingiz kerak. Odatda vaqt bo'yicha tartiblangan jurnallarni olishni xohlayotganingiz uchun ularni shunday saqlash mantiqiy ko'rinadi. Agar jurnal toifalari ko'p bo'lsa va ularning barchasi bir xil bo'lsa, unda siz asosiy kalitning birinchi ustuni sifatida jurnal toifasini yaratishingiz mumkin - bu sizga bir nechta jadval o'rniga bitta jadvalga ega bo'lishga imkon beradi, bu esa katta plyus bo'ladi. ClickHouse-ga kiritish (qattiq disklari bo'lgan serverlarda ma'lumotlarni sekundiga ~1 martadan ko'p bo'lmagan holda kiritish tavsiya etiladi. butun server uchun).

Ya'ni, bizga taxminan quyidagi jadval sxemasi kerak:

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

Afsuski, men qo'lga olishim va yuklab olishim mumkin bo'lgan haqiqiy jurnallar bilan ochiq manbalarni darhol topa olmadim, shuning uchun men buni misol sifatida oldim. 2015 yilgacha Amazon mahsulotlarining sharhlari. Albatta, ularning tuzilishi matn jurnallari bilan mutlaqo bir xil emas, lekin illyustratsiya uchun bu muhim emas.

Amazon sharhlarini ClickHouse-ga yuklash bo'yicha ko'rsatmalar

Keling, jadval tuzamiz:

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 ma'lumotlar to'plamida faqat ko'rib chiqish sanasi mavjud, ammo aniq vaqt yo'q, shuning uchun ushbu ma'lumotlarni randon bilan to'ldiramiz.

10 GB operativ xotiraga sig'maydigan juda katta ma'lumotlar to'plamini olish uchun barcha tsv fayllarini yuklab olishingiz va o'zingizni birinchi ~ 20-16 bilan cheklashingiz shart emas. TSV fayllarini yuklash uchun men quyidagi buyruqdan foydalandim:

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-dagi 1000 Gb o'lchamli standart doimiy diskda (bu HDD) (men bu o'lchamni tezlikni biroz yuqoriroq qilish uchun oldim, lekin kerakli o'lchamdagi SSD arzonroq bo'lar edi) yuklash tezligi 75 yadroda taxminan ~ 4 MB/sek edi.

  • Men Google'da ishlayotganimni band qilishim kerak, lekin men shaxsiy hisobdan foydalanganman va bu maqola kompaniyadagi ishimga hech qanday aloqasi yo'q.

Men ushbu maxsus ma'lumotlar to'plami bilan barcha rasmlarni ishlab chiqaraman, chunki bu mening qo'limda bor edi.

Maʼlumotlarni skanerlash jarayonini koʻrsatish

ClickHouse-da biz jurnallar bilan jadvalni to'liq skanerlashdan foydalanamiz va bu operatsiya juda ko'p vaqt talab qilishi va bir nechta moslik topilsa, uzoq vaqt davomida hech qanday natija bermasligi mumkin, shuning uchun uni ko'rsatish tavsiya etiladi. natijaga ega bo'lgan birinchi qatorlar olinmaguncha so'rovning borishi. Buning uchun HTTP interfeysida HTTP sarlavhalarida progressni yuborish imkonini beruvchi parametr mavjud: send_progress_in_http_headers=1. Afsuski, standart Go kutubxonasi sarlavhalarni qabul qilinganda o'qiy olmaydi, lekin HTTP 1.0 interfeysi (1.1 bilan adashtirmaslik kerak!) ClickHouse tomonidan qo'llab-quvvatlanadi, shuning uchun siz ClickHouse-ga xom TCP ulanishini ochib, uni u erga yuborishingiz mumkin. GET /?query=... HTTP/1.0nn va javob sarlavhalari va tanasini hech qanday qochish yoki shifrlashsiz qabul qiling, shuning uchun bu holda biz standart kutubxonadan foydalanishimiz shart emas.

ClickHouse-dan oqim jurnallari

ClickHouse nisbatan uzoq vaqt davomida (2019 yildan beri?) ORDER BY bilan soʻrovlar uchun optimallashtirishga ega boʻlgan.

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

U skanerlash tugashini kutmasdan, xabarida "bir narsa" pastki qatoriga ega bo'lgan satrlarni darhol qaytarishni boshlaydi.

Bundan tashqari, agar ClickHouse o'zi unga ulanish yopilganida so'rovni bekor qilsa, bu juda qulay bo'lar edi, lekin bu standart xatti-harakatlar emas. Avtomatik so'rovni bekor qilish opsiyasi yordamida yoqilishi mumkin cancel_http_readonly_queries_on_client_close=1.

Go-da SIGPIPE-dan to'g'ri foydalanish

Siz bajarganingizda, aytaylik, buyruq some_cmd | head -n 10, aniq qanday buyruq some_cmd qachon bajarilishini to'xtatadi head 10 qatorni ayirdingizmi? Javob oddiy: qachon head tugaydi, quvur yopiladi va some_cmd buyrug'ining stdout shartli ravishda "hech qaerga" ishora qila boshlaydi. Qachon some_cmd yopiq quvurga yozishga harakat qiladi, u SIGPIPE signalini oladi, bu esa dasturni sukut bo'yicha jimgina tugatadi.

Go'da bu ham sukut bo'yicha sodir bo'ladi, lekin SIGPIPE signal ishlovchisi ham oxirida "signal: SIGPIPE" yoki shunga o'xshash xabarni chop etadi va bu xabarni tozalash uchun biz SIGPIPEni o'zimiz xohlagan tarzda, ya'ni jimgina ishlov berishimiz kerak. Chiqish:

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

Xabar kontekstini ko'rsatish

Ko'pincha siz qandaydir xatolik yuzaga kelgan kontekstni ko'rishni xohlaysiz (masalan, qaysi so'rov vahima qo'zg'atdi yoki buzilishdan oldin qanday muammolar paydo bo'lgan) grep Bu -A, -B va -C parametrlari yordamida amalga oshiriladi, ular mos ravishda xabardan keyin, oldin va atrofida belgilangan qatorlar sonini ko'rsatadi.

Afsuski, men ClickHouse-da xuddi shunday qilishning oson yo'lini topa olmadim, shuning uchun kontekstni ko'rsatish uchun natijaning har bir satriga shunga o'xshash qo'shimcha so'rov yuboriladi (tafsilotlar saralash va kontekstning avval ko'rsatilishiga bog'liq. yoki keyin):

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

So'rov ClickHouse mos keladigan qatorni qaytargandan so'ng deyarli darhol yuborilganligi sababli, u keshda tugaydi va umuman so'rov juda tez bajariladi va ozgina CPU iste'mol qiladi (odatda so'rov mening virtual mashinamda ~6 milodiy vaqtni oladi).

Haqiqiy vaqtda yangi xabarlarni ko'rsatish

Kiruvchi xabarlarni (deyarli) real vaqtda ko'rsatish uchun biz so'rovni bir necha soniyada bir marta bajaramiz, avval duch kelgan oxirgi vaqt tamg'asini eslaymiz.

Buyruqlar misollari

Oddiy logscli buyruqlari amalda qanday ko'rinishga ega?

Agar siz maqolaning boshida aytib o'tgan Amazon ma'lumotlar to'plamini yuklab olgan bo'lsangiz, quyidagi buyruqlarni bajarishingiz mumkin:

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

Manbalar

Yordamchi dastur kodi (hujjatlarsiz) github da mavjud https://github.com/YuriyNasretdinov/logscli. ClickHouse-ga asoslangan jurnallarni ko'rish uchun konsol interfeysi haqidagi g'oyam haqidagi fikringizni eshitishdan xursand bo'lardim.

Manba: www.habr.com

a Izoh qo'shish