Биз журналдарды көрүү үчүн дүйнөдөгү эң ыңгайлуу интерфейсти иштеп чыгуудабыз

Биз журналдарды көрүү үчүн дүйнөдөгү эң ыңгайлуу интерфейсти иштеп чыгуудабыз Эгер сиз журналдарды көрүү үчүн веб-интерфейстерди колдонгон болсоңуз, анда бул интерфейстер, эреже катары, кандайча түйшүктүү жана (көбүнчө) абдан ыңгайлуу жана жооп бербегендигин байкаган чыгарсыз. Кээ бирлерине көнүп кетсеңиз болот, кээ бирлери таптакыр коркунучтуу, бирок менин оюмча, бардык көйгөйлөрдүн себеби биз журналдарды көрүү милдетине туура эмес мамиле жасап жатканыбызда: биз CLI (буйрук сабынын интерфейси) болгон веб-интерфейс түзүүгө аракет кылабыз. жакшыраак иштейт. Жеке мен tail, grep, awk жана башкалар менен иштөө абдан ыңгайлуумун, ошондуктан мен үчүн журналдар менен иштөө үчүн идеалдуу интерфейс tail жана grepге окшош нерсе болмок, бирок аны көптөгөн серверлерден келген журналдарды окуу үчүн колдонсо болот. Бул, албетте, аларды ClickHouseдан оку!

*habra колдонуучунун жеке пикири боюнча yourROCK

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 Булуттагы 1000 ГБ өлчөмүндөгү стандарттуу Persistent Disk (бул 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 негизинде журналдарды көрүү үчүн консолдук интерфейс боюнча менин идеям боюнча сиздин пикириңизди угууга кубанычтамын.

Source: www.habr.com

Комментарий кошуу