Ако сте икада користили веб интерфејсе за преглед дневника, онда сте вероватно приметили како су, по правилу, ови интерфејси гломазни и (често) не баш згодни и реагујући. На неке се можете навићи, на неке су апсолутно ужасне, али чини ми се да је разлог свих проблема то што задатку прегледа евиденције приступамо погрешно: покушавамо да креирамо веб интерфејс где ће ЦЛИ (интерфејс командне линије) ради боље. Мени лично је веома пријатно да радим са таил, греп, авк и другима, и стога би за мене идеалан интерфејс за рад са логовима био нешто слично таил и греп, али који би такође могао да се користи за читање дневника који долазе са многих сервера. То је, наравно, прочитајте их из ЦлицкХоусе-а!
*према личном мишљењу корисника хабра
Упознајте логсцли
Нисам смислио име за свој интерфејс, и, да будем искрен, он пре постоји у облику прототипа, али ако желите одмах да видите изворни код, онда сте добродошли: (350 линија изабраног Го кода).
Могућности
Мој циљ је био да направим интерфејс који ће изгледати познато онима који су навикли на таил/греп, односно да подржава следеће ствари:
- Погледајте све евиденције, без филтрирања.
- Оставите редове који садрже фиксни подниз (застава
-Fуgrep). - Оставите редове који одговарају регуларном изразу (застава
-Eуgrep). - Подразумевано, гледање је обрнутим хронолошким редоследом, пошто су најновији дневники обично први од интереса.
- Прикажи контекст поред сваке линије (опције
-A,-Bи-Cуgrep, штампајући Н редова пре, после и око сваке одговарајуће линије, респективно). - Прегледајте долазне евиденције у реалном времену, са или без филтрирања (у суштини
tail -f | grep). - Интерфејс мора бити компатибилан са
less,head,tailи други - подразумевано, резултати треба да се враћају без ограничења њиховог броја; линије се штампају као ток све док је корисник заинтересован да их прими; сигналSIGPIPEтребало би да тихо прекину стримовање дневника, баш као што то радеtail,grepи друге УНИКС услужне програме.
Имплементација
Претпостављам да већ некако знате како да испоручите дневнике ЦлицкХоусе-у. Ако не, препоручујем да пробате и И .
Прво морате одлучити о основној шеми. Пошто обично желите да примате евиденције сортиране по времену, чини се логичним да их тако складиштите. Ако постоји много категорија дневника и све су истог типа, онда можете да направите категорију дневника као прву колону примарног кључа - то ће вам омогућити да имате једну табелу уместо неколико, што ће бити велики плус када убацивање у ЦлицкХоусе (на серверима са чврстим дисковима, препоручује се уметање података не више од ~1 пута у секунди за цео сервер).
То јест, потребна нам је отприлике следећа шема табеле:
CREATE TABLE logs(
category LowCardinality(String), -- категория логов (опционально)
time DateTime, -- время события
millis UInt16, -- миллисекунды (могут быть и микросекунды, и т.д.): рекомендуется хранить, если событий много, чтобы было легче различать события между собой
..., -- ваши собственные поля, например имя сервера, уровень логирования, и так далее
message String -- текст сообщения
) ENGINE=MergeTree()
ORDER BY (category, time, millis)
Нажалост, нисам могао одмах да пронађем ниједан отворени извор са реалистичним евиденцијама које бих могао да узмем и преузмем, па сам узео ово као пример . Наравно, њихова структура није потпуно иста као код текстуалних дневника, али за илустрацију ово није важно.
упутства за постављање Амазон рецензија на ЦлицкХоусе
Хајде да направимо табелу:
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
У Амазон скупу података постоји само датум за преглед, али не постоји тачно време, па хајде да попунимо ове податке насумично.
Не морате да преузимате све тсв датотеке и ограничите се на првих ~10-20 да бисте добили прилично велики скуп података који неће стати у 16 ГБ РАМ-а. За отпремање ТСВ датотека користио сам следећу команду:
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
На стандардном трајном диску (који је ХДД) у Гоогле Цлоуд-у величине 1000 ГБ (узео сам ову величину углавном да би брзина била мало већа, иако би можда ССД потребне величине био јефтинији) отпремање брзина је била приближно ~ 75 МБ/сец на 4 језгра.
- Морам да резервишем да радим у Гоогле-у, али користио сам лични налог и овај чланак нема никакве везе са мојим радом у компанији
Направићу све илустрације са овим одређеним скупом података, пошто је то све што сам имао при руци.
Прикажи напредак скенирања података
Пошто ћемо у ЦлицкХоусе-у користити потпуно скенирање табеле са евиденцијама, а ова операција може да потраје значајно време и можда неће дати никакве резултате дуго времена ако се пронађе неколико подударања, препоручљиво је да можете да прикажете напредак упита док се не приме први редови са резултатом. Да бисте то урадили, постоји параметар у ХТТП интерфејсу који вам омогућава да пошаљете напредак у ХТТП заглављима: send_progress_in_http_headers=1. Нажалост, стандардна Го библиотека не може да чита заглавља када су примљена, али ЦлицкХоусе подржава ХТТП 1.0 интерфејс (не треба га мешати са 1.1!), тако да можете да отворите сирову ТЦП везу са ЦлицкХоусе и пошаљете је тамо GET /?query=... HTTP/1.0nn и примимо заглавља и тело одговора без икаквог избегавања или шифровања, тако да у овом случају не морамо ни да користимо стандардну библиотеку.
Стреаминг евиденције са ЦлицкХоусе-а
ЦлицкХоусе има оптимизацију за упите са ОРДЕР БИ релативно дуго (од 2019?), тако да упит попут
SELECT time, millis, message
FROM logs
WHERE message LIKE '%something%'
ORDER BY time DESC, millis DESC
Одмах ће почети да враћа линије које имају подниз „нешто“ у својој поруци, без чекања да се скенирање заврши.
Такође, било би веома згодно да сам ЦлицкХоусе поништи захтев када је веза са њим затворена, али то није подразумевано понашање. Аутоматско отказивање захтева се може омогућити коришћењем опције cancel_http_readonly_queries_on_client_close=1.
Исправно руковање СИГПИПЕ-ом у Го
Када извршите, рецимо, команду some_cmd | head -n 10, тачно како је команда some_cmd зауставља извршење када head одузео 10 редова? Одговор је једноставан: када head завршава, цев се затвара, а стдоут команде соме_цмд почиње да показује, условно, „нигде“. Када some_cmd покушава да пише у затворену цев, .
У Го ово се такође дешава подразумевано, али СИГПИПЕ обрађивач сигнала такође штампа „сигнал: СИГПИПЕ“ или сличну поруку на крају, а да бисмо обрисали ову поруку, само треба да рукујемо СИГПИПЕ-ом на начин на који желимо, то јест, само тихо излаз:
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGPIPE)
go func() {
<-ch
os.Exit(0)
}()
Прикажи контекст поруке
Често желите да видите контекст у којем се десила нека грешка (на пример, који захтев је изазвао панику, или који повезани проблеми су били видљиви пре пада), и у grep Ово се ради помоћу опција -А, -Б и -Ц, које приказују одређени број редова после, пре и око поруке, респективно.
Нажалост, нисам нашао лак начин да то исто урадим у ЦлицкХоусе-у, тако да се за приказ контекста додатни захтев попут овог шаље сваком реду резултата (детаљи зависе од сортирања и да ли је контекст приказан пре или после):
SELECT time,millis,review_body FROM amazon
WHERE (time = 'ВРЕМЯ_СОБЫТИЯ' AND millis < МИЛЛИСЕКУНДЫ_СОБЫТИЯ) OR (time < 'ВРЕМЯ_СОБЫТИЯ')
ORDER BY time DESC, millis DESC
LIMIT КОЛИЧЕСТВО_СТРОК_КОНТЕКСТА
SETTINGS max_threads=1
Пошто се захтев шаље скоро одмах након што ЦлицкХоусе врати одговарајућу линију, он завршава у кешу и генерално захтев се извршава прилично брзо и троши мало ЦПУ-а (обично захтев траје око ~6 мс на мојој виртуелној машини).
Прикажи нове поруке у реалном времену
Да бисмо приказали долазне поруке у (скоро) реалном времену, једноставно извршавамо захтев сваких неколико секунди, памтећи последњу временску ознаку на коју смо раније наишли.
Примери команди
Како типичне логсцли команде изгледају у пракси?
Ако сте преузели Амазон скуп података који сам поменуо на почетку чланка, можете покренути следеће команде:
# Показать строки, где встречается слово 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
референце
Услужни код (без документације) је доступан на гитхуб-у на адреси . Било би ми драго да чујем ваше мишљење о мојој идеји за интерфејс конзоле за гледање дневника заснованог на ЦлицкХоусе-у.
Извор: ввв.хабр.цом
