1 คะแนน โดย GN⁺ 2024-08-21 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ที่ jumpcomedy.com ราว 4 ทุ่ม การเรียก HTTP POST ของ RTK Query ล้มเหลวทั้งหมดจนฟังก์ชันของเว็บไซต์พัง ทั้งที่บนเครื่องโลคัลทำงานปกติ จึงยากต่อการตามหาสาเหตุ
  • ระหว่างที่คำร้องเรียนจากลูกค้าสะสม ผู้ดูแลต้องรับมือกับเหตุขัดข้องเพียงลำพังโดยไม่มี ทีมซัพพอร์ตโปรดักชัน, SRE, วิศวกรอาวุโส หรือผู้จัดการ
  • TypeError ที่เกี่ยวกับ fetch ในเบราว์เซอร์ไม่ได้กลายเป็นเบาะแสโดยตรง เพราะ GET และ DELETE ยังทำงานปกติ
  • ตรวจทั้ง Sentry, ฐานข้อมูลโปรดักชัน, Cloudflare, การอัปเดต Chrome และการย้อนกลับไปเวอร์ชันก่อนหน้าแล้วก็ยังไม่เปลี่ยนแปลง แต่เมื่อใส่ PostHog api_key ที่ปล่อยว่างไว้ในโลคัลกลับทำให้เกิดปัญหาซ้ำได้
  • หลังจากถอด PostHog ออก ฟังก์ชันทั้งหมดกลับมาปกติ และภายหลังก็พบเหตุขัดข้องแบบเดียวกันใน GitHub issue ของ PostHog และ Redux Toolkit จึงชี้ว่าเป็น ผลกระทบจากเครื่องมือภายนอก

แรงกดดันที่เกิดจากเหตุขัดข้อง

  • jumpcomedy.com เริ่มตั้งแต่ราว 4 ทุ่ม การเรียก HTTP POST ที่อิง RTK Query ล้มเหลวทั้งหมด ทำให้ฟังก์ชันสำคัญทำงานไม่ได้ตามปกติ
  • แม้จะมีการเปลี่ยนแปลงที่เพิ่ง deploy ไปไม่นาน แต่ก็ไม่มีอะไรที่ดูเป็นต้นเหตุ และในสภาพแวดล้อมโลคัลก็ไม่สามารถทำให้ปัญหาเกิดซ้ำได้ จึงยิ่งตามแกะรอยได้ยาก
  • มีการขอความช่วยเหลือไปยัง Discord ของ NextJS และ Vercel แต่ไม่ได้รับคำตอบ และก็ไม่มี ทีมซัพพอร์ตโปรดักชัน ที่จะรับช่วงการรับมือเหตุขัดข้องต่อได้
  • อีเมลจากลูกค้ายังคงเพิ่มขึ้นต่อเนื่อง
    • สอบถามว่าไม่สามารถเปลี่ยนราคากิจกรรมได้
    • สอบถามว่าไม่สามารถลบโค้ดโปรโมชันได้
  • เพราะลูกค้าธุรกิจขนาดเล็กพึ่งพาบริการนี้อยู่ ผู้ดูแลจึงรู้สึกอับอาย เศร้า ไร้ความสามารถ และมีอาการ imposter syndrome

