วิธีหา processing speed จาก log file ด้วย shell script

[บันทึกกันลืม] ห่างหายไปนาน

กำลังทำระบบ ETL ซึ่งเป็นลักษณะของ Concurrent processing โจทย์คือ ต้องเอาข้อมูล 40 ล้าน items เข้าไปใน Apache Cassandra cluster ที่ประกอบด้วย 5 nodes เป้าหมายคือ 1000 items /second

วิธีทำ concurrent ด้วย python เดี๋ยวมาเล่าให้ฟัง (รอ Link ตรงนี้)

โดยย่อ การนำเข้าข้อมูล ทำด้วย Python script แล้วจะเขียน log file หน้าตาประมาณนี้ ให้สนใจแค่ว่าคอลัมน์แรก เป็น timestamp

ประมาณว่า บรรทัดแรก เขียนข้อมูลเมื่อ 2022-11-30 07:34:13

แล้วบรรทัดล่าสุด หน้าตาประมาณนี้

ประมาณว่า บรรทัดสุดท้าย เขียนข้อมูลเมื่อ 2022-11-30 11:12:19

ทำไปแล้วกี่ items ใช้คำสั่ง wc -l นับบรรทัด เก็บในตัวแปร it

wc -l kx.log

ได้มาประมาณ 17,030,016 items

แล้วเราจะหา จำนวนวินาที จากเริ่มต้น ถึงปัจจุบันอย่างไร ???

อันนี้คือ shell script เดี๋ยวอธิบายต่อไป

t1=$(head -1 kx.log|cut -d, -f1); ts1=$(date -d "$t1" +%s); t2=$(tail -1 kx.log|cut -d, -f1); ts2=$(date -d "$t2" +%s); it=$(wc -l kx.log|cut -d' ' -f1); retrys=$(wc -l retryf.txt| cut -d' ' -f1); ss=$(expr $ts2 - $ts1) ; timelag=$(date -d@$ss -u +%H:%M:%S); speed=$(expr \( $it - $retrys \) / \( $ts2 - $ts1 \)); echo "process $it items, take $timelag,  $speed it/s"

เมื่อ run แล้ว ได้ผลลัพธ์ประมาณนี้

process 17030016 items, 1334 it/s

มาดูรายละเอียดกัน

t1=$(head -1 kx.log|cut -d, -f1)

เป็นการสร้างตัวแปร ชื่อ t1 ซึ่ง $(…) เป็นการสั่งให้คำสั่ง ภายในวงเล็บ นั้นทำงาน

head -1 kx.log

คำสั่ง head -1 คือ เอาบรรทัดแรก

cut -d, -f1

เป็นการ แยกข้อความ ด้วย , และเอา ฟิลด์ (field) ที่ 1 ออกมา

ผลรวมของคำสั่งนี้ คือ จะได้ timestamp เก็บในตัวแปร t1

2022-11-30 07:34:13

เช่นเดียวกับเวลาของบรรทัดสุดท้าย เปลี่ยนจาก head เป็น tail ก็จะได้ ตัวแปร t2

2022-11-30 11:12:19

คราวนี้ เราจะรู้ได้ไง ว่า ระหว่าง 2022-11-30 07:34:13 กับ 2022-11-30 11:12:19 ห่างกันกี่วินาที ?

เราสามารถใช้คำสั่ง (เก็บในตัวแปร ts2)

date -d '2022-11-30 11:12:19' +%s

เพื่อได้วินาทีของวันเวลา คือค่า

1669781539

เช่นดัวกับ เวลาเริ่มต้น (เก็บในตัวแปร ts1)

date -d '2022-11-30 07:34:13' +%s

จะได้ค่า

1669768453

มาถึงตรงนี้ เราก็จะได้ตัวแปร ts1, ts2, it เราจะหาความเร็วก็ต้องใช้สูตร

speed = it / (ts2 - ts1)

ใน shell script เราเขียนตรง ๆ อย่างนั้นไม่ได้ ต้องใช้ผ่านคำสั่ง expr (เก็บในตัวแปร speed)

expr $it / \( $ts2 - $ts1 \)

คราวนี้ เราต้องการรู้ด้วยว่า ใช้เวลาทำไปแล้ว กี่ชั่วโมง นาที วินาที คำสั่งนี้ ใช้ date -d แล้วใช้ @ ตามด้วยจำนวนวินาที

date -d@60  -u +%H:%M:%S

ใช้คำสั่งนี้ หา จำนวนวินาที เก็บในตัวแปร ss

expr $ts2 - $ts1

แล้วใช้คำสั่งนี้ แปลงเป็น ชั่วโมง นาที วินาที เก็บในตัวแปร timelag

date -d@$ss -u +%H:%M:%S

สุดท้าย เอามารวมกันทั้งหมด แล้ว echo ออกไป

echo "process $it items, take $timelag,  $speed it/s"

ผลที่ได้คือ

process 17030016 items, take 04:29:03, 1334 it/s

หวังว่าจะเป็นประโยชน์ครับ