跳转到正文
YGJoon 技术博客

Flutter集成Sentry日志收集

发布于:
·1.1k 字 · 约 3 分钟·作者:
DSN 初始化、captureException 上报崩溃、configureScope 绑定用户信息:Sentry 让线上错误可追踪
Flutter集成Sentry日志收集文章封面
目录

简介

Sentry是一个开源的实时错误跟踪系统,它能帮助开发者实时监控和修复崩溃。本文将详细介绍如何在Flutter项目中集成Sentry,实现全面的错误监控和日志收集。

集成步骤

1. 添加依赖

在pubspec.yaml文件中添加Sentry依赖:

dependencies:
  sentry_flutter: ^7.13.2

2. 初始化配置

在应用程序入口处初始化Sentry:

import 'package:flutter/material.dart';
import 'package:sentry_flutter/sentry_flutter.dart';

Future<void> main() async {
  await SentryFlutter.init(
    (options) {
      options.dsn = 'YOUR_DSN_HERE'; // 从Sentry后台获取的DSN
      options.tracesSampleRate = 1.0; // 性能监控采样率
      options.debug = true; // 开发环境建议开启debug模式
    },
    appRunner: () => runApp(MyApp()),
  );
}

基本使用

1. 捕获异常

try {
  throw Exception('测试异常');
} catch (exception, stackTrace) {
  await Sentry.captureException(
    exception,
    stackTrace: stackTrace,
  );
}

2. 添加自定义上下文

// 添加用户信息
Sentry.configureScope((scope) {
  scope.setUser(SentryUser(
    id: 'user-123',
    email: '[email protected]',
    username: 'username',
  ));
});

// 添加标签
Sentry.configureScope((scope) {
  scope.setTag('page', 'home');
  scope.setTag('network', 'wifi');
});

// 添加额外数据
Sentry.configureScope((scope) {
  scope.setExtra('device_info', {
    'model': 'iPhone 12',
    'os': 'iOS 15.0',
  });
});

3. 性能监控

// 监控整个操作的性能
final transaction = Sentry.startTransaction(
  'processOrder',
  'operation',
);

try {
  // 执行耗时操作
  await processOrder();
  transaction.finish(status: SpanStatus.ok());
} catch (exception) {
  transaction.finish(status: SpanStatus.internalError());
  await Sentry.captureException(exception);
}

// 监控特定操作
final span = transaction.startChild(
  'http.client',
  description: '获取用户数据',
);

try {
  await getUserData();
  span.finish(status: SpanStatus.ok());
} catch (exception) {
  span.finish(status: SpanStatus.internalError());
  throw exception;
}

高级配置

1. 过滤敏感信息

await SentryFlutter.init(
  (options) {
    options.beforeSend = (event, {hint}) {
      // 移除敏感信息
      event.tags?.remove('password');
      event.extra?.remove('creditCard');
      return event;
    };
  },
  appRunner: () => runApp(MyApp()),
);

2. 自定义事件分组

await Sentry.captureException(
  exception,
  stackTrace: stackTrace,
  fingerprint: ['unique-error-group'],
);

3. 离线缓存

await SentryFlutter.init(
  (options) {
    options.maxCacheItems = 30; // 最大缓存事件数
    options.maxCacheItems = Duration(days: 7); // 缓存时间
  },
  appRunner: () => runApp(MyApp()),
);

最佳实践

1. 错误边界处理

class ErrorBoundary extends StatelessWidget {
  final Widget child;

  const ErrorBoundary({Key? key, required this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ErrorWidget.builder = (FlutterErrorDetails details) {
      Sentry.captureException(
        details.exception,
        stackTrace: details.stack,
      );
      
      return Material(
        child: Center(
          child: Text('发生错误,请稍后重试'),
        ),
      );
    };
  }
}

2. 网络请求监控

class SentryHttpClient extends http.BaseClient {
  final http.Client _inner = http.Client();

  @override
  Future<http.StreamedResponse> send(http.BaseRequest request) async {
    final span = Sentry.startTransaction(
      'http.client',
      'http',
      bindToScope: true,
    ).startChild(
      'http.request',
      description: '${request.method} ${request.url}',
    );

    try {
      final response = await _inner.send(request);
      span.finish(status: SpanStatus.ok());
      return response;
    } catch (exception) {
      span.finish(status: SpanStatus.internalError());
      await Sentry.captureException(exception);
      rethrow;
    }
  }
}

3. 版本管理

await SentryFlutter.init(
  (options) {
    options.release = '[email protected]'; // 应用版本
    options.dist = '1'; // 构建号
    options.environment = 'production'; // 环境标识
  },
  appRunner: () => runApp(MyApp()),
);

注意事项

  1. DSN安全性:不要在代码中硬编码DSN,建议通过配置文件或环境变量注入。

  2. 性能影响:合理设置采样率,避免过多的性能监控影响应用性能。

  3. 数据隐私:确保在发送事件前移除所有敏感信息。

  4. 调试模式:开发环境建议开启debug模式,方便排查问题。

  5. 错误分组:合理使用fingerprint功能,避免相似错误产生过多重复事件。

实战案例

Sentry(线上崩溃收集)我还没接过——我的 App 出问题都是用户微信直接找我,量小,Sentry 的接入成本暂时不值。但我吃过没崩溃收集的亏:flutter_brightness 有次在用户电脑上启动闪退,我复现不出来,只能让用户录屏+描述,折腾两天才发现是某台机器没串口设备,SerialPort.availablePorts 返回空,我的代码没判空。Sentry 的价值不在”收集”,在”复现不了的 bug 有堆栈”。等用户量上来,第一个要接的就是它,而不是 Analytics。接入本身不难(sentry_flutter 按文档走),难的是”崩溃了要有人看”——小团队先保证有人看,再谈接入。参考:Sentry 官方 Flutter 文档。

总结

Sentry 接入按 sentry_flutter 文档走,DSN 初始化 + captureException,半天能跑起来。真正的成本在后面:崩溃了要有人看、有人修。小团队用户量没起来之前,先保证”有人看”再谈接入——否则就是给线上错误建了个没人看的坟场。它的价值不在”收集”,在”复现不了的 bug 有堆栈”。


分享这篇文章:


相关文章

上一篇
Flutter 插件开发 Android 平台篇
下一篇
Flutter 自定义注解详解