

ระบบที่แยกเป็นหลายบริการมักมี log ของแต่ละส่วนอยู่แล้ว แต่เวลาผู้ใช้บอกว่างานหนึ่งช้า เราก็ยังต้องตามว่าเริ่มจากเว็บ ผ่าน API ไหน และไปรออะไรต่อที่ปลายทาง หากแต่ละบริการบันทึกรหัสของตัวเองโดยไม่มีความสัมพันธ์ การเปิดหลายหน้าจอก็ไม่ได้ทำให้ต่อเรื่องได้ง่ายขึ้นเสมอไป
Distributed tracing เข้ามาช่วยเก็บความสัมพันธ์ของงานเหล่านี้ โดยมองการทำงานย่อยเป็น span ที่อยู่ในบริบทของ trace เดียวกันตามเส้นทาง แต่การติดตั้งตัวส่งข้อมูลในทุกบริการยังไม่พอ หากบริบทหลุดตอนข้ามจากส่วนหนึ่งไปอีกส่วน เราก็อาจได้ trace แยกหลายเรื่องแทนงานเดียวที่ตั้งใจตาม
จุดเริ่มจึงควรเป็นการไล่เส้นทางของงานจริงในระบบว่า context ต้องข้ามขอบเขตตรงไหนบ้าง แล้วค่อยตรวจการส่งต่อทีละช่วงครับ
Trace ID ช่วยระบุชุดการติดตาม ส่วน span มีรหัสและความสัมพันธ์กับงานที่เกี่ยวข้อง ทำให้เครื่องมือแสดงได้ว่าการเรียกปลายทางเกิดในบริบทของขั้นใด ไม่ใช่เพียงค้นข้อความที่มีเลขเหมือนกันแล้วถือว่ารู้ลำดับเหตุการณ์ครบแล้ว
สำหรับ HTTP มาตรฐาน W3C Trace Context กำหนดรูปแบบ header เช่น traceparent เพื่อส่งข้อมูลที่ใช้ต่อความสัมพันธ์ ฝั่งผู้ส่งต้องนำ context ที่เกี่ยวข้องใส่ในคำขอ ส่วนฝั่งรับต้องอ่านกลับมาเป็นบริบทก่อนสร้าง span ที่สัมพันธ์กันตาม instrumentation ที่ใช้
จึงมีทั้งขั้น inject และ extract หากทำเฉพาะฝั่งส่ง แต่บริการรับสร้าง trace ใหม่โดยไม่อ่าน header ความต่อเนื่องก็ยังขาดได้ ในทางกลับกัน การคัดลอก Trace ID เป็นข้อความลง log อย่างเดียวก็ไม่เท่ากับสร้างความสัมพันธ์ของ span ให้ถูกต้องแล้ว

