Protobuf Decoder: ส่อง Payload ดิบโดยไม่ต้องมี Schema
decode payload protobuf จาก base64 หรือ hex โดยไม่ต้องมี schema ดู field numbers, wire types, varints, strings และ nested messages เพื่อ debug gRPC และ Kafka
Table of Contents
เคยเจอไหมตอน debug ระบบที่คุยกันด้วย protobuf แล้วเปิด log ออกมาเจอแต่ string แปลก ๆ อย่าง CgtoaGVsbG8hISEQlgE= หรือลำดับไบต์ hex เรียงยาวเหยียด ทั้งที่รู้ว่าข้างในมีข้อมูลสำคัญซ่อนอยู่ ถ้ามีไฟล์ .proto ครบก็คงไม่มีปัญหา แต่ในโลกจริงไฟล์ schema มักอยู่คนละ repo คนละทีม หรือเวอร์ชันไม่ตรงกับที่ใช้ encode จริง นั่งถอด byte เองก็ทั้งเสียเวลาและเสี่ยงผิด
Protobuf Decoder คือเครื่องมือฟรีที่ช่วยคุณถอด payload จาก base64 หรือ hex ให้กลายเป็นโครงสร้างที่อ่านได้ทันที โดยไม่ต้องมีไฟล์ .proto เลย แค่วาง bytes ลงไป มันจะอ่าน wire format ตรง ๆ แล้วแสดง field number, wire type, ค่า varint, string ที่ถอดแล้ว และต้นไม้ของ nested message ให้ดูชัดเจนในไม่กี่วินาที
ที่สำคัญ เครื่องมือนี้ทำงานใน browser 100% ข้อมูลของคุณไม่ถูกส่งไปเซิร์ฟเวอร์ใด ๆ รัน offline ได้ทั้งหมด จึงใช้กับ payload ที่มีข้อมูลละเอียดอ่อนได้อย่างปลอดภัย เหมาะทั้งงาน debug gRPC และการตรวจค่า message ใน Kafka
ทำไมต้องใช้ Protobuf Decoder?
- ไม่มีไฟล์ .proto ก็ถอดได้ — wire format ของ protobuf เก็บ field number กับ wire type ไว้ในทุก field เครื่องมืออ่าน tag ตรง ๆ ได้โดยไม่ต้องรู้ชื่อ field ทำให้ยัง debug ต่อได้แม้ schema หายหรือเวอร์ชันไม่ตรงกัน
- ประหยัดเวลา debug gRPC — เห็นทันทีว่า request หรือ response มี field อะไรบ้าง ค่าเป็นเท่าไร จุดไหน encode ผิดหรือค่าหายไป โดยไม่ต้องเขียน code ชั่วคราวมาถอดเอง
- ตรวจค่า message ใน Kafka ได้เร็ว — payload ใน topic ที่ใช้ protobuf มักโผล่ใน log เป็น base64 วางลงเครื่องมือนี้แล้วเห็นค่าจริงของทุก field ทันที
- เห็นโครงสร้าง nested message เป็นต้นไม้ — message ที่ซ้อนกันหลายชั้นถูกแยกเป็น hierarchy ชัดเจน เจาะเข้าไปดูชั้นในได้ทีละระดับ
- ทำงาน offline ทั้งหมด — ทุกการ decode เกิดขึ้นบนเครื่องคุณ ไม่มีการอัปโหลดข้อมูลไปที่ใด เหมาะกับข้อมูล production และระบบ internal
- เรียนรู้ wire format ไปพร้อมกัน — ได้เห็น tag byte และ varint ตัวจริงช่วยให้เข้าใจ protobuf เชิงลึกมากกว่าอ่านเอกสารอย่างเดียว
ฟีเจอร์หลัก
| ฟีเจอร์ | ทำอะไร |
|---|---|
| รับ input แบบ base64 หรือ hex | วาง payload ในรูปแบบไหนก็ได้ ทูลจะแปลงเป็น bytes ให้ก่อนเริ่ม decode |
| Decode แบบไม่มี schema | อ่าน wire format โดยตรง ไม่ต้องมีไฟล์ .proto หรือ generated code |
| แสดง field number และ wire type | บอกชัดว่าแต่ละ field คือหมายเลขอะไร และถูกเข้ารหัสด้วย wire type ใด |
| ถอดค่า varint และ string | แสดงค่าตัวเลขจาก varint และข้อความจาก length-delimited ให้อ่านได้ทันที |
| ต้นไม้ nested message | แสดง message ที่ซ้อนกันเป็น hierarchy พร้อมตรวจช่วง field number ให้ |
| รัน offline ใน browser | ทุกอย่างประมวลผลบนเครื่องคุณ ไม่มีข้อมูลออกนอกเครื่องแม้แต่ไบต์เดียว |
รายละเอียดเพิ่มเติม:
- การตรวจช่วง field number ช่วยเตือนตั้งแต่เนิ่น ๆ เมื่อ bytes ที่วางอาจไม่ใช่ protobuf หรือ copy มาผิดจุด ทำให้ไม่เสียเวลาไล่หา bug ผิดทาง
- รองรับทั้ง hex ที่มีและไม่มี prefix 0x ทำให้วาง payload จาก dump หรือ log หลากหลายแหล่งได้สบาย
- ใช้ได้ทั้งกับ payload ของ gRPC และค่า message ที่เก็บใน Kafka จึงเป็นทูลเดียวจบสำหรับงาน debug protobuf
วิธี Decode Payload Protobuf
- เปิด Protobuf Decoder ใน browser ของคุณ
- เตรียม payload — ถ้ามาจาก log ที่เป็น base64 ให้ copy มาทั้งก้อน ถ้ามาจาก dump ที่เป็น hex ให้ copy ลำดับไบต์มาให้ครบ
- เลือกโหมด input เป็น base64 หรือ hex ให้ตรงกับต้นทาง แล้ววาง payload ลงช่องใส่ข้อมูล
- กดปุ่ม decode แล้วอ่านผลลัพธ์ที่แสดง field number, wire type, ค่า varint และ string ของแต่ละ field
- เจาะดูต้นไม้ nested message สำหรับ field ที่ซ้อนอยู่ชั้นใน แล้วใช้ข้อมูลที่ได้ต่อในงาน debug ของคุณได้เลย
Wire Format อธิบายแบบเข้าใจง่าย
หัวใจของ protobuf คือทุก field ใน message เริ่มด้วย tag byte หนึ่งตัว (หรือหลายตัวถ้า field number ใหญ่) ซึ่งรวมสองอย่างไว้ด้วยกัน ได้แก่ field number อยู่ที่บิตบน คำนวณจากการเอา tag ไป shift ขวา 3 บิต และ wire type อยู่ที่ 3 บิตล่าง คำนวณจากการเอา tag AND กับ 7 อีกมุมหนึ่งก็คือ tag = (field number × 8) + wire type
wire type ที่พบบ่อยมีสี่แบบ:
- varint (0) — ตัวเลขจำนวนเต็มอย่าง int32, int64, bool และ enum เข้ารหัสแบบ variable-length ค่าเล็กใช้ไบต์น้อยมาก
- 64-bit (1) — double หรือ fixed64 ใช้ความยาวคงที่ 8 ไบต์
- length-delimited (2) — string, bytes, packed repeated และ nested message โครงสร้างคือ tag ตามด้วยความยาวแล้วตามด้วยข้อมูลดิบ
- 32-bit (5) — float หรือ fixed32 ใช้ความยาวคงที่ 4 ไบต์
การเข้ารหัส varint ใช้เทคนิค 7 บิตต่อไบต์ ไบต์แรกเก็บ 7 บิตล่างของค่า และตั้งบิตสูงสุดเป็น 1 ถ้ายังมีต่อ ไบต์ถัดไปเก็บ 7 บิตถัดไปอีกทอด เช่น ค่า 150 จะถูกเขียนเป็นไบต์ 96 01 ส่วน string และ nested message ใช้ wire type 2 เหมือนกัน คือ tag + ความยาว (เป็น varint) + ข้อมูลดิบ
ความฉลาดของการ decode แบบไม่มี schema อยู่ตรงนี้ เครื่องมือจะลองตีความข้อมูลข้างใน wire type 2 เป็นข้อความ UTF-8 ถ้าอ่านออกก็แสดงเป็น string แต่ถ้าข้างในยัง parse เป็น protobuf ได้อีกชั้น ก็จะแสดงเป็น nested message ต่อเป็นต้นไม้ ทำให้ debug ได้โดยไม่ต้องรู้ชื่อ field เลย ลองดูตัวอย่างระดับ byte สั้น ๆ:
bytes : 0A 08 68 65 6C 6C 6F 21 21 21 10 96 01 0A = tag → field 1, wire type 2 (length-delimited) 08 = ความยาว 8 ไบต์ → "hello!!!" 10 = tag → field 2, wire type 0 (varint) 96 01 = varint ค่า 150
เพราะทุกอย่างถูกเก็บในโครงสร้างที่อ่านได้แบบนี้ การถอดโดยไม่มี schema จึงเป็นไปได้จริง และนั่นคือเหตุผลที่ Protobuf Decoder ใช้ debug ได้ทันทีแม้ไฟล์ .proto จะหายไปแล้ว
กรณีใช้งานจริง
วิเคราะห์คำขอ gRPC ที่ส่งผิด
สมมติ endpoint ของ gRPC ส่ง error กลับมาแปลก ๆ และคุณสงสัยว่าฝั่ง client encode field ไหนผิด เมื่อเปิด verbose log ได้ payload จะอยู่ในรูป base64 ให้วางลง Protobuf Decoder เช่นเห็นว่า field 2 เป็น varint ค่า 0 ทั้งที่ควรเป็นรหัส user ที่ไม่เป็นศูนย์ ปัญหาก็ชัดขึ้นทันทีว่าต้องไปแก้ที่ไหน
ส่องค่า message ใน Kafka
เวลา inspect topic ที่ใช้ protobuf ค่า value ที่เห็นใน console หรือเครื่องมือของ Kafka มักโชว์เป็น base64 หรือ bytes ที่อ่านไม่ออก copy ค่านั้นมาวางแล้ว decode จะเห็นว่าแต่ละ field มีค่าอะไร เช่น อยากรู้ว่า event ที่ consumer ข้ามไปเงียบ ๆ มี field 3 เป็นค่าอะไร ก็ได้คำตอบในไม่กี่วินาทีโดยไม่ต้องเขียน consumer ชั่วคราวขึ้นมาแก้ปัญหาเฉพาะหน้า
ถอด payload ที่ดักจับได้จาก network
เมื่อใช้ proxy หรือ tcpdump ดัก traffic ระหว่าง service แล้วได้ไบต์ดิบมาเป็น hex ให้วางลงโหมด hex แล้วดูโครงสร้างทั้งก้อนตั้งแต่ระดับ field จนถึง nested message ชั้นใน เหมาะกับงานสอบสวนเหตุการณ์ที่อยากรู้ว่าระบบส่งอะไรกันจริง ๆ และเพราะทำงาน offline ทั้งหมด จึงวิเคราะห์ข้อมูลจริงได้อย่างปลอดภัย
สอนคอนเซปต์ wire format ให้ทีม
ถ้าคุณเป็น tech lead ที่อยากให้ทีมเข้าใจ protobuf เชิงลึก ลองให้ทุกคนเขียน message ง่าย ๆ แบบ encode ด้วยมือ แล้วเอามา decode ในเครื่องมือนี้เทียบกัน การได้เห็น tag byte, varint และ length-delimited ตัวจริงจะช่วยให้ทีมจดจำและเข้าใจได้ดีกว่าอ่าน spec เฉย ๆ มาก
แนวทางปฏิบัติที่ดี
- ตัด header ที่ไม่ใช่ payload ออกก่อน — บาง protocol เช่น gRPC มี frame header 5 ไบต์นำหน้า (1 ไบต์ compressed flag + 4 ไบต์ความยาว) ตัดออกก่อนแล้วค่อย decode ผลจะสะอาดกว่า
- ยืนยันรูปแบบ input ให้แน่ใจ — ถ้า payload มาจาก log แบบ base64 ก็เลือกโหมด base64 อย่า decode ในโหมด hex แล้วงงว่าทำไมผลลัพธ์ไม่ออก
- ใช้ field number เทียบกับข้อมูลอ้างอิงที่มี — แม้ไม่มีไฟล์ .proto ก็มักมีเอกสารหรือ code เดิมบอกว่า field 1 คืออะไร ใช้ผล decode เทียบเพื่อแปลความหมายให้ครบ
- ระวังการตีความข้อมูลดิบ — wire type 2 อาจเป็น string หรือ nested message ก็ได้ ถ้าค่าดูแปลกให้ลองมองทั้งสองแบบก่อนสรุปผล
- เลือกเครื่องมือที่ offline กับข้อมูลลับเสมอ — ทูลนี้รันใน browser 100% จึงใช้กับ payload production ได้ แต่กับเครื่องมืออื่นควรเช็กเสมอว่าข้อมูลจะไม่ถูกส่งออกไปไหน
- เก็บ payload ต้นฉบับไว้อ้างอิง — ตอน debug ควรแนบ base64 ต้นทางไว้ใน ticket เพื่อให้เพื่อนร่วมทีม decode ซ้ำแล้วได้ผลเดียวกัน
พร้อมลองแล้วหรือยัง เปิด Protobuf Decoder วาง payload แรกของคุณลงไป แล้วคุณจะไม่ต้องกลับไปนั่งอ่านไบต์ดิบด้วยตาเปล่าอีก — ใช้ฟรี ทำงาน offline และไม่มีข้อมูลของคุณออกจากเครื่องแม้แต่ไบต์เดียว
เครื่องมือที่เกี่ยวข้องที่คุณอาจสนใจ:
- Base64 Encoder — เข้ารหัสและถอดรหัสข้อความเป็น base64 ได้ทันที
- Hex Viewer — สำรวจไบต์ดิบของไฟล์หรือข้อมูลในรูปแบบ hex dump
- JSON to Protobuf Schema — แปลง JSON เป็นไฟล์ .proto เมื่อพร้อมสร้าง schema อย่างเป็นทางการ
ขอให้ถอดรหัสอย่างสนุก!
คำถามที่พบบ่อย
ถ: ถอด payload โดยไม่มีไฟล์ .proto ได้จริงเหรอ?
ตอบ: ได้ครับ เพราะ wire format ของ protobuf เก็บ field number และ wire type ไว้ใน tag byte ของทุก field เครื่องมือจึงอ่านโครงสร้างได้ตรง ๆ เพียงแต่จะไม่รู้ชื่อ field เชิงความหมาย คุณต้องเทียบกับเอกสารหรือ code เดิมเพิ่มเติมเอง
ถ: payload ของ gRPC วางตรง ๆ แล้ว decode ไม่ออก ต้องทำอย่างไร?
ตอบ: message ของ gRPC มักมี frame header 5 ไบต์นำหน้า คือ 1 ไบต์ compressed flag กับ 4 ไบต์ความยาว message ให้ตัด 5 ไบต์แรกออกก่อน แล้ว decode เฉพาะส่วน payload ผลจะออกเป็นปกติ
ถ: เครื่องมือนี้ส่งข้อมูลของฉันขึ้นเซิร์ฟเวอร์ไหม?
ตอบ: ไม่ส่งครับ ทุกอย่างประมวลผลใน browser ของคุณ ทำงานได้แม้ตัดการเชื่อมต่ออินเทอร์เน็ต จึงใช้กับ payload ที่มีข้อมูลจริงได้อย่างปลอดภัย
ถ: ถอดแล้วได้ค่า string ที่อ่านไม่ออก แปลว่าอะไร?
ตอบ: มีโอกาสว่า field นั้นเป็น bytes ดิบ ไม่ใช่ข้อความ UTF-8 หรือข้อมูลข้างในเป็น nested message ที่ไม่ได้เริ่มด้วย tag ที่ถูกต้อง ลองดูว่าเจาะเข้าไปเป็น message ชั้นในได้หรือไม่ และเทียบกับ schema หรือเอกสารที่รู้จัก
ถ: field number เกิน 15 ต้องใช้หลายไบต์จริงไหม?
ตอบ: จริงครับ tag byte เก็บ field number ได้ถึง 15 เพราะ 3 บิตล่างต้องเก็บ wire type ไปแล้ว field number 16 ขึ้นไปจะใช้ varint หลายไบต์ในส่วน tag ซึ่งเครื่องมือถอดให้ได้ตามปกติ