ติดตามข้อผิดพลาด UnifyPort API ด้วย request_id และ X-Request-Id
เมื่อตรวจสอบข้อผิดพลาด UnifyPort API ให้เก็บ request_id จาก JSON ตอบกลับ หรือ X-Request-Id จากเฮดเดอร์ตอบกลับ คุณส่ง X-Request-Id ของตัวเองในเฮดเดอร์คำขอได้ โดย JSON จะส่งค่านั้นกลับมาเป็น client_request_id เพื่อเชื่อมกับบันทึกของแอป ID เหล่านี้ใช้ตรวจสอบคำขอ ไม่ใช่ ID ข้อความหรือเหตุการณ์ webhook และไม่ได้รับประกันว่าการเรียกซ้ำจะไม่ทำงานซ้ำ
ประเด็นสำคัญ
- แยกการทำงานทางธุรกิจ การเรียก HTTP แต่ละครั้ง และ ID คำขอฝั่งเซิร์ฟเวอร์
- อ่านเฮดเดอร์แม้ไม่มีเนื้อหา JSON รวมถึงการลบที่สำเร็จด้วยสถานะ
204 - เมื่อ timeout อาจไม่มี ID จากเซิร์ฟเวอร์ และผลการทำงานอาจยังไม่ทราบแน่ชัด
- เก็บรหัสข้อผิดพลาดแบบมีโครงสร้าง ไม่เก็บข้อมูลยืนยันตัวตนหรือข้อความทั้งหมด
ควรเก็บ ID ตัวไหน?
เอกสารแนะนำ APIกำหนดรูปแบบการติดตามไว้ ชื่อเฮดเดอร์เดียวกันมีหน้าที่ต่างกันตามทิศทาง:
| ค่า | ที่มา | การใช้งาน |
|---|---|---|
X-Request-Id ของคุณ | เฮดเดอร์คำขอจากไคลเอนต์ | ค้นหาการเรียก HTTP ในระบบของคุณ |
client_request_id | ค่าจากไคลเอนต์ที่ JSON ส่งกลับ | จับคู่คำตอบกับการเรียกครั้งนั้น |
request_id | JSON จากเซิร์ฟเวอร์ | แจ้งทีมสนับสนุนให้ค้นหาคำขอฝั่งเซิร์ฟเวอร์ |
X-Request-Id ในคำตอบ | เฮดเดอร์จากเซิร์ฟเวอร์ | เก็บข้อมูลติดตามแม้ไม่มีเนื้อหาตอบกลับ |
data.message_id | ผลการส่งข้อความที่สำเร็จเมื่อมีฟิลด์นี้ | ระบุข้อความ ไม่ใช่คำขอ HTTP |
บทความอัปเดต API เดือนมิถุนายนแนะนำฟิลด์เหล่านี้แล้ว บทความนี้เน้นการเก็บข้อมูลให้ครบทุกกรณี ไม่ใช่เพียงเพิ่มชื่อฟิลด์ลงใน log
แนะนำให้มี ID ภายในสำหรับงานหนึ่งชิ้น เช่น การตอบที่ผ่านการอนุมัติแล้ว และสร้าง ID แยกสำหรับการเรียก HTTP แต่ละครั้ง พร้อมเก็บความสัมพันธ์ไว้ นี่เป็นแนวทางออกแบบแอป ไม่ใช่ฟิลด์เพิ่มเติมของ UnifyPort อย่าใส่ชื่อลูกค้า เบอร์โทร เนื้อหาข้อความ หรือคีย์ลงใน ID
บันทึกการเรียกครั้งเดียวโดยไม่เพิ่ม retry อัตโนมัติ
เริ่มจากการอ่าน workspace ปัจจุบันซึ่งไม่แก้ไขข้อมูล ตัวอย่าง Node.js นี้ใช้ fetch ที่มีมาในระบบ และอ่านคีย์จากตัวแปรสภาพแวดล้อมฝั่งแบ็กเอนด์ UNIFYPORT_API_KEY โดยบันทึกเฉพาะรายการวินิจฉัยที่กำหนด ไม่บันทึกเฮดเดอร์คำขอหรือเนื้อหาคำตอบทั้งหมด
ค่า timeout เป็นเพียงนโยบายตัวอย่างของไคลเอนต์ ไม่ใช่ข้อจำกัดของบริการ ฟังก์ชันเรียกเพียงครั้งเดียวในระดับแอป และคืน Response เดิมให้ผู้เรียกจัดการต่อ
import { randomUUID } from 'node:crypto';
async function tracedWorkspaceRead(apiKey, operationId) {
const clientAttemptId = randomUUID();
const startedAt = new Date().toISOString();
const startedMs = Date.now();
let response;
try {
response = await fetch('https://api.unifyport.ai/v1/workspace', {
headers: {
'X-Api-Key': apiKey,
'X-Request-Id': clientAttemptId
},
signal: AbortSignal.timeout(10000)
});
} catch {
console.info({
operation_id: operationId,
client_attempt_id: clientAttemptId,
started_at: startedAt,
elapsed_ms: Date.now() - startedMs,
outcome: 'no_http_response'
});
throw new Error('No HTTP response; inspect the local attempt record');
}
const headerId = response.headers.get('X-Request-Id');
const body = response.status === 204
? null
: await response.clone().json().catch(() => null);
console.info({
operation_id: operationId,
client_attempt_id: clientAttemptId,
started_at: startedAt,
elapsed_ms: Date.now() - startedMs,
http_status: response.status,
server_request_id_header: headerId,
server_request_id_body: body?.request_id ?? null,
echoed_client_request_id: body?.client_request_id ?? null,
error_code: body?.error?.code ?? null,
numeric_code: body?.error?.numeric_code ?? null
});
return response;
}
const apiKey = process.env.UNIFYPORT_API_KEY;
if (!apiKey) throw new Error('Configure UNIFYPORT_API_KEY');
await tracedWorkspaceRead(apiKey, randomUUID());
ชื่ออย่าง operation_id และ outcome เป็นฟิลด์บันทึกภายในแอป ไม่ใช่โครงสร้างคำตอบของ API โค้ดมีสาขาสำหรับ 204 เพื่อประยุกต์ใช้กับการทำงานที่เอกสารระบุว่าไม่มีเนื้อหาตอบกลับ แต่การอ่าน workspace ที่สำเร็จจะได้ 200 ใช้ mock ภายในเครื่องเพื่อทดสอบกรณีว่าง ไม่ต้องลบบัญชีรับส่งข้อความเพื่อทดสอบ log
การเก็บค่าทั้งจากเฮดเดอร์และ JSON ช่วยให้เห็นค่าที่หายไปหรือไม่ตรงกัน คำตอบจากระบบตัวกลางอาจไม่ตรงกับรูปแบบ API ให้เก็บสถานะ HTTP และบันทึกการเรียกภายในไว้ อย่าสร้าง ID แล้วอ้างว่าเป็นค่าจากเซิร์ฟเวอร์ ในระบบจริงต้องจำกัดขนาดข้อมูลที่แปลงและบันทึก พร้อมควบคุมสิทธิ์และระยะเวลาเก็บรักษา
เปลี่ยนบันทึกเป็นรายงานปัญหาที่ตรวจสอบได้
เอกสารข้อผิดพลาดกำหนด error.code, error.numeric_code และ error.message ใช้ code หรือ numeric_code ในการแยกเงื่อนไข ไม่ใช้ข้อความอธิบายสำหรับมนุษย์ รหัสตัวเลขอาจระบุสาเหตุจากระบบต้นทางให้ละเอียดขึ้น โดยไม่เปลี่ยนรหัสเดิมหรือสถานะ HTTP
| สิ่งที่พบ | หลักฐานที่ควรเก็บ | การตัดสินใจถัดไป |
|---|---|---|
| JSON สำเร็จหรือผิดพลาด | สถานะ ID เซิร์ฟเวอร์ ค่าที่ส่งกลับให้ไคลเอนต์ และรหัสข้อผิดพลาด | ตีความตามเอกสารของ endpoint |
204 ไม่มีเนื้อหา | สถานะและเฮดเดอร์ X-Request-Id | อย่าถือว่าการไม่มี JSON คือ API ล้มเหลว |
| เนื้อหาอ่านไม่ได้หรือรูปแบบไม่ตรง | สถานะ ID ในเฮดเดอร์ถ้ามี และ ID การเรียกภายใน | ตรวจสอบเส้นทางของคำตอบ |
| ไม่มีคำตอบ HTTP | ID การเรียกภายใน เวลาเริ่ม และงานที่ทำ | คงผลลัพธ์เป็นไม่ทราบจนกว่าจะตรวจสอบได้ |
รายงานถึงทีมสนับสนุนควรมีสภาพแวดล้อม เวลา UTC เมธอด HTTP และรูปแบบเส้นทาง ID เซิร์ฟเวอร์ถ้าได้รับ ID การเรียกภายใน สถานะ รหัสข้อผิดพลาด และสิ่งที่คาดหวังเทียบกับสิ่งที่เกิดขึ้น แชร์ ID บัญชีหรือบทสนทนาเฉพาะช่องทางที่จำกัดสิทธิ์ อย่าแนบ API key ข้อมูลเซสชัน signing secret reply token หรือ URL สื่อที่มีลายเซ็นสำหรับเข้าถึงข้อมูล
คู่มือแก้ปัญหา X Chatแสดงการใช้ข้อมูลเหล่านี้เพื่อแยกปัญหาทั้งบัญชีออกจากปัญหาเฉพาะบทสนทนา ID คำขอช่วยค้นหาหลักฐาน แต่ไม่ได้บอกสาเหตุด้วยตัวมันเอง
การติดตามไม่ใช่สิทธิ์ให้ส่งซ้ำ
การใช้ ID ไคลเอนต์เดิมซ้ำกับ POST /v1/messages ไม่ใช่กลไก idempotency ที่เอกสารรับประกัน หากการส่ง timeout งานอาจสำเร็จแล้วแม้ไคลเอนต์ไม่ได้รับคำตอบ ให้บันทึกความไม่แน่นอนก่อนตัดสินใจส่งอีกครั้ง
สำหรับทีมที่เชื่อมต่อ LINE ต้องแยกสิ่งนี้ออกจากข้อกำหนด retry key ของ LINE ซึ่งระบุ x-line-accepted-request-id ในคำตอบเมื่อคำขอถูกยอมรับไปแล้ว อย่าอนุมานพฤติกรรมเดียวกันจากชื่อเฮดเดอร์ติดตามของ UnifyPort อ่านขั้นตอนเฉพาะได้ในคู่มือ LINE retry key
webhook ใช้การเชื่อมโยงอีกชุดหนึ่ง เอกสารการส่ง webhookกำหนด X-Device-Event-Id และ X-Device-Delivery-Id โดยค่าหลังอาจใช้ event ID แทน จึงไม่รับประกันว่าไม่ซ้ำในแต่ละ HTTP attempt อย่าเชื่อม REST กับเหตุการณ์เพียงเพราะทั้งคู่มี ID หากต้องการ ID เฉพาะของการรับแต่ละครั้ง ให้สร้างในระบบของคุณ การตัดเหตุการณ์ซ้ำต้องทำตามกฎของแต่ละชนิด รวมถึงข้อยกเว้น HistorySync และแยกจากระบบ log
คำถามที่พบบ่อย
ทำไมลบสำเร็จแต่ไม่มี request_id?
คำตอบ 204 ไม่มี JSON ให้อ่านเฮดเดอร์ X-Request-Id แทน
ใช้ request_id ตรวจสถานะการส่งได้ไหม?
ข้อกำหนดการติดตามไม่ได้ระบุ endpoint สำหรับค้นหาสถานะคำขอ เก็บผลจริงและตรวจสอบผ่านหลักฐานที่ระบบรองรับ อย่าสร้าง URL ใหม่จาก ID เอง
client_request_id เป็น idempotency key หรือไม่?
ไม่มีการรับประกันเช่นนั้นในเอกสาร ฟิลด์นี้ส่งค่าไคลเอนต์กลับมาเพื่อเชื่อมโยงข้อมูล ไม่ได้ป้องกันการส่งซ้ำ
ขั้นตอนถัดไปและแหล่งอ้างอิง
เพิ่มข้อมูลวินิจฉัยใน API client ที่ใช้อยู่หนึ่งตัว แล้วใช้ mock ภายในเครื่องทดสอบ JSON error คำตอบว่าง เนื้อหาผิดรูปแบบ และเครือข่ายล้มเหลว อ้างอิงเอกสารข้อผิดพลาดเมื่อเขียนเงื่อนไข
ตรวจสอบเมื่อ 2026-10-01:
เปลี่ยนการเชื่อมต่อข้อความให้เป็น pipeline ผลิตภัณฑ์ที่เสถียร
เริ่มจากการส่งผ่าน API เดียว แล้วส่งข้อความขาเข้าทั้งหมดกลับสู่ระบบธุรกิจของคุณด้วย event มาตรฐาน