Flutter : รู้จักกับ Sentry เครื่องมือสำหรับรายงาน Error ในแอป
สวัสดีผู้อ่านครับ ช่วงนี้ผมก็หาอะไรเล่นไปเรื่อยๆ ไปเจอในเว็บ Flutter ที่แนะนำเรื่อง Crash Reporting โดยใช้เครื่องมือที่ชื่อว่า Sentry นั่นก็เพราะว่า Sentry ได้ทำ library สำหรับ Flutter สำหรับผู้ที่ไม่ทราบว่า Crash Reporting คืออะไร มันก็คือการรายงาน error ของแอปจากเครื่องผู้ใช้ไปที่เว็บ เพื่อให้เราตรวจสอบและแก้ไขปัญหาได้ทันที เพราะว่าเราคงไม่สามารถเดินไปหาผู้ใช้แอปแล้วขอมือถือมาแก้ error ได้แน่ๆ ดังนั้นเลยมีผู้ให้บริการหลายเจ้าพัฒนาเครื่องมือมาเพื่อช่วยแก้ปัญหา ซึ่งเจ้าดังๆที่ผมเคยใช้ก็มี Crashlytic (ตอนนี้ถูก Google ซื้อไปรวมกับ Firebase) ส่วน Sentry ผมก็เพิ่งเคยได้ยิน วันนี้เลยถือโอกาสลองใช้งานกันครับ
เริ่มต้น
สม้ครใช้งาน https://sentry.io/ จากนั้นก็ sign in
แล้วก็สร้าง project
แล้วเราก็จะได้โค้ด DSN เอาไว้ระบุตัวตนของแอปเรา
การใช้งาน Sentry ใน Flutter
เพิ่ม dependencies ใน pubspec.yaml
dependencies: sentry: 2.2.0
import sentry เข้ามาที่ main.dart หรือไฟล์ที่ต้องการ Crash reporting
import 'package:sentry/sentry.dart';
ประกาศ SentryClient พร้อมกับระบุ DSN ของเราให้มัน
final SentryClient sentry = SentryClient(dsn: "....");
ทดลองทำหน้าจอ เมื่อกดปุ่มแล้วจะส่ง error ไปที่ Sentry
class MyHomePage extends StatelessWidget { final SentryClient sentry = SentryClient(dsn: "..."); MyHomePage({Key key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("My Sentry App"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ FlatButton(color: Colors.blue[100],child: Text("Get error"),onPressed: (){ displayError(); },) ], ), ), ); } void displayError() async{ try { throw StateError('This is an async Dart exception.'); } catch(error, stackTrace) { await sentry.captureException( exception: error, stackTrace: stackTrace, ); print("Sent error to Sentry.io ,"+error.toString()); } } }
การดูรายงาน
เสร็จแล้วไปที่เว็บ sentry ที่เมนู Issues ก็จะมี error ของเราปรากฏ
อันไหนเราแก้ไขแล้วก็ติ๊ก แล้วกดที่ Resolve ได้เลย
แยก DebugMode กับ Production
เราคงไม่อยากให้ ระหว่างที่เรา debug แล้วเกิด error แอปส่ง report ไปที่ sentry ปนกับของ Production
ดังนั้นเราควรแยกให้ debugMode แค่ print log ก็พอ
สร้าง method สำหรับเช็คว่าเป็น DebugMode หรือไม่
กรณี Production ให้ comment บรรทัด assert ออก
bool get isInDebugMode { bool inDebugMode = false; assert(inDebugMode = true); return inDebugMode; }
เขียน method สำหรับส่ง report error เพื่อให้ใช้งานง่ายขึ้น
Future<Null> reportErrorToSentry(dynamic error, dynamic stackTrace) async{ if (isInDebugMode) { print(stackTrace); return; } sentry.captureException( exception: error, stackTrace: stackTrace, ); }
method ตอนกดปุ่มของเราจะเหลือแค่นี้
void displayError() async { try { throw StateError('This is an async Dart exception.'); } catch (error, stackTrace) { reportErrorToSentry(error , stackTrace); } }
ดัก Error จากทั้งแอป
การใช้ try catch ดักทีละเคสก็อาจจะเหนื่อยเกินไป เราสามารถใช้ Zone มาครอบแอปของเราได้ โดยเมื่อจุดใดๆในแอปของเรา เกิด error มันจะเข้า onError
Future<Null> main() async { FlutterError.onError = (FlutterErrorDetails details) async { if (isInDebugMode) { FlutterError.dumpErrorToConsole(details); } else { Zone.current.handleUncaughtError(details.exception, details.stack); } }; runZoned<Future<Null>>(() async { runApp(new MyApp()); }, onError: (error, stackTrace) async { await reportError(error, stackTrace); }); }
ราคาค่าบริการของ Sentry
ดูราคาของ sentry ได้ที่ https://sentry.io/pricing/
หลักๆคือ Developer plan จะฟรี แต่รับ error ได้แค่ 5,000 event ต่อเดือน เก็บประวัติ 30 วัน