การคำนวณสถิติ Campaign
ภาพรวม
หลังจากส่ง campaign ออกไปแล้ว ระบบต้องรายงานให้ได้ว่าเข้าถึงผู้ใช้กี่คน มีคนอ่านและคลิกเท่าไร และลิงก์ไหนถูกคลิกมากที่สุด
งานนี้คือ consumer ที่คำนวณตัวเลขเหล่านั้นจากตาราง tracking_log แล้วเขียนผลกลับลงตาราง campaign เพื่อให้ CMS อ่านไปแสดงผลได้ทันทีโดยไม่ต้อง aggregate ใหม่ตอน query
การคำนวณถูก trigger ได้ 2 ทาง คือ (1) cron รายชั่วโมงที่กวาด campaign ซึ่งถูกทำเครื่องหมายว่า dirty ไว้ใน Redis และ (2) การ publish ตรงเข้า queue เมื่อต้องการคำนวณ campaign ใดเป็นการเฉพาะ
Business Flow
ฝั่ง scanner (cron บน profile cron-scheduler)
- ทุกชั่วโมงตรงตาม cron
0 * * * *CampaignStatScannerServiceจะสแกน Redis เพื่อหา key รูปแบบCAMPAIGN_STAT_DIRTY:<campaignId>ซึ่ง key เหล่านี้ถูกตั้งโดยเส้นทาง tracking ทุกครั้งที่มี click หรือ read เข้ามา - แกะ campaign id ออกจากชื่อ key แล้ว publish 1 job ต่อ 1 campaign เข้า queue
calculate_campaign_stat - หากไม่พบ key dirty เลย จะข้ามรอบนั้นไป เพื่อไม่ให้เสีย query ฐานข้อมูลโดยเปล่าประโยชน์
ฝั่ง consumer (profile main)
- รับ payload ที่มีฟิลด์
campaignIdและdateซึ่งเป็น optional ทั้งคู่ หากไม่ระบุcampaignIdระบบจะคำนวณ ทุก campaign ที่มีสถานะsentและยังอยู่ในช่วง tracking period ซึ่งมีค่าเริ่มต้น 90 วันนับจากstart_date calculateCampaignStatsคำนวณตัวเลขรวมจากtracking_logได้แก่totalRecipient— จำนวนผู้รับ โดยกรณี broadcast จะใช้จำนวน follower จาก LINE Insight APItotalReach— จำนวนline_uidที่ไม่ซ้ำกันซึ่งมี activitytotalActivity— จำนวน activity ทั้งหมดtotalUniqueClick— จำนวนline_uidที่ไม่ซ้ำกันซึ่งมีaction_typeเป็นclicktotalFirstClick— จำนวนการคลิกครั้งแรกของ event ที่typeเป็นuriหรือpostback- ทุกตัวเลขใช้เกณฑ์กรองว่า
line_uidต้องไม่เป็น NULL และไม่เท่ากับ-
summarizeCampaignStatsสรุปตัวเลขรายลิงก์และรายรูปลงในคอลัมน์template_trackingโดยแยกตามประเภทflex,tappableImage,imageและvideoพร้อม join กับตารางrich_messageเพื่อระบุว่าลิงก์แต่ละ index คืออะไร- จำนวน read นับจาก event ประเภท
assetส่วนจำนวน click นับจาก event ประเภทuriและpostback
- จำนวน read นับจาก event ประเภท
- เขียนผลลัพธ์ทั้งหมดกลับลงตาราง
campaignทั้งคอลัมน์สถิติและtemplate_tracking
ไฟล์และฟังก์ชันหลัก
internal/campaign/campaign.goService.ProcessCalculateCampaignStat(ctx, payload)— entry point ของ consumercalculateCampaignStats()และgetLineFollowerCount()- ค่าคงที่
defaultCampaignTrackingPeriodDaysเท่ากับ 90 - struct
CampaignStatPayloadซึ่งมีฟิลด์CampaignIDและDate
internal/campaign/stats.gocountUniqueLineUID(),countActivity(),countFirstClick()summarizeCampaignStats(),queryClicks(),queryAssetReads()
internal/campaign/consumer.go—Consumer.HandleCalculateCampaignStatinternal/cronscheduler/campaign_stat_scanner.go—CampaignStatScannerService.Run(ctx)และค่าคงที่campaignDirtyKeyPrefix- Queue: consume
calculate_campaign_statบน profilemainโดยมี cron บน profilecron-schedulerเป็นผู้ publish
จุดเชื่อมต่อกับ Service อื่น
- ตาราง
tracking_log— เป็นแหล่งข้อมูลดิบทั้งหมด โดยใช้คอลัมน์campaign_id,line_uid,action_type,type,rich_message_indexและcreated_date - ตาราง
campaign— ปลายทางที่เขียนผลลัพธ์ และ ตารางrich_message— อ่านโครงสร้างเพื่อ map index กลับไปยังลิงก์ - Redis — key
CAMPAIGN_STAT_DIRTY:*ทำหน้าที่บอกว่า campaign ใดมีข้อมูลใหม่ที่ต้องคำนวณ - LINE API —
GET /v2/bot/insight/followersสำหรับหาค่าtotalRecipientของ campaign แบบ broadcast - ผู้ใช้ผลลัพธ์ — cms-api-go ในโดเมน campaign-management ซึ่งเป็นผู้แสดงหน้ารายงาน campaign