Mobile APM for Flutter applications

The Site24x7 Flutter plugin enables users to monitor HTTP requests, crashes, screen loading times, and custom data of their Flutter mobile applications. This can be achieved by adding transactions and grouping them based on components, individual users, and their sessions, thereby enhancing the performance of the application.

Table of contents

Getting started

Follow the steps outlined below to install site24x7_flutter_plugin in your Flutter application.

  1. To install the plugin, run the following command.
    flutter pub add site24x7_flutter_plugin
  2. Open the pubspec.yaml file located in the app folder, and you will find that a line site24x7_flutter_plugin: has been added to the dependencies section, as shown below.
    dependencies:
    site24x7_flutter_plugin: ^1.0.0

Installation steps for iOS

  1. Add pod to the Podfile in the project_directory/ios/.
    target 'Your_Project_Name' do
          pod 'Site24x7APM'
    end
  2. Run the following command in the same directory.
    pod install

Installation steps for Android

Add the Zoho Maven URL to the build.gradle file located in the android folder of the applications project level.

allprojects {
    repositories {
        ...
        maven { url 'https://maven.zohodl.com' }
        ...
    }
}

Usage in Flutter applications

Import ApmMobileapmFlutterPlugin from the site24x7_flutter.dart file as follows:

import 'package:site24x7_flutter_plugin/site24x7_flutter_plugin.dart';


APIs to capture other parameters

Custom APIs are utilized for monitoring user actions, capturing screens, tracking errors and exceptions, and performing other related tasks. This document provides an overview of the different types of custom APIs offered in Site24x7 and the corresponding syntax for their usage.

Initialize the agent

You can use the API below to start the Site24x7 Flutter agent, which will capture Flutter errors and exceptions seamlessly for enhanced monitoring in your Flutter application.

import 'package:site24x7_flutter_plugin/site24x7_flutter_plugin.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();

  //assign the Site24x7 error callbacks
  //for non-async exceptions
  FlutterError.onError = ApmMobileapmFlutterPlugin.instance.captureFlutterError; //site24x7 custom callback

  //for async exceptions
  PlatformDispatcher.instance.onError = (error, stack) {
    ApmMobileapmFlutterPlugin.instance.captureException(error, stack, false, type: "uncaughtexception"); //site24x7 custom api
    return true;
  };

  //starting the agent
  ApmMobileapmFlutterPlugin.instance.startMonitoring("appKey", uploadInterval); //site24x7 custom api

  ...
  runApp(MyHomePage(title: 'Flutter Demo Home Page'));
  ...

}
Make sure to call WidgetsFlutterBinding.ensureInitialized(); before assigning error callbacks in the main method.


Configure screen tracking

You can use the following mechanism to determine how long it takes for a screen to load. This data is pushed to the Site24x7 servers and can be used for session tracking and crash reporting.

For stateless widget:

import 'package:site24x7_flutter_plugin/site24x7_flutter_plugin.dart';

class FirstScreen extends StatelessWidget {

  FirstScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Sample Widget'),
        ),
        body: Center(
            child: ElevatedButton(
              child: const Text('Go To Stateless Widget'),
              onPressed: () {
                var initialTimeStamp = DateTime.now();
                Navigator.push(
                    context, 
                    MaterialPageRoute(
                        builder: (context) => SampleStatelessWidget()
                        ),
                    ).then((value) {
                    var loadTime = DateTime.now().difference(initialTimeStamp).inMilliseconds;
                    ApmMobileapmFlutterPlugin.instance.addScreen("SampleStatelessWidget", loadTime.toDouble(), initialTimeStamp.millisecondsSinceEpoch); //site24x7 custom api
                });
              },
            ),
          ),
      );
    }
}

For stateful widget:

import 'package:site24x7_flutter_plugin/site24x7_flutter_plugin.dart';

class SampleWidget extends StatefulWidget {
  const SampleWidget({super.key});
  @override
  State createState() => _SampleWidgetState();
}

class _SampleWidgetState extends State {
  late var _initialTimeStamp, _finalTimeStamp;

  @override
  void initState() {
    super.initState();
    _initialTimeStamp = DateTime.now();
  }

  void site24x7AfterBuildCallback(BuildContext context) {
    var finalTimeStamp = DateTime.now();
  }

  @override
  Widget build(BuildContext context) {

    WidgetsBinding.instance!.addPostFrameCallback((_) => site24x7AfterBuildCallback(context));
    return Scaffold(
        appBar: AppBar(
          title: const Text('Sample Widget'),
        ),
        body: Center(
          child: const Text('Hello Sample Widget');
        ),
      );
  }

  @override
  void didUpdateWidget(Fetch oldWidget) {
    super.didUpdateWidget(oldWidget);
    //send the widget loading time, i.e., difference between initial and final timestamp should be sent to the server using addScreen API
    var loadTime = _finalTimeStamp.difference(_initialTimeStamp).inMilliseconds;
    ApmMobileapmFlutterPlugin.instance.addScreen("Fetch", loadTime.toDouble(), _initialTimeStamp.millisecondsSinceEpoch); //site24x7 custom api
    //assign final timestamp to initial timestamp
    _initialTimeStamp = DateTime.now();
  }