Instrumentation ของ framework หรือ HTTP client อาจจัดการส่งต่อ context ให้แล้ว ซึ่งช่วยลดงานที่ต้องเขียนเอง แต่ขอบเขตการรองรับต้องตรวจจาก library กับรุ่นที่ใช้จริง ไม่ถือว่าเปิด tracing ในแอปแล้วทุกเส้นทางเครือข่ายจะมีข้อมูลต่อครบโดยอัตโนมัติ
หากมี wrapper ที่สร้าง client ใหม่ หรือมีขั้นทำงานนอกเส้นทางที่ระบบติดตามอยู่ ควรตรวจว่าบริบทปัจจุบันยังถูกเชื่อมมาถึงจุดนั้นหรือไม่ โดยเฉพาะงานที่รันพร้อมกันหลายคำขอ การเก็บ context ในตัวแปรกลางที่ทุกงานใช้ร่วมกันอาจทำให้ข้อมูลของคนละงานปะปนได้
เมื่อจำเป็นต้องส่งเอง ควรใช้ API ของ propagator และกลไก context ที่ SDK รองรับ เพื่อให้การเข้ารหัส การตรวจรูปแบบ และการผูกบริบททำงานร่วมกัน ไม่ประกอบ header เองจากสิ่งที่จำได้เพียงบาง field แล้วคาดว่าระบบอื่นจะตีความตรงกัน
การส่ง message เข้าคิวเปลี่ยนขอบเขตจากการเรียก HTTP ที่มีคำตอบตรงหน้าไปเป็นงานที่อาจรอและถูกทำในภายหลัง Context จึงต้องเดินทางผ่าน metadata หรือพื้นที่ที่ระบบ messaging รองรับ และฝั่ง consumer ต้องดึงกลับมาด้วยวิธีของ instrumentation นั้น
แต่การเชื่อมบริบทไม่ได้บอกว่า worker ควรทำอะไรกับ message ซ้ำ หรือ job มีสิทธิ์เปลี่ยนข้อมูลใด เรื่องเหล่านั้นยังต้องอาศัยรหัสงาน สัญญาของ message และการตรวจสิทธิ์ตามเดิม Trace ใช้ช่วยอธิบายการทำงาน ไม่ควรกลายเป็นแหล่งตัดสินผลธุรกิจแทนข้อมูลของงานเอง
สำหรับงานที่รอนานหรือรวมมาจากหลาย message ควรตรวจรูปแบบความสัมพันธ์ที่ SDK และระบบแสดงผลรองรับด้วย ไม่ยืด span ของคำขอหน้าบ้านให้เปิดอยู่ตลอดเพียงเพราะอยากเห็นทุกอย่างเป็นเส้นเดียว การเลือกรูปแบบควรทำให้ความหมายของช่วงรอและช่วงประมวลผลอ่านได้ตรง
บางครั้งเราต้องการให้บริบทประกอบไปถึงบริการถัดไปด้วย OpenTelemetry มี baggage สำหรับส่งข้อมูลแบบ key-value ตาม context แต่ข้อมูลใน baggage แยกจาก attributes ของ span การใส่ไว้ไม่ได้หมายความว่าทุก backend จะเก็บเป็น field ที่ค้นได้เองโดยไม่มีกลไกนำไปใช้
อีกเรื่องที่ต้องคิดก่อนคือข้อมูลนั้นควรเดินทางไปไกลแค่ไหน เมื่อ instrumentation ส่ง baggage ไปพร้อมคำขอปลายทาง บริการที่เราเรียกอาจเป็นระบบภายนอกที่ไม่ได้ตั้งใจให้เห็นข้อมูลลูกค้าหรือรายละเอียดภายใน จึงควรเลือกเฉพาะสิ่งจำเป็นและกำหนดขอบเขตการส่งต่อให้ชัด
ไม่ควรใส่ token รหัสผ่าน หรือข้อมูลส่วนบุคคลลงไปเพื่อหวังว่าตามงานง่ายขึ้น และข้อมูล baggage ที่รับจากภายนอกก็ไม่มีการรับรองความถูกต้องในตัวเอง ห้ามใช้ค่าที่อ้างว่าเป็นบัญชีหรือองค์กรในนั้นแทนการยืนยันสิทธิ์จากกลไกของบริการ
Header ที่เข้ามาต้องผ่านการอ่านรูปแบบและขอบเขตตามที่เครื่องมือรองรับด้วย การที่ผู้เรียกภายนอกส่งรหัส trace มาได้ ไม่ใช่หลักฐานว่าเขาเป็นเจ้าของงานภายในหรือมีสิทธิ์ค้นรายละเอียดในระบบติดตามของเรา

ในการตรวจชุดทดลอง ลองเริ่มจากคำขอที่มีเส้นทางสั้นและรู้บริการปลายทางแน่นอน แล้วดูว่ารหัส trace กับความสัมพันธ์ของ span ต่อกันได้หรือไม่ จากนั้นค่อยเพิ่มช่วงผ่าน proxy คิว และงานที่รันพร้อมกัน วิธีนี้ช่วยแยกว่าขาดที่การส่ง context หรือขั้นเก็บและแสดงผล
ถ้าต่อความสัมพันธ์ได้แต่ยังไม่เห็นบางงาน ต้องตรวจ sampling และการส่ง telemetry ต่อด้วย เพราะ context ที่ถูกต้องไม่ได้รับรองว่า span ทุกตัวจะถูกเลือกเก็บและส่งถึง backend หากหา trace ไม่เจอจึงยังสรุปไม่ได้ทันทีว่าไม่มี request นั้นเกิดขึ้น
การใส่ Trace ID และ Span ID ใน log ผ่านวิธีที่รองรับช่วยให้สลับจากหลักฐานแต่ละชนิดมาดูบริบทเดียวกันได้ แต่สิทธิ์อ่านข้อมูลและนโยบายปกปิดข้อมูลใน log ยังต้องทำต่อ บทนี้ไม่มี trace จากระบบลูกค้าหรือผลทดสอบการต่อบริการจริงมาแสดง ภาพเป็นแผนผังของขอบเขตการส่งต่อเท่านั้น
การต่อ trace ให้เห็นงานเดียวกันต้องดูทั้งบริบทใน process และการส่งผ่านขอบเขตบริการ เมื่อฝั่งส่งกับฝั่งรับทำงานสัมพันธ์กัน เราจะตามงานย่อยได้มีเหตุผลขึ้น ส่วนข้อมูลที่ส่งต่อยังต้องจำกัดตามความจำเป็น และแยกจากสิทธิ์หรือสถานะธุรกิจ เพื่อให้การติดตามช่วยตรวจระบบโดยไม่เปลี่ยนเป็นทางลัดของข้อมูลที่ควรตรวจจากแหล่งอื่น