Ni disvolvas la plej oportunan* interfacon de la mondo por vidi protokolojn

Ni disvolvas la plej oportunan* interfacon de la mondo por vidi protokolojn Se vi iam uzis retajn interfacojn por vidi protokolojn, tiam vi verŝajne rimarkis kiel, kiel regulo, ĉi tiuj interfacoj estas maloportunaj kaj (ofte) ne tre oportunaj kaj respondemaj. Iuj al kiuj vi povas alkutimiĝi, iuj estas absolute teruraj, sed ŝajnas al mi, ke la kialo de ĉiuj problemoj estas, ke ni malĝuste traktas la taskon vidi protokolojn: ni provas krei retan interfacon kie la CLI (komandlinia interfaco) funkcias pli bone. Mi persone estas tre komforta labori kun tail, grep, awk kaj aliaj, kaj tial por mi la ideala interfaco por labori kun protokoloj estus io simila al tail kaj grep, sed kiu ankaŭ povus esti uzata por legi protokolojn kiuj venis de multaj serviloj. Tio estas, kompreneble, legu ilin de ClickHouse!

*laŭ la persona opinio de la habra uzanto via ROKO

Renkontu logscli

Mi ne elpensis nomon por mia interfaco, kaj, por esti honesta, ĝi prefere ekzistas en formo de prototipo, sed se vi volas tuj vidi la fontkodon, tiam vi estas bonvenaj: https://github.com/YuriyNasretdinov/logscli (350 linioj de elektita Go-kodo).

Trajtoj

Mia celo estis fari interfacon kiu ŝajnus konata al tiuj, kiuj kutimas tail/grep, tio estas, subteni la jenajn aferojn:

  1. Rigardu ĉiujn protokolojn, sen filtrado.
  2. Lasu liniojn enhavantajn fiksan subŝnuron (flago -F у grep).
  3. Lasu liniojn kiuj kongruas kun la regula esprimo (flago -E у grep).
  4. Defaŭlte, spektado estas en inversa kronologia sinsekvo, ĉar la plej lastatempaj protokoloj kutime interesas unue.
  5. Montru kuntekston apud ĉiu linio (opcioj -A, -B и -C у grep, presante N liniojn antaŭ, post, kaj ĉirkaŭ ĉiu kongrua linio, respektive).
  6. Rigardu envenantajn protokolojn en reala tempo, kun aŭ sen filtrado (esence tail -f | grep).
  7. La interfaco devas esti kongrua kun less, head, tail kaj aliaj - defaŭlte, rezultoj devus esti resenditaj sen limigoj pri ilia nombro; linioj estas presitaj kiel rivereto tiel longe kiel la uzanto estas interesita ricevi ilin; signalo SIGPIPE devus silente interrompi protokolon, same kiel ili faras tail, grep kaj aliaj UNIX-servaĵoj.

Реализация

Mi supozos, ke vi jam iel scias kiel liveri protokolojn al ClickHouse. Se ne, mi rekomendas provi ĝin LSD и katidodomoKaj ĉi tiu artikolo pri ŝtiplivero.

Unue vi devas decidi pri la baza skemo. Ĉar vi kutime volas ricevi protokolojn ordigitajn laŭ tempo, ŝajnas logike konservi ilin tiel. Se ekzistas multaj protokolo-kategorioj kaj ili estas ĉiuj de la sama tipo, tiam vi povas fari protokolan kategorion kiel la unua kolumno de la ĉefa ŝlosilo - ĉi tio permesos al vi havi unu tablon anstataŭ pluraj, kio estos granda pluso kiam enmeti en ClickHouse (en serviloj kun malmolaj diskoj, oni rekomendas enmeti datumojn ne pli ol ~1 fojojn je sekundo por la tuta servilo).

Tio estas, ni bezonas proksimume la sekvan tabelskemon:

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

Bedaŭrinde, mi ne povis tuj trovi malfermajn fontojn kun realismaj protokoloj, kiujn mi povus kapti kaj elŝuti, do mi prenis ĉi tion anstataŭe kiel ekzemplon. recenzoj de produktoj de Amazon ĝis 2015. Kompreneble, ilia strukturo ne estas ĝuste la sama kiel tiu de tekstaj protokoloj, sed por ilustraj celoj tio ne gravas.

instrukcioj por alŝuti Amazon-recenzojn al ClickHouse

Ni kreu tabelon:

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

En la Amazon-datumaro estas nur dato por revizio, sed ne ekzistas preciza tempo, do ni plenigu ĉi tiujn datumojn per randon.

Vi ne devas elŝuti ĉiujn tsv-dosierojn kaj limigi vin al la unuaj ~10-20 por akiri sufiĉe grandan aron da datumoj, kiuj ne taŭgas en 16 GB da RAM. Por alŝuti TSV-dosierojn mi uzis la jenan komandon:

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

Sur norma Persistent Disk (kiu estas HDD) en Google Cloud kun grandeco de 1000 GB (mi prenis ĉi tiun grandecon ĉefe por ke la rapido estis iom pli alta, kvankam eble SSD de la bezonata grandeco estus pli malmultekosta) la alŝuto rapido estis proksimume ~ 75 MB/sec sur 4 kernoj.

  • Mi devas rezervi, ke mi laboras ĉe Guglo, sed mi uzis personan konton kaj ĉi tiu artikolo havas nenion komunan kun mia laboro ĉe la kompanio.

