Flutter性能监控插件dynatrace_flutter_plugin的使用

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

Flutter性能监控插件dynatrace_flutter_plugin的使用

Dynatrace Flutter Plugin

Dynatrace 是一款强大的应用性能监控工具,Dynatrace Flutter plugin 为您的Flutter应用程序添加了Dynatrace OneAgent,用于监控Android和iOS平台,并提供了API以便于手动收集Flutter/Dart的数据。

要求

  • Flutter版本 >= 1.12.0
  • Dart版本 >= 2.12
  • Gradle: >= 7.x
  • Android API Level >= 21
  • Java >= 11
  • iOS SDK >= 12

Agent 版本

  • Android Agent: 8.305.1.1005
  • iOS Agent: 8.305.3.1016

快速设置

安装插件

pubspec.yaml文件中添加dynatrace_flutter_plugin依赖:

dependencies:
  dynatrace_flutter_plugin: ^2.243.0

执行以下命令来解析依赖:

  • 终端:flutter pub get
  • Android Studio/IntelliJ:点击Packages get
  • VS Code:点击Get Packages

配置dynatrace.config.yaml

  1. 在Dynatrace创建一个移动应用并下载配置文件dynatrace.config.yaml
  2. 将其存储在项目根目录下。

默认情况下,用户同意模式(user opt-in mode)是激活的,这意味着OneAgent仅发送有限数量的动作直到你更改隐私模式。

启动Flutter插件

有两种启动选项:

Option 1: 使用start()

import 'package:dynatrace_flutter_plugin/dynatrace_flutter_plugin.dart';

void main() => Dynatrace().start(MyApp());

Option 2: 使用startWithoutWidget()

import 'package:dynatrace_flutter_plugin/dynatrace_flutter_plugin.dart';

void main() {
  Dynatrace().startWithoutWidget();
  runApp(MyApp());
}

构建并运行应用程序

在Flutter项目的根目录下运行以下命令以配置Android和iOS项目:

dart run dynatrace_flutter_plugin

然后运行flutter run启动应用程序。

示例Demo

下面是一个完整的示例,展示了如何集成和使用Dynatrace Flutter plugin进行性能监控。

import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:dynatrace_flutter_plugin/dynatrace_flutter_plugin.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

const String HOME_NAV = 'homeNav';
const String TEST_NAV = 'testNav';

var platform = MethodChannel('com.dynatrace.flutter/crash');

main() {
  Dynatrace().start(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dynatrace Test App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      onUnknownRoute: (settings) => MaterialPageRoute(
          builder: (context) => UndefinedView(name: settings.name!)),
      initialRoute: HOME_NAV,
      routes: {
        HOME_NAV: (context) => MyHomePage(),
        TEST_NAV: (context) => TestNav(),
      },
      navigatorObservers: [DynatraceNavigationObserver()],
      home: MyHomePage(),
    );
  }
}

class TestNav extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FloatingActionButton(
          child: Icon(Icons.navigate_before),
          onPressed: () {
            Navigator.pushNamed(context, HOME_NAV);
          },
        ),
      ),
    );
  }
}

class UndefinedView extends StatelessWidget {
  final String? name;
  const UndefinedView({Key? key, this.name}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('No route defined here!'),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, title}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var appBarText = new Text("Dynatrace Test App");
  static var _context;

  static Map<String, VoidCallback> actionsMap = {
    'Single Action': _singleAction,
    'Sub Action': _subAction,
    'Web Action': _webAction,
    'Web Action Override': _webActionOverrideHeader,
    'Web Action Full Manual': _webActionFullManualInstr,
    'Report values': _reportAll,
    'Make Navigation': _makeNavigation,
    'Force errors': _forceErrors,
    'Report crash': _reportCrash,
    'Report crash exception': _reportCrashException,
    'Flush data': _flushData,
    'Tag user': _tagUser,
    'End Session': _endSession,
    'setGpsLocation: Hawaii': _setGpsLocationHawaii,
    'User Privacy Options : All Off': _userPrivacyOptionsAllOff,
    'User Privacy Options : All On': _userPrivacyOptionsAllOn,
    'getUserPrivacyOptions': () async {
      UserPrivacyOptions options = await Dynatrace().getUserPrivacyOptions();
      print('User Privacy Options Crash:');
      print(options.crashReportingOptedIn);
      print('User Privacy Options Level:');
      print(options.dataCollectionLevel);
    }
  };

