Skip to content

feat/screen-render-updates #617

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ target 'Runner' do

use_frameworks!
use_modular_headers!
pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.17/Instabug.podspec'
pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.23/Instabug.podspec'
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

Expand Down
14 changes: 7 additions & 7 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
PODS:
- Flutter (1.0.0)
- Instabug (15.1.17)
- Instabug (15.1.23)
- instabug_flutter (14.3.0):
- Flutter
- Instabug (= 15.1.17)
- Instabug (= 15.1.23)
- OCMock (3.6)

DEPENDENCIES:
- Flutter (from `Flutter`)
- Instabug (from `https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.17/Instabug.podspec`)
- Instabug (from `https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.23/Instabug.podspec`)
- instabug_flutter (from `.symlinks/plugins/instabug_flutter/ios`)
- OCMock (= 3.6)

Expand All @@ -20,16 +20,16 @@ EXTERNAL SOURCES:
Flutter:
:path: Flutter
Instabug:
:podspec: https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.17/Instabug.podspec
:podspec: https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.23/Instabug.podspec
instabug_flutter:
:path: ".symlinks/plugins/instabug_flutter/ios"

SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
Instabug: 316559a02c9b752a3854a6453c2fa414d36252f3
instabug_flutter: 7ae7f3d1c47b9a699e76a7358b6a3e818a253ac3
Instabug: b4659339dc6f67693cf9bd1224abc66831b8722f
instabug_flutter: eeb2e13eefca00e94de1f9156df4889f5481506a
OCMock: 5ea90566be239f179ba766fd9fbae5885040b992

PODFILE CHECKSUM: 8f3e14dab36cc02b0a8767c3086e109fadaa55f3
PODFILE CHECKSUM: 6d8ca5577997736d9cc2249886c9f6d10238385d

COCOAPODS: 1.15.2
2 changes: 2 additions & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import 'src/widget/section_title.dart';

part 'src/components/animated_box.dart';
part 'src/components/apm_switch.dart';

