Biz qeydlərə baxmaq üçün dünyada* ən rahat interfeysi inkişaf etdiririk

Biz qeydlərə baxmaq üçün dünyada* ən rahat interfeysi inkişaf etdiririk Əgər siz heç vaxt qeydlərə baxmaq üçün veb-interfeyslərdən istifadə etmisinizsə, o zaman yəqin ki, bu interfeyslərin bir qayda olaraq necə çətin və (çox vaxt) çox rahat və həssas olmadığını görmüsünüz. Bəzilərinə öyrəşə bilərsiniz, bəziləri tamamilə dəhşətlidir, amma mənə elə gəlir ki, bütün problemlərin səbəbi bizim loglara baxmaq vəzifəsinə yanlış yanaşmağımızdır: biz CLI (command line interface) olan veb interfeys yaratmağa çalışırıq. daha yaxşı işləyir. Mən şəxsən tail, grep, awk və başqaları ilə işləməkdə çox rahatam və buna görə də mənim üçün loglarla işləmək üçün ideal interfeys tail və grep-ə bənzər bir şey olardı, lakin bir çox serverlərdən gələn jurnalları oxumaq üçün də istifadə edilə bilər. Yəni, əlbəttə ki, onları ClickHouse-dan oxuyun!

*habra istifadəçisinin şəxsi fikrinə görə youROCK

logscli ilə tanış olun

İnterfeys üçün bir ad tapmadım və düzünü desəm, o, daha çox prototip şəklində mövcuddur, amma mənbə kodunu dərhal görmək istəyirsinizsə, xoş gəlmisiniz: https://github.com/YuriyNasretdinov/logscli (Seçilmiş Go kodunun 350 sətri).

İmkanları

Məqsədim tail/grep-ə öyrəşmiş insanlara tanış görünəcək bir interfeys yaratmaq, yəni aşağıdakıları dəstəkləmək idi:

  1. Filtrləmədən bütün qeydlərə baxın.
  2. Sabit alt sətirdən ibarət sətirləri tərk edin (bayraq -F у grep).
  3. Normal ifadəyə uyğun sətirləri buraxın (bayraq -E у grep).
  4. Defolt olaraq, baxış tərs xronoloji ardıcıllıqla aparılır, çünki ən son qeydlər adətən ilk növbədə maraq doğurur.
  5. Hər sətrin yanında konteksti göstərin (seçimlər -A, -B и -C у grep, müvafiq olaraq hər uyğun sətirdən əvvəl, sonra və ətrafında N sətir çap edin).
  6. Filtrlə və ya filtrləmədən real vaxt rejimində daxil olan qeydlərə baxın (əsasən tail -f | grep).
  7. İnterfeys uyğun olmalıdır less, head, tail və başqaları - standart olaraq, nəticələr onların sayına məhdudiyyət qoyulmadan qaytarılmalıdır; sətirlər istifadəçi onları almaqda maraqlı olduğu müddətcə axın kimi çap olunur; siqnal SIGPIPE onlar kimi səssizcə log axınını kəsməlidir tail, grep və digər UNIX utilitləri.

Tətbiq

Güman edirəm ki, siz artıq bir şəkildə logları ClickHouse-a necə çatdırmağı bilirsiniz. Əgər yoxsa, sınamağı məsləhət görürəm LSD и pişik evilog çatdırılması haqqında bu məqalə.

Əvvəlcə əsas sxemə qərar verməlisiniz. Siz adətən vaxta görə sıralanmış qeydləri almaq istədiyinizə görə onları bu şəkildə saxlamaq məntiqli görünür. Bir çox jurnal kateqoriyası varsa və hamısı eyni tipdədirsə, onda siz əsas açarın birinci sütunu kimi jurnal kateqoriyası yarada bilərsiniz - bu, bir neçə əvəzinə bir cədvələ sahib olmağa imkan verəcəkdir ki, bu da böyük bir artı olacaq. ClickHouse-a daxil etmək (sərt diskləri olan serverlərdə saniyədə ~1 dəfədən çox olmayan məlumat daxil etmək tövsiyə olunur) bütün server üçün).

Yəni təxminən aşağıdakı cədvəl sxeminə ehtiyacımız var:

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

Təəssüf ki, tuta biləcəyim və yükləyə biləcəyim real jurnalları olan açıq mənbələri dərhal tapa bilmədim, buna görə də bunu nümunə kimi götürdüm. 2015-ci ildən əvvəl Amazon-dan məhsulların rəyləri. Əlbəttə ki, onların strukturu mətn qeydləri ilə tam eyni deyil, lakin illüstrasiya məqsədləri üçün bu vacib deyil.

Amazon rəylərini ClickHouse-a yükləmək üçün təlimatlar

Cədvəl yaradaq:

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 məlumat dəstində yalnız nəzərdən keçirmək üçün bir tarix var, lakin dəqiq vaxt yoxdur, ona görə də bu məlumatları randonla dolduraq.

10 GB RAM-a sığmayan kifayət qədər böyük məlumat dəsti əldə etmək üçün bütün tsv fayllarını yükləməli və özünüzü ilk ~ 20-16 ilə məhdudlaşdırmaq lazım deyil. TSV fayllarını yükləmək üçün aşağıdakı əmrdən istifadə etdim:

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-da 1000 GB ölçüsü olan standart Persistent Diskdə (HDD olan) (bu ölçüsü əsasən sürətin bir az daha yüksək olması üçün götürdüm, baxmayaraq ki, bəlkə də tələb olunan ölçülü bir SSD daha ucuz olardı) yükləmə sürət 75 nüvədə təxminən ~ 4 MB/san idi.

  • Google-da işlədiyim üçün rezervasiya etməliyəm, lakin şəxsi hesabdan istifadə etdim və bu məqalənin şirkətdəki işimə heç bir aidiyyəti yoxdur.

