0Pricing
Go Academy · บทเรียน

มิดเดิลแวร์สำหรับการบันทึกและ ID คำขอ

การบันทึกแบบมีโครงสร้างและการแทรก ID การติดตาม

มิดเดิลแวร์สำหรับการบันทึกและ ID คำขอ เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงต้องบันทึกแบบมีโครงสร้าง

บันทึกข้อความธรรมดาแยกวิเคราะห์ได้ยากเมื่อมีปริมาณมาก การบันทึกแบบมีโครงสร้าง (JSON หรือ key=value) ช่วยให้ตัวรวบรวมบันทึก เช่น Datadog, Loki และ ELK กรองและเชื่อมโยงรายการตามช่องข้อมูลได้

การสร้าง ID คำขอ

สร้าง ID ที่ไม่ซ้ำกันสำหรับแต่ละคำขอ (UUID หรือ ULID) ในมิดเดิลแวร์ แล้วแนบไว้กับส่วนหัวการตอบกลับและบริบท:

func RequestID(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        id := r.Header.Get("X-Request-ID")
        if id == "" { id = uuid.New().String() }
        w.Header().Set("X-Request-ID", id)
        ctx := context.WithValue(r.Context(), reqIDKey{}, id)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

มิดเดิลแวร์บันทึกล็อกด้วย slog

Go 1.21 เพิ่ม log/slog สำหรับการบันทึกแบบมีโครงสร้าง สามารถใช้ภายในมิดเดิลแวร์ได้:

func StructuredLogger(logger *slog.Logger) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            start := time.Now()
            cw := &captureWriter{ResponseWriter: w}
            next.ServeHTTP(cw, r)
            logger.Info("request",
                "method", r.Method,
                "path", r.URL.Path,
                "status", cw.status,
                "latency_ms", time.Since(start).Milliseconds(),
                "request_id", r.Context().Value(reqIDKey{}),
            )
        })
    }
}

captureWriter

ห่อ ResponseWriter เพื่อดักจับรหัสสถานะที่ตัวจัดการเขียน:

type captureWriter struct {
    http.ResponseWriter
    status int
}
func (cw *captureWriter) WriteHeader(code int) {
    cw.status = code
    cw.ResponseWriter.WriteHeader(code)
}
func (cw *captureWriter) Status() int {
    if cw.status == 0 { return http.StatusOK }
    return cw.status
}

การเพิ่ม ID คำขอในทุกบรรทัดบันทึก

สร้างตัวบันทึกลูกสำหรับแต่ละคำขอโดยเติม ID ไว้ล่วงหน้า แล้วจัดเก็บตัวบันทึกนั้นในบริบท:

reqLogger := logger.With("request_id", id)
ctx := context.WithValue(r.Context(), loggerKey{}, reqLogger)

การดึงตัวบันทึกจากบริบท

ฟังก์ชันช่วยเหลือสำหรับดึงตัวบันทึกที่มีขอบเขตตามคำขอจากตัวจัดการหรือบริการใด ๆ:

func LoggerFromContext(ctx context.Context) *slog.Logger {
    l, ok := ctx.Value(loggerKey{}).(*slog.Logger)
    if !ok { return slog.Default() }
    return l
}

ระดับการบันทึก

ใช้ระดับให้เหมาะสม ได้แก่ Debug สำหรับรายละเอียดระหว่างการพัฒนา Info สำหรับสรุปคำขอ Warn สำหรับความผิดปกติที่กู้คืนได้ และ Error สำหรับความล้มเหลวที่ต้องดำเนินการ อย่าบันทึกช่องข้อมูลที่มีความละเอียดอ่อน เช่น โทเคนและรหัสผ่าน

กลุ่มช่วงเวลาแฝง

ใส่เวลาแฝงของคำขอในทุกบรรทัดบันทึก แล้วรวมเป็นกลุ่มฮิสโตแกรมในระบบเมตริกของคุณ (Prometheus) เพื่อติดตามเปอร์เซ็นไทล์ P50/P95/P99

รหัสสหสัมพันธ์ในไมโครเซอร์วิส

ส่งต่อส่วนหัว X-Request-ID จากคำขอขาเข้าทั้งหมดไปยังการเรียกใช้ HTTP และ gRPC ขาออกทั้งหมด เพื่อเปิดใช้การติดตามแบบกระจายโดยไม่ต้องมีระบบติดตามเต็มรูปแบบ

การสุ่มตัวอย่างล็อก

สำหรับบริการที่มีปริมาณการใช้งานสูง ให้สุ่มบันทึกล็อกระดับ debug/info เช่น บันทึก 1 จากทุก 100 คำขอที่ระดับ debug เพื่อลดค่าใช้จ่ายในการจัดเก็บ โดยยังคงบันทึกล็อกข้อผิดพลาดไว้อย่างครบถ้วน

zap เทียบกับ slog

zap (Uber) ทำงานเร็วกว่า slog สำหรับบริการที่มีปริมาณงานสูง แต่ต้องตั้งค่ามากกว่า ส่วน slog เป็นไลบรารีมาตรฐาน พกพาได้ และเพียงพอสำหรับบริการส่วนใหญ่ ควรเลือกใช้ slog เว้นแต่ผลการทดสอบประสิทธิภาพจะแสดงว่ามีคอขวด

ตรวจสอบอย่างรวดเร็ว

เหตุใดจึงต้องใช้ captureWriter ในมิดเดิลแวร์การบันทึกล็อก

สรุป: การบันทึกล็อกและรหัสคำขอ

ประเด็นสำคัญ:

  • สร้างหรือส่งต่อ X-Request-ID ในมิดเดิลแวร์ แล้วจัดเก็บไว้ในบริบท
  • ใช้ slog สำหรับล็อกแบบมีโครงสร้างพร้อมฟิลด์แบบคีย์-ค่า
  • captureWriter ดักจับรหัสสถานะเพื่อใช้บันทึกล็อกหลังตัวจัดการทำงานเสร็จ
  • ส่งต่อรหัสสหสัมพันธ์ไปยังการเรียกใช้ปลายทางทั้งหมด

คำถามที่พบบ่อย

บทเรียน “มิดเดิลแวร์สำหรับการบันทึกและ ID คำขอ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “มิดเดิลแวร์สำหรับการบันทึกและ ID คำขอ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “มิดเดิลแวร์สำหรับการบันทึกและ ID คำขอ”

การบันทึกแบบมีโครงสร้างและการแทรก ID การติดตาม คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “มิดเดิลแวร์สำหรับการบันทึกและ ID คำขอ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม

ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐานสายโซ่มิดเดิลแวร์ HTTP
  2. มิดเดิลแวร์สำหรับการบันทึกและ ID คำขอ
  3. มิดเดิลแวร์การยืนยันตัวตนและจำกัดอัตรา
  4. มิดเดิลแวร์ CORS และกู้คืนจาก panic
← กลับไปที่ Go Academy