part 'src/components/fatal_crashes_content.dart';
part 'src/components/flows_content.dart';
part 'src/components/network_content.dart';
Expand All @@ -44,6 +45,7 @@ void main() {

Instabug.init(
token: 'ed6f659591566da19b67857e1b9d40ab',
// token: '4d75635ae06e5afb4360c04cfcf1987c',
invocationEvents: [InvocationEvent.floatingButton],
debugLogsLevel: LogLevel.verbose,
).then((_) {
Expand Down
2 changes: 1 addition & 1 deletion ios/instabug_flutter.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ Pod::Spec.new do |s|
s.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-framework "Flutter" -framework "InstabugSDK"'}

s.dependency 'Flutter'
s.dependency 'Instabug', '15.1.17'
s.dependency 'Instabug', '15.1.23'
end

6 changes: 4 additions & 2 deletions lib/src/modules/apm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ class APM {
(_) async {
// Start screen render collector for custom ui trace if enabled.
if (await FlagsConfig.screenRendering.isEnabled()) {
InstabugScreenRenderManager.I.endScreenRenderCollector();

// final uiTraceId = IBGDateTime.I.now().millisecondsSinceEpoch;
InstabugScreenRenderManager.I
.startScreenRenderCollectorForTraceId(0, UiTraceType.custom);
}
Expand All @@ -210,8 +213,7 @@ class APM {
static Future<void> endUITrace() async {
// End screen render collector for custom ui trace if enabled.
if (InstabugScreenRenderManager.I.screenRenderEnabled) {
return InstabugScreenRenderManager.I
.endScreenRenderCollectorForCustomUiTrace();
return InstabugScreenRenderManager.I.endScreenRenderCollector();
}

return _host.endUITrace();
Expand Down
3 changes: 3 additions & 0 deletions lib/src/utils/instabug_navigator_observer.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:instabug_flutter/instabug_flutter.dart';
Expand Down Expand Up @@ -27,6 +28,7 @@ class InstabugNavigatorObserver extends NavigatorObserver {
name: maskedScreenName,
);

InstabugScreenRenderManager.I.endScreenRenderCollector();
ScreenLoadingManager.I
.startUiTrace(maskedScreenName, screenName)
.then(_startScreenRenderCollector);
Expand Down Expand Up @@ -67,6 +69,7 @@ class InstabugNavigatorObserver extends NavigatorObserver {

FutureOr<void> _startScreenRenderCollector(int? uiTraceId) async {
final isScreenRenderEnabled = await FlagsConfig.screenRendering.isEnabled();
log("isScreenRenderEnabled $isScreenRenderEnabled", name: "Andrew");
await _checkForScreenRenderInitialization(isScreenRenderEnabled);
if (uiTraceId != null && isScreenRenderEnabled) {
InstabugScreenRenderManager.I
Expand Down
76 changes: 42 additions & 34 deletions lib/src/utils/screen_rendering/instabug_screen_render_manager.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer' show log;
import 'dart:ui' show TimingsCallback, FrameTiming, FramePhase;

import 'package:flutter/widgets.dart';
Expand Down Expand Up @@ -131,73 +132,68 @@ class InstabugScreenRenderManager {
return;
}

//Save the memory cached data to be sent to native side
if (_delayedFrames.isNotEmpty) {
_saveCollectedData();
_resetCachedFrameData();
}

//Sync the captured screen render data of the Custom UI trace when starting new one
if (type == UiTraceType.custom) {
// Report only if the collector was active
if (_screenRenderForCustomUiTrace.isActive) {
_reportScreenRenderForCustomUiTrace(_screenRenderForCustomUiTrace);
_screenRenderForCustomUiTrace.clear();
}
_screenRenderForCustomUiTrace.traceId = traceId;
}

//Sync the captured screen render data of the Auto UI trace when starting new one
if (type == UiTraceType.auto) {
// Report only if the collector was active
if (_screenRenderForAutoUiTrace.isActive) {
_reportScreenRenderForAutoUiTrace(_screenRenderForAutoUiTrace);
_screenRenderForAutoUiTrace.clear();
}
_screenRenderForAutoUiTrace.traceId = traceId;
}
} catch (error, stackTrace) {
_logExceptionErrorAndStackTrace(error, stackTrace);
}
}

/// Stop screen render collector and sync the captured data.
@internal
void stopScreenRenderCollector() {
void endScreenRenderCollector([
UiTraceType type = UiTraceType.auto,
]) {
try {
// Return if frameTimingListener not attached
if (!screenRenderEnabled || !_isTimingsListenerAttached) {
return;
}

//Save the memory cached data to be sent to native side
if (_delayedFrames.isNotEmpty) {
_saveCollectedData();
_resetCachedFrameData();
}

// Sync Screen Render data for custom ui trace if exists
if (_screenRenderForCustomUiTrace.isActive) {
//Sync the captured screen render data of the Custom UI trace if the collector was active
if (type == UiTraceType.custom &&
_screenRenderForCustomUiTrace.isActive) {
_reportScreenRenderForCustomUiTrace(_screenRenderForCustomUiTrace);
_screenRenderForCustomUiTrace.clear();
}

// Sync Screen Render data for auto ui trace if exists
if (_screenRenderForAutoUiTrace.isActive) {
//Sync the captured screen render data of the Auto UI trace if the collector was active
if (type == UiTraceType.auto && _screenRenderForAutoUiTrace.isActive) {
_reportScreenRenderForAutoUiTrace(_screenRenderForAutoUiTrace);
_screenRenderForAutoUiTrace.clear();
}
} catch (error, stackTrace) {
_logExceptionErrorAndStackTrace(error, stackTrace);
}
}

/// Sync the capture screen render data of the custom UI trace without stopping the collector.
/// Stop screen render collector and sync the captured data.
@internal
void endScreenRenderCollectorForCustomUiTrace() {
void stopScreenRenderCollector() {
try {
if (!_screenRenderForCustomUiTrace.isActive) {
return;
if (_delayedFrames.isNotEmpty) {
_saveCollectedData();
}

// Save the captured screen rendering data to be synced
_updateCustomUiData();

// Sync the saved screen rendering data
_reportScreenRenderForCustomUiTrace(_screenRenderForCustomUiTrace);
// Sync Screen Render data for custom ui trace if exists
if (_screenRenderForCustomUiTrace.isActive) {
_reportScreenRenderForCustomUiTrace(_screenRenderForCustomUiTrace);
}

_screenRenderForCustomUiTrace.clear();
// Sync Screen Render data for auto ui trace if exists
if (_screenRenderForAutoUiTrace.isActive) {
_reportScreenRenderForAutoUiTrace(_screenRenderForAutoUiTrace);
}
} catch (error, stackTrace) {
_logExceptionErrorAndStackTrace(error, stackTrace);
}
Expand Down Expand Up @@ -300,6 +296,10 @@ class InstabugScreenRenderManager {

/// Save Slow/Frozen Frames data
void _onDelayedFrameDetected(int startTime, int durationInMicroseconds) {
log(
"${durationInMicroseconds >= 700000 ? "🚨Frozen" : "⚠️Slow"} Frame Detected (startTime: $startTime, duration: $durationInMicroseconds µs)",
name: tag,
);
_delayedFrames.add(
InstabugFrameData(
startTime,
Expand All @@ -315,6 +315,10 @@ class InstabugScreenRenderManager {
InstabugScreenRenderData screenRenderData,
) async {
try {
log(
"reportScreenRenderForCustomUiTrace $screenRenderData",
name: tag,
);
await APM.endScreenRenderForCustomUiTrace(screenRenderData);
return true;
} catch (error, stackTrace) {
Expand All @@ -332,6 +336,10 @@ class InstabugScreenRenderManager {
try {
// Save the end time for the running ui trace, it's only needed in Android SDK.
screenRenderData.saveEndTime();
log(
"reportScreenRenderForAutoUiTrace $screenRenderData",
name: tag,
);
await APM.endScreenRenderForAutoUiTrace(screenRenderData);

return true;
Expand Down
7 changes: 2 additions & 5 deletions test/apm_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -346,13 +346,10 @@ void main() {
() async {
when(mHost.isScreenRenderEnabled()).thenAnswer((_) async => true);
when(mScreenRenderManager.screenRenderEnabled).thenReturn(true);
const traceName = "traceNameTest";
await APM.startUITrace(traceName);
await APM.endUITrace();

verify(mHost.startUITrace(traceName)).called(1);
verify(
mScreenRenderManager.endScreenRenderCollectorForCustomUiTrace(),
mScreenRenderManager.endScreenRenderCollector(),
).called(1);
verifyNever(mHost.endUITrace());
});
Expand All @@ -371,7 +368,7 @@ void main() {
mHost.endUITrace(),
).called(1);
verifyNever(
mScreenRenderManager.endScreenRenderCollectorForCustomUiTrace(),
mScreenRenderManager.endScreenRenderCollector(),
);
});
});
Expand Down
73 changes: 50 additions & 23 deletions test/utils/screen_render/instabug_screen_render_manager_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,6 @@ void main() {
); // the one form initForTesting()
});

test(
'should report data to native when starting new trace from the same type',
() async {
final frameTestData = InstabugScreenRenderData(
traceId: 123,
frameData: [
InstabugFrameData(10000, 200),
InstabugFrameData(20000, 1000),
],
frozenFramesTotalDurationMicro: 1000,
slowFramesTotalDurationMicro: 200,
);

manager.startScreenRenderCollectorForTraceId(frameTestData.traceId);
manager.setFrameData(frameTestData);
manager.startScreenRenderCollectorForTraceId(2);
verify(mApmHost.endScreenRenderForAutoUiTrace(any)).called(1);
});

test('should attach timing listener if it is not attached', () async {
manager.stopScreenRenderCollector(); // this should detach listener safely

Expand Down Expand Up @@ -272,7 +253,7 @@ void main() {

manager.setFrameData(frameTestData);

manager.endScreenRenderCollectorForCustomUiTrace();
manager.endScreenRenderCollector();

expect(manager.screenRenderForCustomUiTrace.isActive, false);
expect(manager.screenRenderForCustomUiTrace == frameTestData, false);
Expand All @@ -298,11 +279,11 @@ void main() {

manager.setFrameData(frameTestData);

manager.endScreenRenderCollectorForCustomUiTrace();
manager.endScreenRenderCollector();
});

test('should not remove timing callback listener', () {
manager.endScreenRenderCollectorForCustomUiTrace();
manager.endScreenRenderCollector();

verifyNever(mWidgetBinding.removeTimingsCallback(any));
});
Expand All @@ -320,7 +301,7 @@ void main() {

manager.startScreenRenderCollectorForTraceId(0, UiTraceType.custom);
manager.setFrameData(frameTestData);
manager.endScreenRenderCollectorForCustomUiTrace();
manager.endScreenRenderCollector(UiTraceType.custom);
verify(mApmHost.endScreenRenderForCustomUiTrace(any)).called(1);
});
});
Expand Down Expand Up @@ -419,4 +400,50 @@ void main() {
);
});
});

group('InstabugScreenRenderManager.endScreenRenderCollector', () {
test('should save and reset cached data if delayed frames exist', () {
final frameTestData = InstabugScreenRenderData(
traceId: 123,
frameData: [
InstabugFrameData(10000, 200),
InstabugFrameData(20000, 1000),
],
frozenFramesTotalDurationMicro: 1000,
slowFramesTotalDurationMicro: 200,
);
manager.startScreenRenderCollectorForTraceId(1);
manager.setFrameData(frameTestData);
manager.endScreenRenderCollector();
verify(mApmHost.endScreenRenderForAutoUiTrace(any)).called(1);
expect(manager.screenRenderForAutoUiTrace.isEmpty, true);
expect(manager.screenRenderForAutoUiTrace.isActive, false);
});

test('should report and clear custom trace if type is custom and active',
() {
final frameTestData = InstabugScreenRenderData(
traceId: 123,
frameData: [
InstabugFrameData(10000, 200),
InstabugFrameData(20000, 1000),
],
frozenFramesTotalDurationMicro: 1000,
slowFramesTotalDurationMicro: 200,
);
manager.startScreenRenderCollectorForTraceId(1, UiTraceType.custom);
manager.setFrameData(frameTestData);
manager.endScreenRenderCollector(UiTraceType.custom);
verify(mApmHost.endScreenRenderForCustomUiTrace(any)).called(1);
expect(manager.screenRenderForCustomUiTrace.isEmpty, true);
expect(manager.screenRenderForCustomUiTrace.isActive, false);
});

test('should return early if not enabled or timings not attached', () {
manager.screenRenderEnabled = false;
manager.endScreenRenderCollector();
verifyNever(mApmHost.endScreenRenderForAutoUiTrace(any));
verifyNever(mApmHost.endScreenRenderForCustomUiTrace(any));
});
});
}
Loading