Catching bugs on the client-side: how we developed our error tracking system
Bài tóm tắt Bumble 2020 3. Quy mô lớn Độ khó: Trung bình
Bumble · 2020 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc
Bối cảnh
- Bumble và Badoo có web (desktop, mobile) và app Android, iOS với hàng triệu người dùng. Web phát hành 1–2 lần mỗi ngày, app native khoảng một lần mỗi tuần; phân tích lỗi là một bước của mỗi lần phát hành: release manager cần bản tổng hợp lỗi của phiên bản để quyết định có đưa build lên không, hay gỡ tính năng hỏng khỏi bản phát hành.
- Trước đó có hai hệ: HockeyApp cho crash native, và một hệ tự viết bằng PHP (2014) cho lỗi JS: MySQL, một bảng cho mỗi phiên bản ứng dụng, giữ 10–20 bản gần nhất, tìm theo vài trường.
- Microsoft mua HockeyApp và đẩy người dùng sang AppCenter, hạn chót 16/10/2019, nhưng AppCenter chỉ hỗ trợ file mapping DexGuard (cần để giải mã stack trace Android, không có thì không gom nhóm lỗi được) từ cuối tháng 12/2019; HockeyApp còn đếm sai tổng số lỗi nên phải chép thêm vào hệ analytics nội bộ. Năm 2017 đội frontend gần gấp đôi, hệ JS cũ lộ giới hạn; theo Bumble, sửa còn đắt hơn làm mới.
Thay đổi chính
- Yêu cầu: mọi lỗi client ở một chỗ; giữ mọi sự kiện không lấy mẫu ít nhất sáu tháng (để truy một lỗi ma của đúng một user tại một thời điểm); chịu được lỗi sinh hàng triệu sự kiện mỗi phút; trả lời được "bao nhiêu user bị ảnh hưởng", không chỉ "bao nhiêu sự kiện"; gom nhóm kèm metadata (lần đầu, lần cuối, phiên bản xuất hiện, trạng thái); tìm kiếm linh hoạt có full-text; tích hợp Jira; tự host.
- Không chọn SaaS (Bugsnag, Rollbar...) vì lo giá và chính sách đổi như HockeyApp đã đổi; không chọn Sentry 8 (đầu 2018) vì lấy mẫu sự kiện, dùng PostgreSQL (team chưa có kinh nghiệm), thiếu tích hợp Jira và viết bằng Python trong khi team dùng PHP và Go. Tự làm Gelato.
- Thu thập: API đọc, kiểm định dạng để bỏ nhiễu, rồi đẩy vào hàng đợi trung gian (LSD, Live Streaming Daemon, hệ đã dùng lâu ở Badoo) để xử lý bất đồng bộ. Lý do: lỗi của một dependency có thể làm lượng lỗi tăng vọt (SDK Facebook iOS ngày 10/7/2020 làm nhiều app sập), DB có thể tạm không ghi được; hàng đợi giảm rủi ro mất dữ liệu và giữ API trả lời nhanh cho client.
- Lưu trữ: Elasticsearch thay vì ClickHouse (đầu 2018). ClickHouse ghi nhanh, nén chuỗi tốt, cú pháp gần MySQL, nhưng khi đó chưa có xoá theo điều kiện (partition theo ngày còn thử nghiệm), cập nhật theo điều kiện (pipeline xử lý bất đồng bộ cần ghi lại vài trường) và full-text search. Elasticsearch có sẵn cả ba, scale và nhân bản sẵn, nhiều aggregation; nhược điểm: ngôn ngữ truy vấn khó, JVM cần chuyên môn (gặp vấn đề GC khi nâng từ 6.8 lên 7.5), nén chuỗi kém. Đã có sẵn một cụm Elasticsearch cho log nên không phải dựng hạ tầng mới.
- Mô hình dữ liệu: index riêng cho metadata và cho sự kiện thô, mỗi ứng dụng một index để chỉnh theo tải (app ít dùng nằm ở node warm trong kiến trúc hot-warm-cold); trường dùng cho thống kê chung đưa lên mức trên, phần riêng của từng loại lỗi nằm trong trường lồng
attributes(ý tưởng mượn từ Sentry). - Xử lý: Android: service Kotlin dùng ReTrace của ProGuard để giải mã stack trace, lấy file mapping từ Ceph (tự đẩy lên khi TeamCity dựng bản phát hành). iOS: symbolication bằng service Go gọi thư viện Symbolic của Sentry (Rust, có C-ABI) qua cgo, thay vì dùng nguyên Symbolicator (khó tích hợp, team chưa biết Rust).
- Gom nhóm bằng fingerprint (hash): JS theo message, type, origin; Android theo ba dòng đầu stack trace; iOS theo frame đầu không thuộc hệ thống trong thread bị crash.
- So sánh hai phiên bản: lỗi có ở bản này mà không có ở bản kia, để thấy lỗi mới và hồi quy. Từ ý tưởng tới chuyển hẳn mất gần hai năm. Lúc viết, Bumble khuyên người khác nên xem Sentry trước, vì Sentry 9 (7/2018) đã thêm tích hợp tracker và hướng sang ClickHouse.
Vì sao
- Theo Bumble, cách dùng dữ liệu (theo phiên bản, theo user, so bản phát hành, gắn vào quy trình phát hành) quyết định cách lưu; một hệ tự host gắn chặt quy trình nội bộ đáng công làm khi sản phẩm sẵn có không khớp và nhà cung cấp có thể đổi luật.
Bài học cho SWE
- Dữ liệu từ client đến theo cơn (một dependency hỏng là cả triệu lỗi); đặt hàng đợi giữa API nhận và phần xử lý.
- Chọn DB theo các thao tác cần ngay (xoá, cập nhật theo điều kiện, full-text) và theo hạ tầng đã vận hành, không chỉ theo tốc độ ghi; đánh giá lại khi DB kia trưởng thành.
- Phụ thuộc vào SaaS có rủi ro bị đổi luật đúng lúc không có lối thay; viết lại thứ mình cần giữ quyền kiểm soát.
- Gắn lỗi với phiên bản phát hành và so hai phiên bản là cách biến dữ liệu lỗi thành cổng phát hành.
Liên quan
- Observability và monitoring · Kiến trúc frontend · Chọn database theo workload
- Cùng công ty: Bumble 2019
- Cùng bài toán: Discord 2025 · ClickHouse 2025
#Client error tracking#Gelato#HockeyApp#AppCenter#Sentry#LSD queue#Elasticsearch vs ClickHouse#hot-warm-cold#deobfuscation#ReTrace#symbolication#Symbolic#cgo#fingerprint grouping
Được nhắc tới trong
Công ty (1)
Bài tóm tắt (1)