The Real User Monitoring (RUM) SDK for Flutter provides API methods for configuration and custom data reporting.
Start configuration
The start method is the core startup method of the AlibabaCloudRUM Flutter SDK. It initializes the monitoring system and starts the application.
Future<void> start(Widget topLevelWidget, {Function()? beforeRunApp}) async
|
Parameter |
Description |
Constraints |
Failure result |
|
topLevelWidget |
The root widget of your Flutter application. |
Required. Must not be null. |
API call fails. |
|
beforeRunApp |
A callback function that is called before |
Optional. If set, you must call |
- |
Example:
AlibabaCloudRUM().start(
// Root widget
MyApp(),
beforeRunApp: () async => {
// You must call the following method before this callback completes
WidgetsFlutterBinding.ensureInitialized(),
// Other business logic
// ...
},
);
Advanced start configuration
In addition to the start method, you can use the initialize method to start the SDK. When you use this method, you must call WidgetsFlutterBinding.ensureInitialized before calling initialize.
Future<void> initialize();
Example:
// Make sure to call WidgetsFlutterBinding.ensureInitialized before calling initialize
WidgetsFlutterBinding.ensureInitialized();
// Call the initialize method to initialize the SDK
AlibabaCloudRUM().initialize();
// Remember to call runApp
runApp(MyApp());
Register an action collector
The SDK provides AlibabaCloudActionCapture for automatically collecting user click actions in Flutter applications. Register it once at the root Widget of your application and use it to wrap MaterialApp or CupertinoApp.
const AlibabaCloudActionCapture({
Key? key,
required Widget child,
CustomGestureElementCapture? customGestureElementCapture,
})
|
Parameter |
Description |
Constraints |
Failure result |
|
child |
The root application Widget for Action collection. |
Required |
- |
|
customGestureElementCapture |
Custom Widget recognition callback. |
Optional. Unrecognized Widgets return |
If the callback throws an exception or returns an empty |
Basic example:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return AlibabaCloudActionCapture(
child: MaterialApp(
home: const MyHomePage(),
routes: {
// ...
},
navigatorObservers: [
AlibabaCloudRUMNavigationObserver(
ignoreRoutes: ['home_page'],
enablePagePerf: true,
),
],
),
);
}
}
Use ActionAnnotation to set business description and attributes
For actions that require a stable business name or additional attributes, wrap the target Widget with ActionAnnotation in the subtree of AlibabaCloudActionCapture. ActionAnnotation does not change the layout or interaction behavior of the child Widget.
const ActionAnnotation({
Key? key,
required String description,
required Widget child,
Map<String, Object?>? attributes,
})
|
Parameter |
Description |
Constraints |
Failure result |
|
description |
The Action business description for reporting. |
Required |
- |
|
child |
The target Widget to annotate. |
Required |
- |
|
attributes |
Custom attributes reported with the Action. |
Optional. All values must be encodable by |
If encoding fails, the custom attributes are not carried, but the Action continues to be reported. |
Example:
ActionAnnotation(
description: 'Submit Order',
attributes: const {
'page': 'checkout',
'business_action': 'submit_order',
},
child: ElevatedButton(
onPressed: () {
// Submit order.
},
child: const Text('Submit'),
),
)
The above operation prioritizes using description. The expected Action name is Button(Submit Order). The priority of description is higher than the Text content or Semantics labels in the target Widget's subtree. attributes should not contain sensitive data such as passwords, tokens, or personal information.
Recognize business custom Widgets
For business custom Widgets that the SDK cannot recognize by default, you can return GestureCaptureInfo via customGestureElementCapture.
typedef CustomGestureElementCapture = GestureCaptureInfo? Function(
Widget widget,
);
const GestureCaptureInfo(
String elementName, {
bool searchForBetter = false,
bool searchForText = true,
})
|
Parameter |
Description |
Default |
|
elementName |
The element name used when reporting the custom Widget. Cannot be empty. |
None |
|
searchForBetter |
Whether to continue searching downward for a Widget with clearer semantics. When |
|
|
searchForText |
Whether to extract Action description from |
|
Full example:
class BusinessActionWidget extends StatelessWidget {
const BusinessActionWidget({
super.key,
required this.child,
});
final Widget child;
@override
Widget build(BuildContext context) => child;
}
GestureCaptureInfo? recognizeBusinessAction(Widget widget) {
if (widget is BusinessActionWidget) {
return const GestureCaptureInfo(
'BusinessAction',
searchForBetter: false,
searchForText: true,
);
}
// Return null to fall back to the SDK's default recognition logic.
return null;
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return AlibabaCloudActionCapture(
customGestureElementCapture: recognizeBusinessAction,
child: MaterialApp(
home: Scaffold(
body: BusinessActionWidget(
child: ElevatedButton(
onPressed: () {
// Add to shopping cart.
},
child: const Text('Add to Cart'),
),
),
),
),
);
}
}
In the example above, clicking the button results in the expected Action name BusinessAction(Add to Cart). The custom recognition callback should be synchronous and lightweight. Unrecognized Widgets must return null. Even if the callback throws an exception, the SDK isolates the exception and falls back to the default recognition logic, without affecting the original click behavior.
Print error information
When the SDK captures a Flutter exception, it calls FlutterError.dumpErrorToConsole by default to print the error information to the console. You can enable or disable this feature with the setDumpError method.
void setDumpError(bool enable)
|
Parameter |
Description |
Constraints |
Failure result |
|
enable |
Whether to print error information to the console. |
true or false |
- |
Example:
// Disable printing error information to the console
AlibabaCloudRUM().setDumpError(false);
Flutter error callback
Flutter does not support cascading error monitoring, so the original error listeners in your application become inactive after the AlibabaCloudRUM SDK intercepts synchronous and asynchronous errors. The SDK provides a unified error callback interface to address this.
void onRUMErrorCallback(bool callback(Object? error, StackTrace? stack, bool isAsync))
Callback parameters:
|
Parameter |
Type |
Description |
|
error |
Object |
The error cause. |
|
stack |
StackTrace (optional) |
The error stack trace. |
|
isAsync |
bool (optional) |
Whether the error is asynchronous. |
Callback return value:
|
Type |
Constraints |
Description |
|
bool |
|
Whether to continue processing the error. |
Example:
AlibabaCloudRUM().onRUMErrorCallback((error, stack, isAsync) {
// Handle the error event
// ...
// logger.d('debuggg error: $error, stack: $stack');
// Return true to let the SDK report the error
return true;
});
Get the device ID
The SDK generates a device ID by default. Use the getDeviceId method to retrieve it.
Future<String?> getDeviceId() async
Example:
AlibabaCloudRUM().getDeviceId().then(((value) => {print("deviceId: ${value}")}));
Set a custom username
Set user-related information to associate data analysis with actual users.
Future<void> setUserName(String userID) async
|
Parameter |
Description |
Constraints |
Failure result |
|
userName |
The username identifier. |
The string can be null or empty. The string must be 256 characters or less and can contain only digits, letters, colons, spaces, forward slashes, underscores, hyphens, periods, and at signs (@). |
API call fails. The setting does not take effect. |
Example:
AlibabaCloudRUM().setUserName("xxxxx");
Set custom user extra information
Set user-related information to associate data analysis with actual users.
-
Set user extra information. This method uses the overwrite mode. Calling this method overwrites all previously configured user extra information.
Future<void> setUserExtraInfo(Map<String, dynamic> extraInfo) asyncParameter
Description
Constraints
Failure result
extraInfo
The user extra information.
The map can be empty or null. The JSON-serialized length must be 7,000 characters or less. Otherwise, the API call fails.
API call fails. The setting does not take effect.
Example:
AlibabaCloudRUM().setUserExtraInfo({"shopId": "xxxxx", "shopName": "yyyyy"}); -
Append user extra information. This method uses the append mode.
Future<void> addUserExtraInfo(Map<String, dynamic> extraInfo) asyncParameter
Description
Constraints
Failure result
extraInfo
The user extra information.
The map can be empty or null. The JSON-serialized length must be 7,000 characters or less. Otherwise, the API call fails.
API call fails. The setting does not take effect.
Example:
AlibabaCloudRUM().addUserExtraInfo({"userId": "11111111"});
Set custom global extra information
Set global extra information to associate data analysis with actual users.
-
Set global extra information. This method uses the overwrite mode. Calling this method overwrites all previously configured global extra information.
Future<void> setExtraInfo(Map<String, dynamic> extraInfo) asyncParameter
Description
Constraints
Failure result
extraInfo
The global extra information.
The map can be empty or null. The JSON-serialized length must be 7,000 characters or less. Otherwise, the API call fails.
API call fails. The setting does not take effect.
Example:
AlibabaCloudRUM().setExtraInfo({"global_key": "global_value", "global_key2": "global_value2"}); -
Append global extra information. This method uses the append mode.
Future<void> addExtraInfo(Map<String, dynamic> extraInfo) asyncParameter
Description
Constraints
Failure result
extraInfo
The global extra information.
The map can be empty or null. The JSON-serialized length must be 7,000 characters or less. Otherwise, the API call fails.
API call fails. The setting does not take effect.
Example:
AlibabaCloudRUM().addExtraInfo({"global_userId": "2222222222"});
Report custom exceptions
Call the custom exception API to report custom exception data.
Future<void> setCustomException(String exceptionType, String causedBy, String errorDump)
|
Parameter |
Description |
Constraints |
Failure result |
|
exceptionType |
The exception name. Required. |
The string length must be greater than 0 and 256 characters or less. |
API call fails. The setting does not take effect. |
|
causedBy |
The exception information. Required. |
The string must be 512 characters or less. Excess characters are truncated. |
- |
|
errorDump |
The exception stack trace. Optional. |
The string can be null or empty. The string must be 10,000 characters or less. Excess characters are truncated. |
- |
Example:
AlibabaCloudRUM().setCustomException("custom exception type",
"caused by customer",
"Custom error dump");
Report custom events
Report custom events by calling the corresponding API with the required parameters.
Future<void> setCustomEvent(String name, {String? group, String? snapshots, double? value, Map<String, String>? attributes})
|
Parameter |
Description |
Constraints |
Failure result |
|
name |
The event name. Required. |
The string must be 512 characters or less. Excess characters are truncated. |
API call fails. The setting does not take effect. |
|
group |
The event group. Optional. |
The string can be null or empty. The string must be 256 characters or less. Excess characters are truncated. |
- |
|
snapshots |
The event snapshot. Optional. |
The string can be null or empty. The string must be 7,000 characters or less. Excess characters are truncated. |
- |
|
value |
The event value. Optional. |
double type |
- |
|
attributes |
The key-value storage information. Optional. |
The JSON-serialized length must be 7,000 characters or less. |
- |
Example:
AlibabaCloudRUM().setCustomEvent("search_shop",
group: "shop",
snapshots: 'Search: ${search.toString()}',
value: 1,
attributes: {"search": "xxxxx"});
Report custom logs
Report custom log information by calling the corresponding API with the required parameters.
Future<void> setCustomLog(String logInfo, {String? name, String? snapshots, String? level, Map<String, String>? attributes})
|
Parameter |
Description |
Constraints |
Failure result |
|
logInfo |
The log information. Required. |
The string length must be greater than 0 and 10,000 characters or less. Excess characters are truncated. |
API call fails. The setting does not take effect. |
|
name |
The log name. Optional. |
The string length must be greater than 0 and 256 characters or less. |
- |
|
snapshots |
The log snapshot. Optional. |
The string can be null or empty. The string must be 7,000 characters or less. Excess characters are truncated. |
- |
|
level |
The log level. Optional. |
The string length must be greater than 0 and 256 characters or less. Default value: INFO. |
- |
|
attributes |
The log additional information. Optional. |
The map can be empty or null. The JSON-serialized length is shared with logInfo. Otherwise, the API call fails. |
- |
Example:
AlibabaCloudRUM().setCustomLog("2024-08-20 14:00:05 Print shopinfo info.",
name: "shop",
snapshots: 'Shop: ${shop.toString()}',
level: "DEBUG",
attributes: {"shopId": "xxxxx", "shopName": "yyyyy"});
Resource snapshot collection
The SDK supports collecting HTTP request/response headers and payload information. By default, no resource snapshot data is collected. You must explicitly enable this feature using the APIs described in the following sections.
HttpClient
You must set ResourceSnapshotProvider to explicitly enable snapshot collection for the HttpClient library.
void setResourceSnapshotProvider(ResourceSnapshotProvider? provider)
|
Parameter |
Description |
Constraints |
Failure result |
|
onRequestHeaders |
HttpClientRequest |
Map<String, Object>? |
Returns the request headers to collect. null indicates that request headers are not collected. |
|
onRequestPayload |
HttpClientRequest |
String? |
Returns the request body to collect. null indicates that the request body is not collected. |
|
onResponseHeaders |
HttpClientResponse |
Map<String, Object>? |
Returns the response headers to collect. null indicates that response headers are not collected. |
|
onResponsePayload |
HttpClientResponse |
String? |
Returns the response body to collect. null indicates that the response body is not collected. |
ResourceSnapshotUtils utility class
Because HttpClientRequest is a write-only stream and HttpClientResponse is a read-only stream, you must use the utility class to cache the data.
|
Method |
Description |
|
|
Caches the request body. Call this method before |
|
|
Retrieves the cached request body. |
|
|
Caches the response body. Call this method after reading the response stream. |
|
|
Retrieves the cached response body. |
-
Due to limitations of the HttpClient library and the SDK collection implementation, response body collection is not supported.
-
You must use
ResourceSnapshotUtilsto collect request payload information.
Example:
AlibabaCloudRUM().setResourceSnapshotProvider(
ResourceSnapshotProvider(
onRequestHeaders: (request) {
return {
'content-type': request.headers.value('content-type') ?? '',
};
},
onRequestPayload: (request) {
// Because the request object does not retain the payload, you must use the ResourceSnapshotUtils class
// to call the ResourceSnapshotUtils.cacheRequestBody method to cache the payload data when the request is sent
final body = ResourceSnapshotUtils.getCachedRequestBody(request);
if (body == null) return null;
// Make sure to desensitize the data
return body.replaceAll(RegExp(r'"password":\s*"[^"]*"'), '"password":"***"');
},
onResponsePayload: (response) {
// Response payload collection is not supported
return null;
},
),
);
Dio
If you use the Dio networking library, the SDK provides a dedicated interceptor called AlibabaCloudRUMDioInterceptor.
AlibabaCloudRUMDioInterceptor({DioResourceSnapshotProvider? onProvideSnapshots})
|
Parameter |
Description |
Constraints |
Failure result |
|
onProvideSnapshots |
The resource snapshot callback function. |
Can be null. When set to null, the interceptor only monitors requests without collecting snapshots. |
- |
DioResourceSnapshotProvider callback parameters
|
Parameter |
Type |
Description |
|
requestOptions |
RequestOptions |
The Dio request configuration, which includes method, uri, headers, and data. |
|
response |
Response? |
The Dio response object. This parameter can be null when the request fails. |
ResourceSnapshots return value
|
Property |
Type |
Description |
|
requestHeaders |
Map<String, Object>? |
The request headers. null indicates that request headers are not collected. |
|
requestPayload |
String? |
The request body. null indicates that the request body is not collected. |
|
responseHeaders |
Map<String, Object>? |
The response headers. null indicates that response headers are not collected. |
|
responsePayload |
String? |
The response body. null indicates that the response body is not collected. |
Example:
final dio = Dio();
// Add AlibabaCloudRUMDioInterceptor
dio.interceptors.add(
AlibabaCloudRUMDioInterceptor(
onProvideSnapshots: (requestOptions, response, error) {
// The following code is for reference only. Desensitize the data based on your business requirements
final headers = <String, Object>{};
response?.headers.forEach((name, value) {
headers[name] = value;
});
return ResourceSnapshots(
requestHeaders: {...requestOptions.headers},
requestPayload: requestOptions.data,
responseHeaders: {...headers},
responsePayload: jsonEncode(response?.data),
);
},
),
);
// Other code omitted
Important notes
-
The SDK does not collect any headers or payload data by default. You must explicitly enable the feature using the APIs described in this section.
-
The caller of the SDK is responsible for data desensitization. The SDK does not automatically filter any sensitive information, including but not limited to passwords and personally identifiable information (PII).