การบันทึก Tracking Log
ภาพรวม
ทุกการอ่าน การคลิก และการส่งข้อความในระบบสุดท้ายแล้วจะถูกบันทึกลงตาราง tracking_log เพียงตารางเดียว ตารางนี้จึงเป็นแหล่งข้อมูลจริงของรายงานแคมเปญและสถิติ rich menu รวมถึงเป็นตัวจุดชนวน trigger ประเภท campaign_click ผ่านกลไก Postgres trigger ร่วมกับ pg-listener
Consumer ตัวนี้รับ event ได้จากสองแหล่ง คือ webhook ซึ่งเป็น postback ที่มาจาก LINE และ redirect ซึ่งเกิดจากการที่ผู้ใช้กดลิงก์ผ่าน redirect service โดยแหล่งหลังต้องผ่านการตรวจลายเซ็น HMAC ก่อนจึงจะบันทึกได้
Business Flow
- รับ payload ชนิด
RedirectTrackingPayloadซึ่งมีฟิลด์logEventType,headers,bodyและbodyRaw - ตรวจความถูกต้องของ payload
logEventTypeต้องมีค่าเป็นwebhookหรือredirectเท่านั้น- กรณี
webhookต้องมีค่า user id อยู่ในโครงสร้าง event ตัวแรกของ body และต้องไม่ว่าง หากรูปแบบผิดไปจากมาตรฐานระบบจะบันทึก log ระดับ warning แต่ยังทำงานต่อ - กรณี
redirectต้องมี headerx-bank-signatureและต้องผ่านการตรวจHMAC-SHA256ที่คำนวณบน raw bytes ของ body ด้วยค่าREDIRECT_API_SECRETโดยเปรียบเทียบแบบ timing-safe เหตุผลที่ต้องใช้ raw bytes คือการ re-marshal ใน Go จะเรียงลำดับคีย์ใหม่และ escape อักขระ HTML ซึ่งทำให้ลายเซ็นไม่ตรงกัน
SaveTrackingLogแปลงข้อมูลให้อยู่ในโครงสร้างของตารางtracking_loggetActionType()แยกประเภทการกระทำออกเป็นread,clickหรือsendhandlePostbackEvent()แกะข้อมูลจาก postback ส่วนhandleAutoResponseEvent()จัดการกรณีบันทึก log ของ auto response- เติมข้อมูลบริบทเข้าไป ได้แก่
campaign_id,rich_message_id,rich_message_index,line_uid,content_typeและtypeซึ่งมีค่าเป็นuri,asset,postbackหรือmessage
insertTrackingLogเขียนแถวใหม่ลงตารางtracking_logsaveTrackingLineUsersอัปเดตแถวline_userทั้งฟิลด์last_activity_typeและlast_activity_statusและหากผู้ใช้เงียบไปเกิน 1 ชั่วโมงจะอัปเดตlast_activity_periodด้วยcheckAndCompleteDelayWaitตรวจว่าผู้ใช้รายนี้มี scheduled action ที่ตั้งไว้แบบรอจนกว่าจะมีการคลิกหรือไม่ (waitForTracking) หากมี การคลิกครั้งนี้จะปลดล็อกให้ action นั้นทำงานต่อทันที โดยตรวจผ่านการ join จากtrigger_ruleไปยังworkflow_idและscheduled_action- การ INSERT ที่เกิดขึ้นจะทำให้ Postgres trigger ยิง
pg_notifyด้วย channelcampaign_clickซึ่ง pg-listener จะรับต่อและส่งเข้าคิวcampaign_click_triggerให้ trigger engine ประมวลผล
ไฟล์และฟังก์ชันหลัก
internal/tracking/service.goService.ProcessTrackingLog(ctx, payload)— entry point ที่รวมทั้งการ validate และการตรวจลายเซ็นverifyXBankSignature(),getActionType(),initializeTrackingData()SaveTrackingLog(),saveTrackingLogInner(),insertTrackingLog(),saveTrackingLineUsers()handlePostbackEvent(),handleAutoResponseEvent(),checkAndCompleteDelayWait()- ค่าคงที่
moduleNameมีค่าเป็นTRACKINGใช้เป็น prefix ของ Redis key
internal/tracking/consumer.go—Consumer.HandleTrackingLoginternal/tracking/payloads.go—RedirectTrackingPayloadและUnmarshalRedirectTrackingPayloadinternal/tracking/signature_test.go— ชุดทดสอบของการตรวจลายเซ็นcmd/worker/integration.go—lineUserFinderซึ่งเป็น adapter ของtracking.LineUserService- คิวที่เกี่ยวข้อง:
tracking_log(runtime profilemain)
จุดเชื่อมต่อกับ Service อื่น
- ต้นทางของงาน —
line-management-webhook-goทั้งจาก postback และ callback ของ redirect service รวมถึง handler ของคิวline_webhookภายใน worker เองในกรณี event ชนิด postback - ฐานข้อมูล —
tracking_log(INSERT),line_user(UPDATE ข้อมูลกิจกรรมล่าสุด) และtrigger_ruleกับscheduled_actionสำหรับกรณี delay-wait - Redis — key ที่ขึ้นต้นด้วย
TRACKING:และเป็นจุดที่ตั้ง dirty flag กลุ่มCAMPAIGN_STAT_DIRTY:กับRICH_MENU_STAT_DIRTY:ให้ scanner นำไปคำนวณสถิติต่อ - ตัวแปรสภาพแวดล้อม —
REDIRECT_API_SECRETสำหรับตรวจx-bank-signature - ผลลัพธ์ต่อเนื่อง — งานคำนวณสถิติแคมเปญ งานคำนวณสถิติ rich menu และ trigger engine ในส่วนของ campaign click