Bütün illüstrasiyaları bu xüsusi məlumat dəsti ilə hazırlayacağam, çünki əlimdə olan budur.

Məlumat skanının gedişatını göstərin

ClickHouse-da qeydləri olan cədvəldə tam skandan istifadə edəcəyimizə və bu əməliyyat xeyli vaxt apara biləcəyinə və bir neçə uyğunluq tapılarsa, uzun müddət heç bir nəticə verməyə biləcəyinə görə, onu göstərə bilmək məsləhətdir nəticə ilə ilk sıralar alınana qədər sorğunun gedişatı. Bunun üçün HTTP interfeysində HTTP başlıqlarında tərəqqi göndərməyə imkan verən bir parametr var: send_progress_in_http_headers=1. Təəssüf ki, standart Go kitabxanası alındıqları kimi başlıqları oxuya bilmir, lakin HTTP 1.0 interfeysi (1.1 ilə qarışdırılmamalıdır!) ClickHouse tərəfindən dəstəklənir, ona görə də ClickHouse-a xam TCP bağlantısını aça və ora göndərə bilərsiniz. GET /?query=... HTTP/1.0nn və cavab başlıqlarını və gövdəsini heç bir qaçış və ya şifrələmə olmadan qəbul edin, belə ki, bu halda standart kitabxanadan istifadə etməyə belə ehtiyacımız yoxdur.

ClickHouse-dan axın qeydləri

ClickHouse nisbətən uzun müddətdir (2019-cu ildən bəri?) ORDER BY ilə sorğular üçün optimallaşdırmaya malikdir.

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

Skanın bitməsini gözləmədən mesajında ​​"bir şey" alt sətirləri olan sətirləri dərhal qaytarmağa başlayacaq.

Həmçinin, əlaqə bağlandıqda ClickHouse özü sorğunu ləğv etsəydi, çox rahat olardı, lakin bu, standart davranış deyil. Seçimdən istifadə edərək sorğunun avtomatik ləğvi aktivləşdirilə bilər cancel_http_readonly_queries_on_client_close=1.

Go-da SIGPIPE-nin düzgün idarə edilməsi

İcra edərkən, əmri deyin some_cmd | head -n 10, dəqiq necə əmr some_cmd zaman icranı dayandırır head 10 sətir çıxıldı? Cavab sadədir: nə vaxt head bitir, boru bağlanır və some_cmd əmrinin stdout işarəsi şərti olaraq “heç bir yerə” işarə etməyə başlayır. Nə vaxt some_cmd bağlı boruya yazmağa çalışır, o, SIGPIPE siqnalını qəbul edir, bu da proqramı səssizcə susmaya görə dayandırır.

Go-da bu, defolt olaraq baş verir, lakin SIGPIPE siqnal idarəedicisi də sonunda "siqnal: SIGPIPE" və ya oxşar mesajı çap edir və bu mesajı təmizləmək üçün biz sadəcə olaraq SIGPIPE-i özümüz istədiyimiz kimi idarə etməliyik, yəni səssizcə. çıxış:

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

Mesaj kontekstini göstərin

Tez-tez siz hansısa xətanın baş verdiyi konteksti (məsələn, hansı sorğunun panikaya səbəb olduğunu və ya qəzadan əvvəl hansı əlaqəli problemlərin göründüyünü) görmək istəyirsiniz. grep Bu, müvafiq olaraq mesajdan sonra, əvvəl və ətrafında müəyyən edilmiş sətir sayını göstərən -A, -B və -C seçimlərindən istifadə etməklə həyata keçirilir.

Təəssüf ki, ClickHouse-da eyni şeyi etmək üçün asan bir yol tapmadım, ona görə də konteksti göstərmək üçün nəticənin hər bir sətrinə bu kimi əlavə sorğu göndərilir (təfsilatlar çeşidləmədən və kontekstin daha əvvəl göstərilib-göstərilməməsindən asılıdır) və ya sonra):

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

Sorğu ClickHouse müvafiq sətri qaytardıqdan sonra demək olar ki, dərhal göndərildiyi üçün o, keş yaddaşa daxil olur və ümumiyyətlə sorğu kifayət qədər tez yerinə yetirilir və bir az CPU sərf edir (adətən sorğu mənim virtual maşınımda təxminən ~6 ms çəkir).

Yeni mesajları real vaxtda göstərin

Daxil olan mesajları (demək olar ki) real vaxt rejimində göstərmək üçün biz sadəcə olaraq sorğunu bir neçə saniyədə bir dəfə yerinə yetiririk, əvvəllər qarşılaşdığımız son vaxt damgasını xatırlayırıq.

Əmr nümunələri

Tipik logscli əmrləri praktikada nə kimi görünür?

Əgər məqalənin əvvəlində qeyd etdiyim Amazon məlumat dəstini yükləmisinizsə, aşağıdakı əmrləri işlədə bilərsiniz:

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

References

Kommunal kod (sənədlər olmadan) github-da mövcuddur https://github.com/YuriyNasretdinov/logscli. ClickHouse əsasında qeydlərə baxmaq üçün konsol interfeysi ideyam haqqında fikirlərinizi eşitməkdən məmnun olaram.

Mənbə: www.habr.com

Добавить комментарий