กระบวนการดีบักและการยืนยันสาเหตุ

  • ข้อผิดพลาดในเบราว์เซอร์คือ TypeError ที่ fetch ทำงานพร้อม request object ที่ถูกใช้ไปแล้ว แต่ก็ไม่ได้ชี้ไปยังสาเหตุจริง
  • มีการเพิ่ม console.log() และ breakpoint หลายจุดเพื่อตรวจดู header, ความยาว API token, ลำดับการเรียก ฯลฯ แต่ก็ยังไม่เจอสาเหตุที่ชัดเจน
  • เคยสงสัยว่าอาจเป็นเพราะ Chrome อัปเดต แต่เมื่อทำให้ปัญหาเกิดซ้ำได้ใน Firefox และ Edge ด้วย จึงไม่ใช่ปัญหาที่เกิดจากเบราว์เซอร์เพียงอย่างเดียว
  • แม้ย้อนกลับไปใช้เวอร์ชันเก่าก็ยังล้มเหลวเหมือนเดิม
    • เวอร์ชันเมื่อหนึ่งเดือนก่อนก็ยังล้มเหลว
    • เวอร์ชันเมื่อสามเดือนก่อนก็ยังล้มเหลว
    • เวอร์ชันเมื่อหนึ่งปีก่อนก็ยังล้มเหลว
  • เพื่อให้ความต่างระหว่างโลคัลกับโปรดักชันลดลง จึงตรวจหลายจุดที่เป็นไปได้
    • เอา Sentry ออกจากโปรดักชัน: ไม่มีการเปลี่ยนแปลง
    • ให้โลคัลเชื่อมกับฐานข้อมูลโปรดักชัน: ไม่มีการเปลี่ยนแปลง
    • ปิด Cloudflare: ไม่มีการเปลี่ยนแปลง
  • บนโลคัลมีการปล่อย PostHog api_key ว่างไว้เพื่อลดค่าใช้จ่าย และเมื่อเพิ่มค่านี้เข้าไปก็ทำให้ปัญหาเดียวกันเกิดซ้ำได้
  • เมื่อเอา PostHog ออกในคอมมิตถัดไป ฟังก์ชันทั้งหมดก็กลับมาทำงานปกติ
  • ต่อมามีการยืนยันปัญหาเดียวกันนี้ผ่าน GitHub issue ด้วย

