Skip to content

Commit c4d8c63

Browse files
authored
Use previous HTTP profile timestamps instead of DateTime.now() when requesting HTTP profiles (#8860)
The time between the target process creating the HTTP profile and DevTools invoking DateTime.now() to set the last HTTP data refresh time could result in some HTTP events being missed. This change updates the network service to use the timestamp sent with the last HTTP profile when requesting the next HTTP profile so network latency won't introduce time gaps in the profile. This change also updates the logic to keep track of last HTTP profile request times by isolate as each profile has its own timestamp that needs to be used when requesting the next profile. Fixes #8380 Fixes #8305
1 parent b5c7b2d commit c4d8c63

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

packages/devtools_app/lib/src/screens/network/network_controller.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,6 @@ class NetworkController extends DisposableController
153153
/// timeline events.
154154
late int _timelineMicrosOffset;
155155

156-
/// The last time at which HTTP information was refreshed.
157-
DateTime lastHttpDataRefreshTime = DateTime.fromMicrosecondsSinceEpoch(0);
158-
159156
/// The last timestamp at which Socket information was refreshed.
160157
///
161158
/// This timestamp is on the monotonic clock used by the timeline.

packages/devtools_app/lib/src/screens/network/network_service.dart

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ class NetworkService {
1313

1414
final NetworkController networkController;
1515

16+
/// Tracks the time (microseconds since epoch) that the HTTP profile was last
17+
/// retrieved for a given isolate ID.
18+
final lastHttpDataRefreshTimePerIsolate = <String, int>{};
19+
1620
/// Updates the last Socket data refresh time to the current time.
1721
///
1822
/// If [alreadyRecordingSocketData] is true, it's unclear when the last
@@ -40,11 +44,18 @@ class NetworkService {
4044
///
4145
/// If [alreadyRecordingHttp] is true it's unclear when the last refresh time
4246
/// would have occurred, so the refresh time is not updated. Otherwise,
43-
/// [NetworkController.lastHttpDataRefreshTime] is updated to the current
47+
/// [lastHttpDataRefreshTimePerIsolate] is updated to the current
4448
/// time.
4549
void updateLastHttpDataRefreshTime({bool alreadyRecordingHttp = false}) {
4650
if (!alreadyRecordingHttp) {
47-
networkController.lastHttpDataRefreshTime = DateTime.now();
51+
for (final isolateId in lastHttpDataRefreshTimePerIsolate.keys.toList()) {
52+
// It's safe to use `DateTime.now()` here since we don't need to worry
53+
// about dropping data between the time the last profile was generated
54+
// by the target application and the time `DateTime.now()` is called
55+
// here.
56+
lastHttpDataRefreshTimePerIsolate[isolateId] =
57+
DateTime.now().microsecondsSinceEpoch;
58+
}
4859
}
4960
}
5061

@@ -59,7 +70,6 @@ class NetworkService {
5970
networkController.lastSocketDataRefreshMicros = timestamp;
6071
List<HttpProfileRequest>? httpRequests;
6172
httpRequests = await _refreshHttpProfile();
62-
networkController.lastHttpDataRefreshTime = DateTime.now();
6373
networkController.processNetworkTraffic(
6474
sockets: sockets,
6575
httpRequests: httpRequests,
@@ -74,9 +84,22 @@ class NetworkService {
7484
await service.forEachIsolate((isolate) async {
7585
final request = await service.getHttpProfileWrapper(
7686
isolate.id!,
77-
updatedSince: networkController.lastHttpDataRefreshTime,
87+
updatedSince: DateTime.fromMicrosecondsSinceEpoch(
88+
lastHttpDataRefreshTimePerIsolate.putIfAbsent(
89+
isolate.id!,
90+
// If a new isolate has spawned, request all HTTP requests from the
91+
// start of time when retrieving the first profile.
92+
() => 0,
93+
),
94+
),
7895
);
7996
requests.addAll(request.requests);
97+
// Update the last request time using the timestamp from the HTTP profile
98+
// instead of DateTime.now() to avoid missing events due to the delay
99+
// between the last profile creation in the target process and the call
100+
// to DateTime.now() here.
101+
lastHttpDataRefreshTimePerIsolate[isolate.id!] =
102+
request.timestamp.microsecondsSinceEpoch;
80103
});
81104
return requests;
82105
}

packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ TODO: Remove this section if there are not any general updates.
4545

4646
* Changed the context menu style to be consistent with other screens
4747
[#8859](https://github.com/flutter/devtools/pull/8859).
48+
* Fixed issue where the HTTP requests would sometimes not be displayed properly, particularly when DevTools is communicating with an application over a slow network connection. - [#8860](https://github.com/flutter/devtools/pull/8860)
4849

4950
## Logging updates
5051

0 commit comments

Comments
 (0)