หากคุณเคยใช้อินเทอร์เฟซเว็บเพื่อดูบันทึก คุณอาจสังเกตเห็นว่าตามกฎแล้วอินเทอร์เฟซเหล่านี้ยุ่งยากและ (บ่อยครั้ง) ไม่สะดวกและตอบสนองมากนัก คุณสามารถคุ้นเคยบางส่วนได้บางส่วนก็แย่มาก แต่สำหรับฉันแล้วดูเหมือนว่าสาเหตุของปัญหาทั้งหมดคือการที่เราเข้าใกล้งานดูบันทึกไม่ถูกต้อง: เราพยายามสร้างเว็บอินเตอร์เฟสที่ CLI (อินเทอร์เฟซบรรทัดคำสั่ง) ทำงานได้ดีขึ้น โดยส่วนตัวแล้วฉันรู้สึกสบายใจมากที่ได้ทำงานกับ tail, grep, awk และอื่นๆ ดังนั้นสำหรับฉัน อินเทอร์เฟซในอุดมคติสำหรับการทำงานกับบันทึกจะคล้ายกับ tail และ grep แต่ก็สามารถใช้เพื่ออ่านบันทึกที่มาจากเซิร์ฟเวอร์จำนวนมากได้ แน่นอนว่าอ่านได้จาก ClickHouse!
*ตามความคิดเห็นส่วนตัวของผู้ใช้ฮาบรา
พบกับ logscli
ฉันไม่ได้ตั้งชื่ออินเทอร์เฟซของฉันขึ้นมา และบอกตามตรงว่ามันค่อนข้างมีอยู่ในรูปแบบของต้นแบบ แต่ถ้าคุณต้องการเห็นซอร์สโค้ดทันที คุณก็ยินดีต้อนรับ:
ความสามารถในการ
เป้าหมายของฉันคือการสร้างอินเทอร์เฟซที่ดูคุ้นเคยสำหรับผู้ที่คุ้นเคยกับ tail/grep นั่นคือเพื่อรองรับสิ่งต่อไปนี้:
- ดูบันทึกทั้งหมดโดยไม่ต้องกรอง
- ปล่อยให้บรรทัดมีสตริงย่อยคงที่ (flag
-F
уgrep
). - เว้นบรรทัดที่ตรงกับนิพจน์ทั่วไป (flag
-E
уgrep
). - ตามค่าเริ่มต้น การดูจะเรียงลำดับเวลาแบบย้อนกลับ เนื่องจากบันทึกล่าสุดมักเป็นที่สนใจก่อน
- แสดงบริบทถัดจากแต่ละบรรทัด (options
-A
,-B
и-C
уgrep
พิมพ์ N บรรทัดก่อน หลัง และรอบแต่ละบรรทัดที่ตรงกัน ตามลำดับ) - ดูบันทึกที่เข้ามาแบบเรียลไทม์ โดยมีหรือไม่มีการกรอง (โดยพื้นฐานแล้ว
tail -f | grep
). - อินเทอร์เฟซจะต้องเข้ากันได้กับ
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)
น่าเสียดายที่ฉันไม่สามารถหาโอเพ่นซอร์สที่มีบันทึกจริงที่สามารถคว้าและดาวน์โหลดได้ในทันที ดังนั้นฉันจึงใช้สิ่งนี้เป็นตัวอย่างแทน
คำแนะนำในการอัพโหลดรีวิว 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 มีเพียงวันที่สำหรับการตรวจสอบ แต่ไม่มีเวลาที่แน่นอน ดังนั้นเรามากรอกข้อมูลนี้ด้วยแรนดอนกันดีกว่า
คุณไม่จำเป็นต้องดาวน์โหลดไฟล์ tsv ทั้งหมดและจำกัดตัวเองไว้ที่ประมาณ 10-20 ไฟล์แรก เพื่อให้ได้ชุดข้อมูลที่ค่อนข้างใหญ่ซึ่งไม่พอดีกับ RAM ขนาด 16 GB ในการอัปโหลดไฟล์ 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
บน Persistent Disk มาตรฐาน (ซึ่งเป็น HDD) ใน Google Cloud ที่มีขนาด 1000 GB (ฉันใช้ขนาดนี้เป็นหลักเพื่อให้ความเร็วสูงขึ้นเล็กน้อย แม้ว่าบางที SSD ที่มีขนาดที่ต้องการอาจมีราคาถูกกว่าก็ตาม) การอัปโหลด ความเร็วอยู่ที่ประมาณ ~ 75 MB/วินาที บน 4 คอร์
- ฉันต้องจองว่าฉันทำงานที่ Google แต่ฉันใช้บัญชีส่วนตัวและบทความนี้ไม่เกี่ยวข้องกับงานของฉันที่บริษัท
ฉันจะสร้างภาพประกอบทั้งหมดด้วยชุดข้อมูลนี้ เนื่องจากนี่คือทั้งหมดที่ฉันมี
แสดงความคืบหน้าในการสแกนข้อมูล
เนื่องจากใน ClickHouse เราจะใช้การสแกนแบบเต็มบนโต๊ะพร้อมบันทึก และการดำเนินการนี้อาจใช้เวลานานมากและอาจไม่ให้ผลลัพธ์ใดๆ เป็นเวลานานหากพบรายการที่ตรงกันน้อย ขอแนะนำให้แสดง ความคืบหน้าของแบบสอบถามจนกระทั่งได้รับแถวแรกพร้อมผลลัพธ์ เมื่อต้องการทำเช่นนี้ มีพารามิเตอร์ในอินเทอร์เฟซ HTTP ที่ช่วยให้คุณสามารถส่งความคืบหน้าในส่วนหัว HTTP: send_progress_in_http_headers=1
. น่าเสียดายที่ไลบรารี Go มาตรฐานไม่สามารถอ่านส่วนหัวตามที่ได้รับ แต่ ClickHouse รองรับอินเทอร์เฟซ HTTP 1.0 (เพื่อไม่ให้สับสนกับ 1.1!) ดังนั้นคุณจึงสามารถเปิดการเชื่อมต่อ TCP แบบดิบไปยัง ClickHouse และส่งไปที่นั่นได้ 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
.
การจัดการ SIGPIPE ใน Go อย่างถูกต้อง
เมื่อคุณดำเนินการให้พูดคำสั่ง some_cmd | head -n 10
ตรงตามคำสั่งอย่างไร some_cmd
หยุดการดำเนินการเมื่อ head
ลบ 10 บรรทัด? คำตอบนั้นง่าย: เมื่อใด head
สิ้นสุด ไปป์ปิด และ stdout ของคำสั่ง some_cmd จะเริ่มชี้ "ไม่มีที่ไหนเลย" ตามเงื่อนไข เมื่อไร some_cmd
พยายามเขียนไปยังไปป์ปิด
ใน 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 ms บนเครื่องเสมือนของฉัน)
แสดงข้อความใหม่แบบเรียลไทม์
เพื่อแสดงข้อความขาเข้า (เกือบ) แบบเรียลไทม์ เราเพียงดำเนินการตามคำขอทุกๆ สองสามวินาที โดยจดจำการประทับเวลาล่าสุดที่เราพบก่อนหน้านี้
ตัวอย่างคำสั่ง
คำสั่ง 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 ที่
ที่มา: will.com