Mi produktos ĉiujn ilustraĵojn kun ĉi tiu aparta datumaro, ĉar ĉi tio estas ĉio, kion mi havis ĉemane.

Montru la progreson de la skanado de datumoj

Ĉar en ClickHouse ni uzos plenan skanadon sur tablo kun protokoloj, kaj ĉi tiu operacio povas preni signifan kvanton da tempo kaj eble ne produktas ajnajn rezultojn dum longa tempo se malmultaj kongruoj estas trovitaj, estas konsilinde povi montri la progreso de la demando ĝis la unuaj vicoj kun la rezulto estas ricevitaj. Por fari tion, ekzistas parametro en la HTTP-interfaco, kiu permesas vin sendi progreson en HTTP-kapoj: send_progress_in_http_headers=1. Bedaŭrinde, la norma Go-biblioteko ne povas legi kapliniojn kiam ili estas ricevitaj, sed la HTTP 1.0-interfaco (ne konfuzu kun 1.1!) estas subtenata de ClickHouse, do vi povas malfermi krudan TCP-konekton al ClickHouse kaj sendi ĝin tien. GET /?query=... HTTP/1.0nn kaj ricevu la respondkapojn kaj korpon sen ia eskapo aŭ ĉifrado, do ĉi-kaze ni eĉ ne bezonas uzi la norman bibliotekon.

Streaming protokoloj de ClickHouse

ClickHouse havas optimumigon por demandoj kun ORDER BY dum relative longa tempo (ekde 2019?), do demando kiel

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

Ĝi tuj komencos resendi liniojn, kiuj havas la subĉenon "io" en sia mesaĝo, sen atendi ke la skanado finiĝos.

Ankaŭ, estus tre oportune se ClickHouse mem nuligis la peton kiam la konekto al ĝi estis fermita, sed ĉi tio ne estas la defaŭlta konduto. Aŭtomata peto nuligo povas esti ebligita per la opcio cancel_http_readonly_queries_on_client_close=1.

Ĝusta uzado de SIGPIPE en Go

Kiam vi plenumas, ekzemple, la komandon some_cmd | head -n 10, ĝuste kiel la komando some_cmd ĉesas ekzekuton kiam head subtrahis 10 liniojn? La respondo estas simpla: kiam head finiĝas, la pipo fermiĝas, kaj la stdout de la komando some_cmd komencas indiki, kondiĉe, "al nenie". Kiam some_cmd provas skribi al fermita tubo, ĝi ricevas SIGPIPE-signalon, kiu silente finas la programon defaŭlte.

En Go ankaŭ tio okazas defaŭlte, sed la SIGPIPE-signaltraktilo ankaŭ presas "signalon: SIGPIPE" aŭ similan mesaĝon ĉe la fino, kaj por forigi ĉi tiun mesaĝon ni nur bezonas pritrakti SIGPIPE mem kiel ni volas, tio estas, nur silente. eliro:

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

Montru mesaĝan kuntekston

Ofte vi volas vidi la kuntekston en kiu okazis ia eraro (ekzemple, kiu peto kaŭzis panikon, aŭ kiaj rilataj problemoj estis videblaj antaŭ la kraŝo), kaj en grep Ĉi tio estas farita uzante la opciojn -A, -B kaj -C, kiuj montras la specifitan nombron da linioj post, antaŭ kaj ĉirkaŭ la mesaĝo, respektive.

Bedaŭrinde, mi ne trovis facilan manieron fari la samon en ClickHouse, do por montri la kuntekston, plia peto tia estas sendata al ĉiu linio de la rezulto (la detaloj dependas de la ordigo kaj ĉu la kunteksto estas montrata antaŭe. aŭ poste):

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

Ĉar la peto estas sendita preskaŭ tuj post kiam ClickHouse resendas la respondan linion, ĝi finiĝas en la kaŝmemoro kaj ĝenerale la peto efektiviĝas sufiĉe rapide kaj konsumas iom da CPU (kutime la peto daŭras ĉirkaŭ ~6 ms sur mia virtuala maŝino).

Montru novajn mesaĝojn en reala tempo

Por montri envenantajn mesaĝojn en (preskaŭ) reala tempo, ni simple plenumas la peton unufoje ĉiujn kelkajn sekundojn, memorante la lastan tempomarkon, kiun ni renkontis antaŭe.

Ekzemploj de komando

Kiel aspektas tipaj logscli-komandoj en la praktiko?

Se vi elŝutis la Amazon-datumon, kiun mi menciis komence de la artikolo, vi povas ruli la jenajn komandojn:

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

referencoj

La utilkodo (sen dokumentado) estas havebla ĉe github ĉe https://github.com/YuriyNasretdinov/logscli. Mi ĝojus aŭdi viajn pensojn pri mia ideo pri konzola interfaco por vidi protokolojn bazitajn sur ClickHouse.

fonto: www.habr.com

Aldoni komenton