  @override
  Widget build(BuildContext context) {
    _context = context;

    final ScrollController sController = ScrollController();
    return Scaffold(
      appBar: AppBar(
        title: appBarText,
        automaticallyImplyLeading: false,
      ),
      body: Scrollbar(
        controller: sController,
        child: SingleChildScrollView(
          controller: sController,
          padding: const EdgeInsets.all(20.0),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                for (int i = 0; i < actionsMap.keys.length; i++)
                  Container(
                    width: 280.0,
                    height: 45.0,
                    padding: const EdgeInsets.all(8.0),
                    child: ElevatedButton(
                      onPressed: actionsMap.values.elementAt(i),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: Colors.blue,
                      ),
                      child: Text(
                        actionsMap.keys.elementAt(i),
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  static void _makeNavigation() {
    Navigator.pushNamed(_context, TEST_NAV);
  }

  static void _singleAction() {
    print('Single action called flutter');
    DynatraceRootAction myAction =
        Dynatrace().enterAction("MyButton tapped - Single Action");
    //Perform the action and whatever else is needed.
    myAction.leaveAction();
  }

  static void _subAction() {
    DynatraceRootAction myAction =
        Dynatrace().enterAction("MyButton tapped - Sub Action");
    DynatraceAction mySubAction = myAction.enterAction("MyButton Sub Action");
    //Perform the action and whatever else is needed.
    mySubAction.leaveAction();
    myAction.leaveAction();
  }

  static void _webAction() async {
    var client = Dynatrace().createHttpClient();
    var url = 'https://dynatrace.com';
    DynatraceRootAction webAction =
        Dynatrace().enterAction('Web Action - $url');

    try {
      await client.get(Uri.parse(url));
    } catch (error) {
      // insert error handling here
    } finally {
      client.close();
      webAction.leaveAction();
    }
  }

  static void _webActionOverrideHeader() async {
    HttpClient client = HttpClient();
    DynatraceRootAction action =
        Dynatrace().enterAction("MyButton tapped - Web Action Override");
    final request = await client.getUrl(Uri.parse('https://dynatrace.com'));
    request.headers.set(action.getRequestTagHeader(),
        await action.getRequestTag('https://dynatrace.com'));
    final response = await request.close();
    print(response);
    action.leaveAction();
  }

  static void _webActionFullManualInstr() async {
    HttpClient client = HttpClient();

    DynatraceRootAction action =
        Dynatrace().enterAction("MyButton tapped - Web Action Full Manual");
    WebRequestTiming timing =
        await action.createWebRequestTiming('https://dynatrace.com');

    final request = await client.getUrl(Uri.parse('https://dynatrace.com'));
    request.headers.add(timing.getRequestTagHeader(), timing.getRequestTag());
    timing.startWebRequestTiming();
    final response = await request.close();
    timing.stopWebRequestTiming(response.statusCode, response.reasonPhrase);
    print(response);
    action.leaveAction();
  }

  static void _reportAll() {
    DynatraceRootAction myAction =
        Dynatrace().enterAction("MyButton tapped - Report values");
    myAction.reportStringValue("ValueNameString", "ImportantValue");
    myAction.reportIntValue("ValueNameInt", 1234);
    myAction.reportDoubleValue("ValueNameDouble", 123.4567);
    myAction.reportEvent("ValueNameEvent");
    myAction.reportError("ValueNameError", 408);
    myAction.leaveAction();
  }

  static void _forceErrors() {
    String input = '12,34';
    double.parse(input);
  }

  static void _reportCrash() async {
    await platform.invokeMethod('forceCrash');
  }

  static void _reportCrashException() {
    try {
      throw IntegerDivisionByZeroException();
    } on IntegerDivisionByZeroException catch (e) {
      print('ANKH, exception is caused');
      Dynatrace().reportCrashWithException(
        "cpe2e_ReportCrashException_android",
        e,
      );
    }
  }

  static void _flushData() {
    Dynatrace().flushEvents();
  }

  static void _tagUser() {
    Dynatrace().identifyUser("User XY");
  }

  static void _endSession() {
    Dynatrace().endSession();
  }

  static void _setGpsLocationHawaii() {
    // set GPS coords to Hawaii
    Dynatrace().setGPSLocation(19, 155);
  }

  static void _userPrivacyOptionsAllOff() {
    Dynatrace().applyUserPrivacyOptions(
        UserPrivacyOptions(DataCollectionLevel.Off, false));
  }

  static void _userPrivacyOptionsAllOn() {
    Dynatrace().applyUserPrivacyOptions(
        UserPrivacyOptions(DataCollectionLevel.UserBehavior, true));
  }
}

此示例代码演示了如何使用Dynatrace Flutter plugin来监控应用程序的不同方面,包括单个动作、子动作、网络请求、报告值等。您可以根据需要调整和扩展这些功能。


更多关于Flutter性能监控插件dynatrace_flutter_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter性能监控插件dynatrace_flutter_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成和使用dynatrace_flutter_plugin进行性能监控的示例代码。

前提条件

  1. 确保你已经安装并配置好了Flutter开发环境。
  2. 你需要在Dynatrace平台上创建一个应用程序并获取相关的配置信息(如Tenant Token, Application ID等)。

步骤

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  dynatrace_flutter_plugin: ^最新版本号  # 请替换为实际的最新版本号

然后运行flutter pub get来安装依赖。

2. 配置插件

在你的Flutter项目的入口文件(通常是main.dart)中,进行插件的初始化配置:

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

void main() {
  // 初始化Dynatrace插件
  DynatraceFlutterPlugin.instance
    ..configure(
      tenantToken: '你的Tenant Token', // 替换为你的Tenant Token
      applicationId: '你的Application ID', // 替换为你的Application ID
      beaconUrl: 'https://你的Dynatrace Beacon URL', // 替换为你的Dynatrace Beacon URL
      // 其他可选配置
    )
    ..start();

  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'),
    );
  }
}

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

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

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

  void _incrementCounter() {
    setState(() {
      _counter++;
      // 手动追踪一个自定义动作(可选)
      DynatraceFlutterPlugin.instance.trackCustomEvent(
        actionName: 'Counter Incremented',
        parameters: {
          'counterValue': _counter.toString(),
        },
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

3. 运行应用

确保你已经正确配置了Dynatrace的相关信息,然后运行你的Flutter应用:

flutter run

注意事项

  • 确保你的Dynatrace账户和应用程序配置正确,并且你拥有正确的Tenant Token和Application ID。
  • 插件的版本号需要替换为实际的最新版本号。
  • 你可以在Dynatrace平台上查看和分析你的Flutter应用的性能数据。

通过上述步骤,你应该能够在Flutter项目中成功集成并使用dynatrace_flutter_plugin进行性能监控。

回到顶部