Flutter错误追踪插件groveman_sentry的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter错误追踪插件groveman_sentry的使用

Groveman Sentry

pub License: MIT groveman_sentry codecov

它将您的日志发送到Sentry。

这与sentry-dartsentry-flutter完美配合使用。

使用

在您的pubspec.yaml文件中添加依赖项:

dependencies:
  groveman:
  groveman_sentry:
  sentry: 
  // 或者
  sentry_flutter: 

在您想要使用它的位置导入它,例如在主文件中:

import 'package:groveman/groveman.dart';
import 'package:groveman_sentry/groveman_sentry.dart';

初始化Sentry并在应用程序启动时插入SentryTree:

import 'package:flutter/widgets.dart';
import 'package:groveman/groveman.dart';
import 'package:groveman_sentry/groveman_sentry.dart';
import 'package:sentry_flutter/sentry_flutter.dart';

void main() {
  Groveman.plantTree(DebugTree());
  Groveman.captureErrorInZone(() async {
    WidgetsFlutterBinding.ensureInitialized();
    await SentryFlutter.init(
      (options) {
        options.dsn = 'https://example@sentry.io/add-your-dsn-here';
      },
    );    
    if (kReleaseMode) {
      Groveman.plantTree(SentryTree());
    }
    Groveman.captureErrorInCurrentIsolate();
    runApp(const MyApp());
  });
}

通常,您只在生产环境中发送日志。

默认情况下,日志级别infowarningerrorfatal会被发送到Sentry。

Groveman.error(message, error: exception);

如果LogRecord.error不为空,则会通过captureEvent发送,否则使用addBreadcrumb

LogRecord转换为SentryEvent

  • LogRecord.level -> SentryLevel
  • LogRecord.message -> SentryMessage(message)
  • LogRecord.extra -> extra
  • LogRecord.error -> throwable
  • LogRecord.tag -> tags

groveman作为logger被发送到SentryEvent
LogRecord.stackTrace仅在captureEvent中发送。

LogRecord转换为Breadcrumb

  • LogRecord.level -> SentryLevel
  • LogRecord.message -> message
  • LogRecord.extra -> data

要自定义,创建SentryTree时传递所需的日志级别:

Groveman.plantTree(
  SentryTree(logLevels: [
    LogLevel.warning,
    LogLevel.info,
  ]),
);

许可证

版权所有 © 2025 Kauê Martins
该项目采用MIT许可证


示例代码

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

void main() {
  Groveman.plantTree(DebugTree(showColor: true));
  Groveman.captureErrorInZone(() async {
    await SentryFlutter.init(
      (options) {
        options.dsn = const String.fromEnvironment('SENTRY_DNS');
      },
    );
    Groveman.plantTree(SentryTree());
    Groveman.captureErrorInCurrentIsolate();
    runApp(const MyApp());
  });
}

class MyApp extends StatelessWidget {
  const MyApp({
    super.key,
  });

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({
    super.key,
    required this.title,
  });

  final String title;

  [@override](/user/override)
  // ignore: library_private_types_in_public_api
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
      Groveman.info(
        'Counter - $_counter',
        tag: 'counter',
        extra: {'my_counter': _counter},
      );
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton.extended(
            onPressed: () {
              Groveman.fatal(
                'Fatal',
                error: 'Fatal',
                stackTrace: StackTrace.current,
                extra: {'my_counter': _counter},
              );
            },
            label: const Text('Report fatal error'),
            icon: const Icon(Icons.bug_report),
          ),
          const SizedBox(
            height: 16,
          ),
          FloatingActionButton.extended(
            onPressed: () {
              Future.delayed(
                Duration.zero,
                () => throw Exception('Async error'),
              );
            },
            label: const Text('Report error'),
            icon: const Icon(Icons.error),
          ),
          const SizedBox(
            height: 16,
          ),
          FloatingActionButton.extended(
            onPressed: _incrementCounter,
            label: const Text('Increment'),
            icon: const Icon(Icons.add),
          ),
        ],
      ),
    );
  }
}

更多关于Flutter错误追踪插件groveman_sentry的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter错误追踪插件groveman_sentry的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter项目中集成和使用groveman_sentry(通常称为sentry_flutter,因为groveman_sentry可能是一个拼写错误或者特定分支/fork的名称,但官方的Sentry Flutter SDK是sentry_flutter)可以帮助你有效地追踪和分析应用中的错误。以下是如何在Flutter项目中集成并使用sentry_flutter的详细步骤和代码示例。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加sentry_fluttersentry的依赖:

dependencies:
  flutter:
    sdk: flutter
  sentry_flutter: ^x.y.z  # 请替换为最新版本号

运行flutter pub get来安装依赖。

2. 配置Sentry

在你的Flutter项目的lib目录下创建一个新的Dart文件,比如sentry_config.dart,用于初始化Sentry客户端。

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

void configureSentry(BuildContext context) {
  final SentryOptions options = SentryOptions(
    dsn: 'https://your-dsn-here@sentry.io/your-project-id',
    // 其他可选配置
    environment: kReleaseMode ? 'production' : 'development',
    release: '1.0.0',  // 你的应用版本
    dist: 'flutter',
  );

  // 初始化Sentry客户端
  Sentry.init(options: options);

  // 捕获Flutter框架的异常
  FlutterError.onError = Sentry.captureFlutterError;

  // 可选:捕获隔离区(Isolate)中的未捕获异常
  Isolate.current.addErrorListener(RawReceivePort((pair) {
    final List<dynamic> errorAndStackTrace = pair as List<dynamic>;
    Sentry.captureException(
      errorAndStackTrace.first,
      stackTrace: errorAndStackTrace.skip(1).toList(),
    );
  }).sendPort!;
}

确保将dsn替换为你的Sentry项目的实际DSN。

3. 在应用中初始化Sentry

在你的主应用文件(通常是main.dart)中调用configureSentry函数。

import 'package:flutter/material.dart';
import 'sentry_config.dart';  // 导入你创建的Sentry配置文件

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  configureSentry(null);  // 在main函数中,context为null,因为还没有构建Widget树
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

4. 手动捕获异常

你可以在代码中的任何地方使用Sentry.captureException来手动捕获并报告异常。

void someFunctionThatMightThrow() {
  try {
    // 可能会抛出异常的代码
    throw Exception('Something went wrong!');
  } catch (e, s) {
    Sentry.captureException(e, stackTrace: s);
  }
}

5. 测试和验证

确保你的应用已经正确配置了Sentry,并尝试触发一些错误(比如除以零、访问空列表的元素等)。然后检查Sentry仪表板,看看错误是否被正确捕获和报告。

总结

通过以上步骤,你可以在Flutter项目中集成并使用sentry_flutter来追踪和分析应用中的错误。记得替换示例代码中的DSN和其他配置信息为你的实际值,并根据需要调整配置选项。

回到顶部