  @override
  void dispose() {
    super.dispose();
    //send the widget loading time, i.e., difference between initial and final timestamp should be sent to the server using addScreen API
    var loadTime = _finalTimeStamp.difference(_initialTimeStamp).inMilliseconds;
    ApmMobileapmFlutterPlugin.instance.addScreen("Fetch", loadTime.toDouble(), _initialTimeStamp.millisecondsSinceEpoch); //site24x7 custom api
  }
}

To capture breadcrumbs during routing automatically, utilize the Site24x7NavigatorObserver() function in the following manner:

class MyHomePage extends StatefulWidget {
  @override
  State createState() => _MyHomePageState();
}

class _MyHomePageState extends State with WidgetsBindingObserver {

  @override
  Widget build(BuildContext context){
    return MaterialApp(
      routes: {
        '/first': (context) => FirstScreen(),
        '/second': (context) => SecondScreen(),
        '/fetch': (context) => FetchScreen()
      },
      navigatorObservers: [
        Site24x7NavigatorObserver() //site24x7 custom navigator observer
      ]
    );
  }

}


Network monitoring

Network monitoring capabilities include support for HTTP and Dio packages, allowing for the capture of API calls made using these packages.

HTTP package:

import 'package:http/http.dart' as http;
import 'package:site24x7_flutter_plugin/site24x7_flutter.dart';

...

//site24x7 custom components
var client = Site24x7HttpClient();
                  (or)
var client = Site24x7HttpClient(client: http.Client());

var dataURL = Uri.parse('https://jsonplaceholder.typicode.com/posts?userId=1&_limit=5');
http.Response response = await client.get(dataURL);

...

Dio package:

import 'package:dio/dio.dart';
import 'package:site24x7_flutter_plugin/site24x7_flutter_plugin.dart';

...

var dio = Dio();

dio.enableSite24x7(); //site24x7 dio extension

var dataURL = 'https://jsonplaceholder.typicode.com/posts?userId=1_limit=5';
final response = await dio.get(dataURL);

...
Ensure that you have installed the HTTP and Dio packages before making an API call. Additionally, remember to include .enableSite24x7() at the conclusion of any custom configuration on the Dio object.


Error monitoring

You can manually capture exceptions that occur in catch blocks by using the API mentioned below.

To capture non-async exceptions:

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  FlutterError.onError = ApmMobileapmFlutterPlugin.instance.captureFlutterError; //site24x7 custom callback
  runApp(MyHomePage());
}

To capture async exceptions:

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  PlatformDispatcher.instance.onError = (error, stack){
    ApmMobileapmFlutterPlugin.instance.platformDispatcherErrorCallback(error, stack); //site24x7 custom api
  };
  runApp(MyHomePage());
}
It is recommended to use error monitoring custom APIs before calling runApp().

To capture caught exceptions:

try {

  //code which might generate exceptions

} catch (exception, stack){
  ApmMobileapmFlutterPlugin.instance.captureException(exception, stack);
}


Managing transactions and components

You can start and stop a unique component within a transaction. You can also begin more than one component in a single transaction.

ApmMobileapmFlutterPlugin.instance.startTransaction("listing_blogs");

//Grouping various operations using components.
ApmMobileapmFlutterPlugin.instance.startComponent("listing_blogs", "http_request");
//your code/logic
ApmMobileapmFlutterPlugin.instance.stopComponent("listing_blogs", "http_request");

ApmMobileapmFlutterPlugin.instance.startComponent("listing_blogs", "view_data_onto_screen");
//your code/logic
ApmMobileapmFlutterPlugin.instance.stopComponent("listing_blogs", "view_data_onto_screen");

ApmMobileapmFlutterPlugin.instance.stopTransaction("listing_blogs");


User tracking

You can track a specific user by setting up a unique user identifier. In case a unique ID is not provided, Site24x7 will generate a random GUID and assign it as the user ID.

ApmMobileapmFlutterPlugin.instance.setUserId("user@example.com");


Adding breadcrumbs

Use the function below to add breadcrumbs manually.

ApmMobileapmFlutterPlugin.instance.addBreadcrumb(event, message);
ex: ApmMobileapmFlutterPlugin.instance.addBreadcrumb("Info", "download completed");


Manual flush

You can use the API provided below to promptly send data to the Site24x7 servers instead of waiting for the next upload interval.

ApmMobileapmFlutterPlugin.instance.flush();


Forced application crash

You can force your application to crash and display an error message: This is a site24x7 crash.

ApmMobileapmFlutterPlugin.instance.crashApplication();

 

Release notes

Version 1.0.0

05 February 2024

Enhancements:

  • Support for tracking HTTP calls with the request method, response time, throughput, status codes, platform, and screens.
  • Support for tracking screens based on the response time, throughput, and count.
  • Support for automatic tracking of navigations.
  • Support for manually tracking views.
  • Enabled user sessions tracking with a session timeout of 15 minutes.
  • Support for manually adding user IDs.
  • Support for tracking async and non-async crashes using agent-provided callbacks.
  • Support for manually adding breadcrumbs.
  • Support for packages such as HTTP and Dio.
Was this document helpful?
Thanks for taking the time to share your feedback. We’ll use your feedback to improve our online help resources.