1 ความคิดเห็น

 
GN⁺ 2024-08-21
ความคิดเห็นจาก Hacker News
  • ตอนทำงานเป็น SRE อยู่ 1 ปีในบริษัทข้ามชาติขนาดใหญ่ ผมสามารถหลุดออกจากโหมด “แพนิก” แบบที่บทความพูดถึงได้
    ในมุมธุรกิจ ปัญหาทุกอย่างดูเหมือนเหตุการณ์วันสิ้นโลก และในสถานการณ์แบบนั้นก็แพนิกได้ง่าย แต่จริง ๆ แล้วกรณีที่แย่ขนาดนั้นมีน้อยมาก และต่อให้แย่ก็มักจะรอดไปได้
    ในสถานการณ์แบบนี้ สิ่งสำคัญคือ หยุด 5–10 นาที ก่อนจะลงมือแก้ทันที แล้วพยายามวาดภาพสถานการณ์ให้ชัดเจนที่สุด ความกลัวขัดขวางการตัดสินใจด้วยเหตุผล และถ้ากดปุ่มมั่ว ๆ ตอนกำลังแพนิก ปัญหาอาจยิ่งพันกันกว่าเดิม เคล็ดลับของผมคือเอาน้ำเย็นจัดสาดหน้าและมือเพื่อตัดวงจรความกลัว
    พอเจอเรื่องแบบนี้สักสองสามครั้ง ก็จะรู้ว่ามันโอเคกว่าที่คิด และเกิดความมั่นใจว่าเคยรับมือกับสถานการณ์แย่ ๆ มาก่อน จึงรู้ว่าต่อให้ไม่มีใครให้ขอความช่วยเหลือก็ยังรับมือได้

    • ถ้ามีอะไร “พัง” บริษัทอาจแตกตื่นได้ แต่ต้องจำไว้ว่าบริษัทกลับไม่ตื่นตระหนกเลยกับปัญหาอื่น ๆ ที่จริงแล้วอาจสำคัญกว่านั้นด้วยซ้ำ
      เช่น ซอฟต์แวร์ที่ซื้อมาแต่ทำอะไรไม่ได้เลยเพราะจัดคนหรือคอนฟิกพลาด, พนักงานเสียเวลาปีละหลายพันชั่วโมงกับประสบการณ์ผู้ใช้ที่แย่และข้อกำหนดไร้ความหมาย, ความสามารถบางอย่างที่ถูกปล่อยทิ้งไว้โดยไม่ก่อประโยชน์, การประชุมไร้ประโยชน์ที่กินเวลาทุกวัน, ฟีเจอร์ที่มีอยู่เพียงเพื่อให้ผ่านข้อกำหนดการตรวจสอบ, หรือผู้บริหารที่ยังคงผลาญเงินบริษัทต่อไป
      ดาวน์ไทม์ไม่ได้ดูแย่กว่าปัญหาเหล่านี้ แต่กลับดึงดูดความสนใจและความแพนิกได้มากกว่ามาก ให้ความรู้สึกเหมือนการเปรียบเทียบระหว่างการก่อการร้ายกับโรคหัวใจ บริษัทไม่ได้ใส่ใจการนอนหรือสุขภาพจิตของคุณ และจะผลักดันไปให้ไกลที่สุดเท่าที่ทำได้ ไม่ได้หมายความว่ามีเจตนาร้าย แต่ในแง่นี้ก็เหมือนคนที่คอยรังแก ยิ่งคุณถอยเท่าไร เขาก็ยิ่งรุกมากเท่านั้น
    • ความผิดพลาดเลวร้ายที่สุดที่เคยเห็นระหว่างเหตุขัดข้องจริง ๆ มักมาจาก การตอบสนองเกินเหตุ
      คติในการเขียนโปรแกรมอย่างหนึ่งของผมคือ “ห้ามมนตร์ดำ” ถ้าไม่เข้าใจว่าทำไมมันถึงทำงาน ก็ยังถือว่ายังไม่จบ
      ผมมองการรับมือเหตุขัดข้องแบบเดียวกัน ถ้าอธิบายอย่างสอดคล้องไม่ได้ว่าข้อเสนอของใครสักคนจะส่งผลอย่างไร ก็ไม่ควรทำตาม วันหนึ่งอาจมีจังหวะที่ต้องเหนี่ยวไกไปเลยก็ได้ แต่พอมองย้อนกลับไป สุดท้ายเหมือนไม่เคยมีกรณีแบบนั้นจริง ๆ
      เป็นเรื่องช็อกพอสมควรที่ได้เห็นผู้บริหารระดับสูงซึ่งปกติใจเย็นมาก ๆ เริ่มโยนตัวเลือกแก้ไขแบบสุ่ม ๆ ออกมาระหว่างเกิดเหตุขัดข้อง
    • ในทางกลับกัน คนที่ต้องเปลี่ยนราคางานอีเวนต์บน jumpcomedy.com ตอนตี 2 ประมาณบวกลบ 2 ไทม์โซน คงผิดหวังมาก บางคนในนั้นอาจถึงกับตายไปแล้วก็ได้
      ลองจินตนาการดูว่าความเสียหายจะหนักกว่านี้แค่ไหน ถ้ามีใครไปห้ามนักพัฒนาคนเดียวรายนี้ว่า “อย่าพยายามดัน fetch ให้เป็นกระแส”
    • VP ที่เจ๋งที่สุดคนหนึ่งที่ผมรู้จักมักพูดว่า “ช้าคือราบรื่น และราบรื่นคือเร็ว
      คำพูดที่ว่าความกลัวขัดขวางการตัดสินใจด้วยเหตุผลนั้นถูกต้อง และผมอยากเสริมว่าความกลัวติดต่อกันได้ง่ายมากด้วย เมื่อคนปฏิบัติงานเห็นผู้นำ ผู้จัดการ หรือเพื่อนร่วมงานแพนิก พวกเขาก็มักจะแพนิกตามไปด้วย โชคดีที่ VP ของผมใจเย็นเสมอ และให้ความสำคัญกับความชัดเจนมากกว่าการลงมือทำ
    • ท้ายที่สุด คุณไม่ได้เป็นคนรับความเสี่ยงนั้นเอง มันไม่ใช่บริษัทของคุณ และบริษัทสามารถตัดคุณออกได้ทุกเมื่อโดยไม่ต้องบอกล่วงหน้า และในความเป็นจริงก็จะทำแบบนั้น แน่นอนว่าถ้าเป็นบริษัทของคุณเองก็เป็นข้อยกเว้น
  • ผมไม่ค่อยแน่ใจว่านี่คือ การล่มสลายทางจิตใจ หรือเปล่า และอาจทำให้คนที่เคยล่มสลายจริง ๆ จากความเครียดด้านเทคโนโลยีเข้าใจผิดได้
    ของผมเคยเกิดขึ้นแค่ครั้งเดียว และนั่นคืออาการวิตกกังวลกำเริบ ผมโชคดีมากที่ภรรยาอยู่ข้าง ๆ คอยอธิบายสถานการณ์และช่วยให้ผมเข้าใจว่ากำลังเจออะไร ภรรยาเคยเจอหลายครั้ง แต่สำหรับผมนั่นเป็นครั้งแรก และโชคดีที่เป็นครั้งสุดท้าย
    เรื่องแบบนี้เกิดขึ้นกับคนเราได้ และตัวมันเองไม่ได้ผิดอะไรเลย สิ่งสำคัญมากคือต้องยอมรับให้ได้จากข้างในว่านั่นไม่ได้แปลว่าคุณมีข้อบกพร่องหรืออ่อนแอ
    ในกรณีของผม สิ่งที่ทำให้มันหยุดลงได้ในที่สุดคือ Xanax และเพราะมันทำให้ผมนอนหลับได้ ผมจึงคิดว่าคุ้มที่จะมีไว้ใกล้มือ
    สิ่งที่อยากบอกคือ ความคิดที่รุกรานจิตใจ กับภาวะที่ควบคุมไม่ได้จริง ๆ และทำให้ทำงานไม่ได้อย่างอาการวิตกกังวลกำเริบหรือแพนิกกำเริบนั้นต่างกัน ถ้าเกิดเรื่องแบบนั้น คุณจะทำงานไม่ได้ และนั่นก็ไม่เป็นไร

    • https://www.webmd.com/mental-health/signs-nervous-breakdown
      ไม่ใช่ทุกการล่มสลายจะมาในรูปแบบแพนิกหรือวิตกกังวลกำเริบ มันอาจแสดงออกแบบนั้นได้ แต่ไม่ใช่วิธีเดียว ความเครียดแสดงออกแตกต่างกันมากในแต่ละคน และแม้แต่ในแต่ละตัวกระตุ้นความเครียด
      เราไม่รู้ได้ว่าในหัวของคนนั้นเขาเจออะไรจริง ๆ ดังนั้นการ “วินิจฉัย” จากภายนอกแทบเป็นไปไม่ได้เลย ถึงจะไม่ใช่อาการแพนิกกำเริบเต็มรูปแบบ แต่ก็ฟังดูเหมือนเขาเป็นอัมพาตในการทำงานอยู่หลายชั่วโมง
    • ควรระวังกับคำพูดว่า “ควรมี Xanax ไว้ใกล้มือ”
      พอลองค้นออนไลน์ดู เหมือนว่า Xanax อาจทำให้เสพติด ได้
      https://www.drugs.com/xanax.html
      ดูไม่ใช่ยาประเภทที่ควรกินแบบสบาย ๆ
    • ผมไม่ควรต้องถึงขั้นกินยาเพื่อรับมือกับฟีเจอร์ที่ปล่อยออกมาแบบลวก ๆ อยู่เสมอ การเปลี่ยนแปลงที่ดันเข้าไปโดยไม่คิดอะไร และ สัญญาณเตือน PagerDuty ตอนตี 3 ที่ตามมา
      มีโอกาสสูงที่เราจะได้เห็นคนกลุ่มใหญ่ที่เข้าวงการเทคโนโลยีช่วงกลางทศวรรษ 2000 ตายจากโรคที่เกี่ยวข้องกับความเครียด
    • สิ่งหนึ่งที่ผมไม่คาดคิดตอนทำงานในบริษัทเทคโนโลยีระดับองค์กร คือมี เพื่อนร่วมงานที่กิน Xanax เป็นประจำ มากแค่ไหน
      ในฐานะคนที่มีความวิตกกังวลรุนแรงมาตลอดชีวิต แค่ความคิดว่ายาเม็ดเดียวที่ทำให้เสพติดได้อาจลบมันทั้งหมดไปได้ก็น่ากลัวแล้ว ผมคงต้องเกาะมันไปตลอดชีวิตแน่ ๆ
    • จริง ๆ แล้วผิดหวัง เพราะมันเป็นแค่เรื่อง การดีบัก dependency ธรรมดา ผมเคยรู้สึกว่าเกือบถึงจุดล่มสลายอยู่สองสามครั้ง เลยหวังว่าบทความจะเกี่ยวข้องกับผมมากกว่านี้
  • ความเครียดของคนคนนี้เกิดจากโค้ดหนึ่งบรรทัดของ PostHog คอมมิตที่ถูก revert คืออันนี้: https://github.com/PostHog/posthog-js/pull/1371/commits/7598...
    ผมเห็นบทเรียนสองอย่างจากเรื่องนี้ อย่างแรก ถ้าคุณ deploy อะไรออกไป คุณก็เป็นเจ้าของมัน ดังนั้นยิ่ง deploy น้อยเท่าไรก็ยิ่งดี และควรลด dependency ให้น้อยที่สุด อย่างที่สอง ควรเอาสิ่งที่ไม่สำคัญออกจาก critical path คอมเพรสเซอร์แอร์พังไม่ควรทำให้เครื่องยนต์ดับ ในเบราว์เซอร์ทำให้สำเร็จได้ยากมาก แต่ก็คุ้มค่าที่จะลอง

  • ที่แย่กว่านั้นคือ PostHog ดูเหมือนจะอัปเดตบางส่วนของโค้ดตัวเองแบบไดนามิกตอนรันไทม์ และไม่ได้ bundle ไว้ตอน build
    ในเอกสารมีตัวเลือกขั้นสูงสำหรับรวม dependency ทั้งหมดเข้าไปใน build ผมเข้าใจว่าทำไมถึงทำแบบนั้น และผมอาจเข้าใจผิดก็ได้ แต่ในมุมผู้ใช้ ผมคาดหวังว่า การโหลดโค้ดที่รันแบบหน่วงเวลา ไม่ควรเป็นค่าเริ่มต้น แต่ควรเป็นตัวเลือกสำหรับ optimization มากกว่า ควรใช้เฉพาะเมื่อการ bundle ทั้งหมดทำให้การส่งมอบล่าช้าอย่างรุนแรงเท่านั้น

    • บทเรียนเหล่านี้มีคุณค่าแน่นอน แต่หลังจากนั้นก็จะมีใครสักคนจากฝั่งการตลาดมาบอกให้ใส่ PostHog หรือสคริปต์ติดตามอื่น ๆ ลงในไซต์ และไม่ยอมรับคำปฏิเสธ
  • ดูเหมือนว่า bug จะอยู่ใน window.fetch ที่ถูก monkey-patch
    https://github.com/PostHog/posthog-js/blob/759829c67fcb8720f...
    บทเรียนใหญ่ที่สุดตรงนี้คือ ถ้าคุณสร้างไลบรารียอดนิยมแล้วทำ monkey-patch ฟังก์ชัน global การทดสอบต้องแน่นมากจริง ๆ
    “เผื่อไว้ ลองครอบ PostHog call ด้วย try/catch กัน” กับ “เพราะ PostHog เลยทำให้ส่งคำขอ POST ด้วย fetch() ไม่ได้จริง ๆ” เป็นคนละเรื่องกันโดยสิ้นเชิง

    • ผมลองดูเพื่อหาว่าทำไม test ถึงจับเรื่องนี้ไม่ได้ และพบว่าแค่เรียก fetch แบบธรรมดาก็อาจเกิด error ได้แล้ว นอกจาก test coverage สำหรับวิธีต่าง ๆ ในการใช้ fetch จะไม่พอแล้ว ดูเหมือนว่า การ mock มากเกินไป ก็มีส่วนด้วย: https://github.com/PostHog/posthog-js/blob/main/src/_tests...
      เมื่อทั้งฟังก์ชัน fetch และ XHR ถูก mock ให้ไม่ทำอะไรเลย แน่นอนว่ามันย่อมจับปัญหาที่เกิดจากการโต้ตอบกับ native API หรือไลบรารีอื่นด้านล่างไม่ได้ มีการตั้งค่า Cypress ไว้ด้วย แต่ไม่รู้ว่าทำไมถึงยังพยายาม mock browser API
    • ขอบคุณที่ชี้ประเด็นนี้ ผมไม่ได้อ่านบทความละเอียดนัก แต่สงสัยอยู่ว่า monitoring library ทำให้ทั้งแอปพลิเคชันล่มได้อย่างไร
      ถ้า integrate อย่างสมเหตุสมผล ต่อให้เลวร้ายที่สุดก็น่าจะเป็นแค่การประมวลผล monitoring event ล้มเหลวเท่านั้น
      การที่ PostHog patch ฟังก์ชัน global ที่สำคัญมาก ควรเป็น feature ที่ document ไว้อย่างชัดเจน เพื่อให้คนใช้รับรู้ และนึกถึงได้อย่างสมเหตุสมผลเวลา debug ปัญหาที่อธิบายจากภายนอกได้ยาก
    • ดูเหมือนมันทำงานตามนิยามนะ มัน hog คำขอ POST ไปรึเปล่า?
    • เรื่องแบบนี้พบได้บ่อยในชุดเครื่องมือ analytics ประเภทนี้ ผมไม่รู้เหมือนกันว่าจะทดสอบทุกอย่างจริง ๆ ได้อย่างไรเมื่อไปแตะ API สำคัญขนาดนี้
      ตัวอย่างเช่น Heap Analytics จนถึงเดือนนี้ ก็ยังไปแตะบางอย่างภายใน Hotwire ทำให้ Hotwire พังแบบสุ่มโดยสิ้นเชิง และทำให้ทุกคลิกกลายเป็นการโหลดทั้งหน้า จากประสบการณ์ของผม มันกระทบ 30–60% ของ page load แก้ได้ก็จริง แต่ต้อง debug เกิน 50 ชั่วโมงกว่าจะทำให้ Heap โหลดหลัง JavaScript ของ Hotwire ทั้งหมดได้
  • อย่างที่หลายคนพูดกัน bug ที่นำไปสู่ความเครียดยามดึกนี้คือการเปลี่ยนโค้ดหนึ่งบรรทัดใน ไลบรารี PostHog[0]
    ผมมองว่านี่เป็นเครื่องเตือนใจถึงความสำคัญของการตั้งชื่อตัวแปรให้ตรงความหมาย
    โค้ด res = await originalFetch(url, init) ดูไม่มีพิษภัยพอสมควร แต่ตามที่ declaration ของ TypeScript แสดงไว้ parameter url ไม่จำเป็นต้องเป็น URL: url: URL | RequestInfo
    ปัญหาจะเกิดเมื่อมันไม่ใช่ URL แต่เป็นอ็อบเจกต์ RequestInfo เพราะตอนต้นของการ implement ฟังก์ชันมีการสร้าง Request object และมันถูก “consume” ไปแล้ว จึงนำกลับมาใช้ตรงนี้อีกไม่ได้
    ถ้าชื่อ parameter แม่นยำกว่านี้ เช่น urlOrRequestInfo ก็คงยากขึ้นที่จะพลาดปัญหาในการเปลี่ยนแปลงนี้
    เป็นความคิดที่คาดเดามากกว่านั้นอีก แต่ linear type จาก linear logic สามารถทำให้แนวคิดว่าค่าถูก “consume” กลายเป็นรูปแบบทางการได้ ดังนั้น type system ที่เหมาะสมก็อาจป้องกัน bug ประเภทนี้ได้
    [0] https://github.com/PostHog/posthog-js/pull/1351/commits/2497...

    • ปัญหาของระบบ type แบบ linear/affine คือกำแพงเริ่มต้นมันสูงมาก
      แค่ดู ownership semantics ของภาษาอย่าง Rust ก็พอแล้ว มันไม่ได้ถึงขั้นทะลุผ่านไม่ได้ และจะดีขึ้นโดยเฉพาะเมื่อมีประสบการณ์มากขึ้น แต่ก็เป็นภาระมากพอจนเป็นจุดที่ผู้เรียนบ่นกันมากที่สุด
  • เป็นบทความที่เครียดมากแต่ก็ตลกด้วย อย่างไรก็ตาม ส่วนที่โทษตัวเองนั้นให้ความรู้สึกคุ้นเคยเกินไป
    ผมดูแลแอป iOS/macOS ที่ค่อนข้างประสบความสำเร็จ และเคยปล่อย release ที่ทำให้ installation มากกว่า 350,000 ชุด พังยับ แม้จะไม่ใช่ความผิดของผมทั้งหมด แต่ก็แทบไม่ต่างกันเพราะมันเป็นผลิตภัณฑ์ของผม
    ตอนนั้นเหงื่อแตกและรู้สึกอับอายมากจริง ๆ แถมเพราะเป็น App Store ตัวแก้ก็ต้องผ่านกระบวนการ review ทำให้ใช้เวลานานขึ้น โชคดีที่หลังส่งไป 30 นาที ก็เข้าสู่การ review และได้รับอนุมัติในไม่กี่นาที

    • งานแรกในฐานะ developer ไม่ได้ “อนุญาต” ให้ผมทำของลูกค้าพังตั้งแต่อายุยังน้อยเพราะผมฉลาด แต่เพราะผมไร้ความสามารถ
      เมื่อสะสมประสบการณ์และย้ายมาสู่บทบาท leadership ผมตระหนักว่านั่นเป็นประสบการณ์ที่มีค่ามาก เมื่อก่อนมันอาจทำให้เครียด แต่ตอนนี้ความทรงจำนั้นไกลมากจนแทบเอื้อมไม่ถึงแล้ว ตอนนี้ผมไม่เครียดกับมันแน่นอน
      อาจเป็นประเด็นถกเถียงได้ แต่บางครั้งผมก็ปล่อยให้สมาชิกทีมช่วงต้นอาชีพทำ production environment พังบ้าง เมื่อผมมองเห็นล่วงหน้าและมั่นใจว่าเรากู้คืนได้รวดเร็ว
      การให้พื้นที่สำหรับความล้มเหลวเป็นเรื่องสามัญสำนึก แต่ผู้นำจำนวนมากจะขีดเส้นไว้ตรงความล้มเหลวที่กระทบลูกค้าจริง ๆ ถ้าเราอยู่ในสถานการณ์ที่พบได้บ่อยและโชคดีมาก ๆ คือไม่ได้สร้างสิ่งสำคัญอย่างซอฟต์แวร์ลงจอดเครื่องบิน ก็ควรให้ทีมได้สัมผัสเหตุขัดข้องใน production แม้ต้องแลกกับการที่ใครบางคนในเมืองสโปแคน รัฐวอชิงตัน ใช้ผลิตภัณฑ์ไม่ได้สักไม่กี่นาที
  • ขอบคุณที่เขียนเรื่องนี้ โดยเฉพาะภายใต้แรงกดดัน และมักจะเป็นทั้งคืน ผมชอบอ่านว่าผู้คนฝ่าฟันความท้าทายแบบนี้กันอย่างไร
    รู้สึกว่ามันดีขึ้นเพราะไม่ได้มีแค่ postmortem เชิงเทคนิค แต่ยังมี มุมมองแบบมนุษย์ ที่มักถูกลบออกจากเรื่องเล่าแบบนี้ด้วย เรื่องเล่าทางเทคนิคแบบนี้เป็นสิ่งที่คงมีแต่นักพัฒนารายเล็ก/คนเดียวหรือผู้ก่อตั้งเท่านั้นที่จะแชร์ได้อย่างอิสระ

  • แค่ดูวิธีที่เขาตามปัญหาก็เห็นก่อนเลยว่าเป็น โปรแกรมเมอร์ เขาไปดูโค้ดของตัวเอง และไปดู log ทั้งสองอย่างสมเหตุสมผล และทั้งสองอย่างอาจเป็นสาเหตุได้ แต่พลาดเบาะแสที่สำคัญที่สุดที่มีอยู่ นั่นคือ “บน localhost มันทำงานได้”
    ถ้าเป็น SRE, DevOps, วิศวกรแพลตฟอร์ม หรือไม่ว่าตำแหน่งที่ถูกเรียกในวันนั้นจะเป็นอะไร ผมคงโฟกัสที่ความแตกต่างระหว่างระบบที่ทำงานได้กับระบบที่ทำงานไม่ได้ คงค่อย ๆ เพิ่มแล้วเอาความแตกต่างออกทีละอย่าง หรือเอาออกแล้วใส่กลับเข้าไป จนกว่าจะเห็นอะไรบางอย่างทำงาน
    สิ่งที่ผมเห็นมีสองอย่าง 1) มีสภาพแวดล้อมที่ทำงานได้ 2) สภาพแวดล้อมที่ล้มเหลวนั้นเดิมทีก็เคยทำงานได้ แล้วจึงเริ่มล้มเหลว
    ไม่ได้หมายความว่าวิธีของผมเหนือกว่า แค่อยากชี้ให้เห็นความต่างของวิธีมองปัญหา ทั้งสองฝ่ายต่างตีวงแคบลงโดยยึดจากสิ่งที่ตัวเองรู้ ผมรู้ระบบ ส่วนคุณรู้โค้ด

    • สมัยนานมาแล้วตอนทำงานเป็นช่างอิเล็กทรอนิกส์ มีบอร์ดโปรเซสเซอร์ของ Perkin Elmer 7/32 กองหนึ่งที่ถูกถอดออกจาก service เป็นบอร์ดเสีย มีหลาย revision และแต่ละบอร์ดมี schematic ของ revision หนึ่งเท่านั้น
      ผมมองว่าไม่น่ามีทาง แต่ช่างที่อาวุโสกว่าและชาญฉลาดกว่าสอนวิธีให้
      เสียบบอร์ดดีเข้ากับ extender แล้วรันโปรแกรม diagnostics ที่ล้มเหลววนลูป ใช้ oscilloscope ดูทุก pin ของ connector แล้วจดบันทึก จากนั้นเปลี่ยนเป็นบอร์ดเสียแล้วทำซ้ำ
      สัญญาณไหนต่างกัน? ก็ไล่ย้อนกลับไปตามสัญญาณนั้น ถ้า schematic ไม่ตรง ก็ใช้ voltmeter กับตาวาด schematic ที่สะท้อนการเดินสายจริง
      เขาเรียกวิธีนี้ว่า “การ์ดดี - การ์ดเสีย” และมันใช้ได้จริง ผมคงไม่อ้างว่าคุ้มต้นทุน แต่ก็ซ่อมบอร์ดได้ทั้งหมด และทักษะการแก้ปัญหาวงจรอิเล็กทรอนิกส์ดิจิทัลของผมก็เพิ่มขึ้นมาก
      งานนี้เป็นงานแบบ “นักดับเพลิง” อย่างหนึ่ง คือรอให้ระบบพัง ดังนั้นต่อให้ช่าง 2 คนใช้เวลา 1 สัปดาห์กับแผงวงจรเดียวก็ไม่เป็นไร
  • “ลองย้อนกลับไปเวอร์ชันเมื่อหนึ่งเดือนก่อน ไม่ได้ แล้วสามเดือนก่อนล่ะ? ไม่ได้ ยังล้มเหลวอยู่ หนึ่งปีก่อนล่ะ? ไม่ได้เลย”
    เขาย้อนกลับเฉพาะโค้ดของตัวเอง แต่ยังใช้ อัปเดต PostHog ที่พังในวันเดียวกันอยู่หรือเปล่า? บทเรียนของผมคือ ต้องทำให้ย้อนกลับทุกอย่างได้ รวมถึง dependency ด้วย

    • PostHog ดูเหมือนจะโหลดเวอร์ชันล่าสุดของบางส่วนของตัวเองอยู่เสมอ
      https://github.com/PostHog/posthog/issues/24471#issuecomment...
      แม้จะมีตัวเลือกให้ bundle เองได้ก็ตาม
      https://github.com/PostHog/posthog/issues/24471#issuecomment...
    • นี่แหละคือบทเรียนสำคัญ ถ้าคุณ link ส่วนหนึ่งของแอปพลิเคชันจาก CDN อื่น การ deploy ของคุณเองก็แทบไม่มีความหมาย
      ผู้เขียนต้นฉบับจัดการได้ดี ด้านบวกของเหตุขัดข้องแบบนี้คือมันให้บทเรียนที่มีคุณค่ามาเป็นกอง
  • เป็นบทความที่ดีที่ทำให้เรานึกถึงคนที่อยู่เบื้องหลังบริการอีกครั้ง และยังแสดงกระบวนการ debugging ได้ดีด้วย
    ในความเป็นจริง ความกดดันไม่ได้ช่วยให้ debug ปัญหาได้เร็วขึ้น ปกติแล้วมันขัดขวางการคิดเสียมากกว่า ต้องพยายามเมินผลลัพธ์ให้มากที่สุดและใจเย็นเท่าที่ทำได้
    พวกเราส่วนใหญ่คงเคยเจอสถานการณ์คล้าย ๆ กันไม่มากก็น้อย แน่นอนว่าความเครียดจากการบริหารบริษัทของตัวเองย่อมหนักเป็นพิเศษ