精选文章

Flutter 日志与崩溃上报

2021-09-03 · 组件

日志与崩溃上报不是“有就行”,而是稳定性工程的基础设施。本文用完整代码范式讲清:日志分级、统一入口、崩溃捕获与上报。

1. 统一日志入口

先定义一个全局 Logger,避免散落的 print

enum LogLevel { debug, info, warn, error }

class Log {
  static LogLevel level = LogLevel.debug;

  static void d(String tag, String msg) => _log(LogLevel.debug, tag, msg);
  static void i(String tag, String msg) => _log(LogLevel.info, tag, msg);
  static void w(String tag, String msg) => _log(LogLevel.warn, tag, msg);
  static void e(String tag, String msg) => _log(LogLevel.error, tag, msg);

  static void _log(LogLevel lv, String tag, String msg) {
    if (lv.index < level.index) return;
    final now = DateTime.now().toIso8601String();
    debugPrint('[$now][$lv][$tag] $msg');
  }
}

2. 崩溃捕获入口

Flutter 侧至少需要捕获两类异常:

  • Flutter 线程异常
  • 非 Flutter(Zone)异常
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  FlutterError.onError = (details) {
    Log.e('crash', details.exceptionAsString());
    CrashReporter.report(details.exception, details.stack);
  };

  runZonedGuarded(() {
    runApp(const MyApp());
  }, (error, stack) {
    Log.e('zone', error.toString());
    CrashReporter.report(error, stack);
  });
}

3. 崩溃上报接口

class CrashReporter {
  static Future<void> report(Object error, StackTrace? stack) async {
    // TODO: upload to your backend
    Log.e('report', error.toString());
  }
}

你可以在这里对接 Sentry、Firebase Crashlytics 或自建平台。

4. 日志持久化(可选)

线上问题排查时,持久化日志很有用:

class FileLogger {
  final File file;
  FileLogger(this.file);

  Future<void> append(String line) async {
    await file.writeAsString(line + '\n', mode: FileMode.append);
  }
}

配合 Log._log 可以写入本地文件。

5. 埋点:让行为可观测

class EventTracker {
  static void track(String event, Map<String, dynamic> data) {
    Log.i('event', '$event $data');
  }
}

埋点不要侵入业务代码太深,统一入口即可。

6. 实践清单

  • 统一日志入口
  • FlutterError + Zone 捕获
  • 崩溃上报
  • 可选日志持久化
  • 统一埋点入口

总结

日志与崩溃上报是工程稳定性的底线。只要统一入口、集中捕获并可上报,就能把线上问题变成可追踪的数据。

JJ

作者简介

专注于内容创作、产品策略与设计实践。欢迎交流合作。

上一篇 下一篇