美文网首页
Flutter项目中如何加入Sentry监控

Flutter项目中如何加入Sentry监控

作者: 天上飘的是浮云 | 来源:发表于2023-03-28 17:15 被阅读0次

    继由《Flutter应用监控体系Docker+Sentry部署》这篇文章好,其实还想写一些在Flutter项目中,如何加入Sentry来进行监控。一直没时间没动力写写,今天来补一补这口锅~

    一、创建项目

    首先,我们之前搭建了本地的Docker+Sentry,那我们可打开本地部署的Sentry网页,并创建项目。


    Create Project
    创建Flutter项目
    Flutter项目

    二、获取创建的Flutter项目的DNS

    在Sentry网页中Settings -> Projects -> 选择你创建的项目 -> Client Keys(DNS)


    DNS

    三、pub.dev Sentry插件

    可以在pub.dev上搜索sentry,会出来很多关于Sentry的插件,我们需要的可能是这几个:sentry_flutter、sentry_dio、sentry、sentry_link。

    • sentry: Sentry的Dary插件。
    • sentry_flutter: Sentry用于Flutter项目的插件,如果是flutter项目,用这个最好。
    • sentry_dio: Dio的Sentry拓展插件,用于Sentry可以监控Dio网络请求的插件。
    • sentry_link: 如果你的网络请求是GraphQL的话,可以使用这个插件,协助完成Sentry对GraphQL请求的监控,当然也可以将GraphQl转为Http请求(参见《Flutter中使用Dio代替GraphQL请求》)。

    四、Flutter中加入Sentry监控

    4.1 引入插件

    首先,需要Sentry_flutter插件,然后根据你使用的网络请求按需选择插件,sentry_dio(Dio请求)、sentry_link(GraphQL请求)、如果是使用的http client发起请求的话,直接用sentry_flutter就行,无需其他插件。

    dependencies:
      flutter:
        sdk: flutter
      sentry_flutter: ^6.17.0
      sentry_dio: ^6.20.1
    
    4.2 初始化Sentry

    首先,我们得在main.dart文件中,初始化sentry。插件SDK会自动捕获错误。

    SentryOptions除了设置DNS、environment外还可以设置其他如:采样率、是否压缩、附件最大值等等,使用的时候可以按需配置。

    import 'package:flutter/widgets.dart';
    import 'package:sentry_flutter/sentry_flutter.dart';
    
    Future<void> main() async {
      await SentryFlutter.init(
        (options) {
          options.dsn = 'https://example@sentry.io/add-your-dsn-here';  (这是Sentry创建项目的时候的DNS,参见“二、获取创建的Flutter项目的DNS”)
          options.environment = 'Dev'; (设置环境,如:Dev、Stage、Live等)
        },
        // Init your App.
        appRunner: () => runApp(MyApp()),
      );
    }
    
    4.3 AssetBundle 的性能监控

    Sentry还能监控我们在pubspec.yaml配置的Asset性能。

    import 'package:flutter/widgets.dart';
    import 'package:sentry_flutter/sentry_flutter.dart';
    
    Future<void> main() async {
      await SentryFlutter.init(
        (options) {
          options.dsn = 'https://example@sentry.io/add-your-dsn-here';  
          options.environment = 'Dev'; (
        },
        // Init your App.
        appRunner: () => runApp(
          DefaultAssetBundle(
            bundle: SentryAssetBundle(),
            child: MyApp(),
          ),
        ),
      );
    }
    
    4.4 监控页面路由Navigation

    可以在你的MaterialApp、WidgetsApp或者CupertinoApp下添加observers。

    MaterialApp(
       navigatorObservers: [
          SentryNavigatorObserver()
       ],
       ...
    );
    
    4.5 网络请求监控

    网络请求可以分为三种情况,三种请求使用方式不一样。

    4.5.1 使用HttpClient请求时
    • 可以直接使用SentryHttpClient(),并且可以设置你需要监控的http Status Code
    import 'package:sentry/sentry.dart';
    
    var client = var client = SentryHttpClient(
      failedRequestStatusCodes: [
        SentryStatusCode.range(400, 404),
        SentryStatusCode(500),
      ],
    );;
    try {
     var uriResponse = await client.post('https://example.com/whatsit/create',
         body: {'name': 'doodle', 'color': 'blue'});
     print(await client.get(uriResponse.bodyFields['uri']));
    } finally {
     client.close();
    }
    
    • 如果你使用的是http.Client(),SentryHttpClient可以包装它
    import 'package:sentry/sentry.dart';
    import 'package:http/http.dart' as http;
    
    final myClient = http.Client();
    
    var client = SentryHttpClient(client: myClient);
    try {
    var uriResponse = await client.post('https://example.com/whatsit/create',
         body: {'name': 'doodle', 'color': 'blue'});
     print(await client.get(uriResponse.bodyFields['uri']));
    } finally {
     client.close();
    }
    
    4.5.2 使用Dio请求时

    需要添加sentry_dio: ^6.20.1插件,它会对Dio进行拓展。它可以设置一些参数值,控制网络请求监控。

        Dio dio = Dio();
    
        dio.addSentry(
          captureFailedRequests: true,
          maxRequestBodySize: MaxRequestBodySize.always,
          maxResponseBodySize: MaxResponseBodySize.always,
        );
    
    使用Dio进行网络请求时,我之前聊过如何进行http 代理,《Flutter中Dio动态设置Http代理IP和端口》《Flutter中Dio如何抓取Https》

    但是如果当Dio请求网络代理和Dio sentry监控碰到一起之后,会产生报错:

    _dio.httpClientAdapter is SentryDioClientAdapter , not sub type of DefaultHttpClientAdapter.

    因为进过Sentry_dio插件包装Dio之后,Dio的网络适配器不再是DefaultHttpClientAdapter,而是包装为SentryDioClientAdapter。所以导致报错,SentryDioClientAdapter又不对外可见,压根就无法直接引用,所以,我想出了这个方法。

    • 在Dio创建实例的时候,保存下原始的HttpClientAdapter:
        Dio dio = Dio();
    
        httpClientAdapter = dio.httpClientAdapter;
    
        dio.addSentry(
          captureFailedRequests: true,
          maxRequestBodySize: MaxRequestBodySize.always,
          maxResponseBodySize: MaxResponseBodySize.always,
        );
    
    • 然后,在设置代理的时候判断下类型:
    String proxy = "PROXY ${ipController.text}:${portController.text}";
    
    if(!(dio?.httpClientAdapter is DefaultHttpClientAdapter)){
      dio?.httpClientAdapter = HttpRequest().httpClientAdapter;
    }
    
    (dio?.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (client) {
      client.findProxy = (url) {
        return proxy;
      };
    
      //Trust certificate for https proxy
      client.badCertificateCallback = (cert, host, port){
        return true;
      };
      return client;
    };
    

    参见Github issue: How to set PROXY when use sentry dio

    4.5.3 使用GraphQL请求时

    需要添加sentry_link: ^0.2.1插件,我们只需要添加SentryGql.link()到我们的links里就行。

    初始化时,添加LinkException的捕捉
    Sentry.init((options) {
      options.addGqlExtractors();
    });
    
    final link = Link.from([
        AuthLink(getToken: () async => 'Bearer $personalAccessToken'),
        SentryGql.link(
          shouldStartTransaction: true,
          graphQlErrorsMarkTransactionAsFailed: true,
        ),
        HttpLink(
          'https://api.github.com/graphql',
          httpClient: SentryHttpClient(),
          serializer: SentryRequestSerializer(),
          parser: SentryResponseParser(),
        ),
      ]);
    
    4.6 网络请求的性能监控

    上面是网络请求的监听,这里要监控下网络请求的性能,

        transaction = Sentry.getSpan() ??
            Sentry.startTransaction(
              'dio-mobile-request',
              'request',
              bindToScope: true,
            );
        
        ISentrySpan? span = transaction.startChild(
            'Get',
            description: path,
          );
        }
    
        try{
          if(errorResponse == null) {
            response = await dio!.get().catchError((error) {
              errorResponse = getErrorResponse(error);
            });
            span?.status = SpanStatus.fromHttpStatusCode(response.statusCode ?? -1);
          }
        }catch (exception) {
          print(exception);
          span?.status = SpanStatus.internalError();
          span?.throwable = exception;
        }finally{
          await span?.finish();
        }
    

    五、无

    差不多了,基本用法就这些了~

    相关文章

      网友评论

          本文标题:Flutter项目中如何加入Sentry监控

          本文链接:https://www.haomeiwen.com/subject/qslzrdtx.html