Skip to content

Commit 5436ea4

Browse files
authored
Show Timer events in the Logging View (#9238)
1 parent 4bc942d commit 5436ea4

7 files changed

Lines changed: 93 additions & 34 deletions

File tree

packages/devtools_app/lib/src/screens/logging/logging_controller.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,11 @@ class LoggingController extends DevToolsScreenController
311311
autoDisposeStreamSubscription(
312312
service.onExtensionEventWithHistorySafe.listen(_handleExtensionEvent),
313313
);
314+
315+
// Log timer events.
316+
autoDisposeStreamSubscription(
317+
service.onTimerEventWithHistorySafe.listen(_handleTimerEvent),
318+
);
314319
}
315320

316321
void _handleExtensionEvent(Event e) {
@@ -425,6 +430,18 @@ class LoggingController extends DevToolsScreenController
425430
}
426431
}
427432

433+
void _handleTimerEvent(Event e) {
434+
log(
435+
LogData(
436+
e.kind!,
437+
jsonEncode(e.json),
438+
e.timestamp,
439+
summary: e.details,
440+
isolateRef: e.isolateRef,
441+
),
442+
);
443+
}
444+
428445
void _handleGCEvent(Event e) {
429446
final newSpace = HeapSpace.parse(e.json!['new'])!;
430447
final oldSpace = HeapSpace.parse(e.json!['old'])!;

packages/devtools_app/lib/src/screens/logging/metadata.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:devtools_app_shared/service.dart';
88
import 'package:devtools_app_shared/ui.dart';
99
import 'package:flutter/material.dart';
1010
import 'package:logging/logging.dart';
11+
import 'package:vm_service/vm_service.dart' show EventKind;
1112

1213
import '../../shared/primitives/utils.dart';
1314
import 'logging_controller.dart';
@@ -201,6 +202,8 @@ class KindMetaDataChip extends MetadataChip {
201202
String? kindIconAsset;
202203
if (kind == 'stdout' || kind == 'stderr') {
203204
kindIcon = Icons.terminal_rounded;
205+
} else if (kind == EventKind.kTimerSignificantlyOverdue) {
206+
kindIcon = Icons.timer_rounded;
204207
} else if (RegExp(r'^flutter\..*$').hasMatch(kind)) {
205208
kindIconAsset = 'icons/flutter.png';
206209
kindIcon = null;

packages/devtools_app/lib/src/service/vm_service_wrapper.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,13 @@ class VmServiceWrapper extends VmService {
246246
);
247247
}
248248

249+
Stream<Event> get onTimerEventWithHistorySafe {
250+
return _maybeReturnStreamWithHistory(
251+
onTimerEventWithHistory,
252+
fallbackStream: onTimerEvent,
253+
);
254+
}
255+
249256
Stream<Event> _maybeReturnStreamWithHistory(
250257
Stream<Event> ddsStream, {
251258
required Stream<Event> fallbackStream,

packages/devtools_app/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ dependencies:
2222
collection: ^1.15.0
2323
dap: ^1.1.0
2424
dart_service_protocol_shared: ^0.0.3
25-
dds_service_extensions: ^2.0.0
25+
dds_service_extensions: ^2.0.2
2626
devtools_app_shared:
2727
devtools_extensions:
2828
devtools_shared:
@@ -53,7 +53,7 @@ dependencies:
5353
stack_trace: ^1.12.0
5454
string_scanner: ^1.4.0
5555
unified_analytics: ^7.0.0
56-
vm_service: '>=15.0.0 <16.0.0'
56+
vm_service: ^15.0.2
5757
vm_service_protos: ^1.0.0
5858
vm_snapshot_analysis: ^0.7.6
5959
web: ^1.0.0

packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ TODO: Remove this section if there are not any general updates.
4343

4444
## Logging updates
4545

46-
TODO: Remove this section if there are not any general updates.
46+
* Started displaying events related to timers in the Logging View. -
47+
[#9238](https://github.com/flutter/devtools/pull/9238).
4748

4849
## App size tool updates
4950

packages/devtools_app/test/screens/logging/logging_controller_test.dart

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@ void main() {
4848
);
4949
}
5050

51+
void addTimerData(String message, {required IsolateRef isolateRef}) {
52+
controller.log(
53+
LogData(
54+
EventKind.kTimerSignificantlyOverdue,
55+
jsonEncode({
56+
'kind': EventKind.kTimerSignificantlyOverdue,
57+
'details': message,
58+
'isolateRef': isolateRef.toJson(),
59+
}),
60+
++timestampCounter,
61+
summary: message,
62+
isolateRef: isolateRef,
63+
),
64+
);
65+
}
66+
5167
void addGcData(String message) {
5268
controller.log(
5369
LogData(
@@ -109,6 +125,15 @@ void main() {
109125
isSystemIsolate: false,
110126
),
111127
);
128+
addTimerData(
129+
'timer event',
130+
isolateRef: IsolateRef(
131+
id: 'isolates/123',
132+
number: '1',
133+
name: 'abc-isolate',
134+
isSystemIsolate: false,
135+
),
136+
);
112137

113138
// The following logs should all be filtered by default.
114139
addGcData('gc1 abc');
@@ -173,8 +198,8 @@ void main() {
173198
test('matchesForSearch - default filters', () {
174199
prepareTestLogs();
175200

176-
expect(controller.filteredData.value, hasLength(10));
177-
expect(controller.matchesForSearch('abc').length, equals(4));
201+
expect(controller.filteredData.value, hasLength(11));
202+
expect(controller.matchesForSearch('abc').length, equals(5));
178203
expect(controller.matchesForSearch('ghi').length, equals(2));
179204
expect(controller.matchesForSearch('abcd').length, equals(0));
180205
expect(controller.matchesForSearch('Flutter*').length, equals(2));
@@ -190,7 +215,7 @@ void main() {
190215
expect(controller.matchesForSearch('severe').length, equals(3));
191216

192217
// Search by isolateRef name.
193-
expect(controller.matchesForSearch('-isolate').length, equals(1));
218+
expect(controller.matchesForSearch('-isolate').length, equals(2));
194219

195220
// Search by zone name.
196221
expect(controller.matchesForSearch('root').length, equals(1));
@@ -202,8 +227,8 @@ void main() {
202227
disableAllFilters();
203228
prepareTestLogs();
204229

205-
expect(controller.filteredData.value, hasLength(17));
206-
expect(controller.matchesForSearch('abc').length, equals(5));
230+
expect(controller.filteredData.value, hasLength(18));
231+
expect(controller.matchesForSearch('abc').length, equals(6));
207232
expect(controller.matchesForSearch('ghi').length, equals(3));
208233
expect(controller.matchesForSearch('abcd').length, equals(0));
209234
expect(controller.matchesForSearch('Flutter*').length, equals(7));
@@ -219,7 +244,7 @@ void main() {
219244
expect(controller.matchesForSearch('severe').length, equals(3));
220245

221246
// Search by isolateRef name.
222-
expect(controller.matchesForSearch('-isolate').length, equals(1));
247+
expect(controller.matchesForSearch('-isolate').length, equals(2));
223248

224249
// Search by zone name.
225250
expect(controller.matchesForSearch('root').length, equals(1));
@@ -230,10 +255,10 @@ void main() {
230255
test('matchesForSearch sets isSearchMatch property', () {
231256
prepareTestLogs();
232257

233-
expect(controller.filteredData.value, hasLength(10));
258+
expect(controller.filteredData.value, hasLength(11));
234259
controller.search = 'abc';
235260
var matches = controller.searchMatches.value;
236-
expect(matches.length, equals(4));
261+
expect(matches.length, equals(5));
237262
verifyIsSearchMatch(controller.filteredData.value, matches);
238263

239264
controller.search = 'Flutter.';
@@ -246,40 +271,40 @@ void main() {
246271
prepareTestLogs();
247272

248273
// At this point data is filtered by the default setting filter values.
249-
expect(controller.data, hasLength(17));
250-
expect(controller.filteredData.value, hasLength(10));
274+
expect(controller.data, hasLength(18));
275+
expect(controller.filteredData.value, hasLength(11));
251276

252277
controller.setActiveFilter(query: 'abc');
253-
expect(controller.data, hasLength(17));
254-
expect(controller.filteredData.value, hasLength(4));
278+
expect(controller.data, hasLength(18));
279+
expect(controller.filteredData.value, hasLength(5));
255280

256281
controller.setActiveFilter(query: 'def');
257-
expect(controller.data, hasLength(17));
282+
expect(controller.data, hasLength(18));
258283
expect(controller.filteredData.value, hasLength(2));
259284

260285
controller.setActiveFilter(query: 'abc def');
261-
expect(controller.data, hasLength(17));
262-
expect(controller.filteredData.value, hasLength(6));
286+
expect(controller.data, hasLength(18));
287+
expect(controller.filteredData.value, hasLength(7));
263288

264289
controller.setActiveFilter(query: 'k:stdout');
265-
expect(controller.data, hasLength(17));
290+
expect(controller.data, hasLength(18));
266291
expect(controller.filteredData.value, hasLength(6));
267292

268293
controller.setActiveFilter(query: '-k:stdout');
269-
expect(controller.data, hasLength(17));
270-
expect(controller.filteredData.value, hasLength(4));
294+
expect(controller.data, hasLength(18));
295+
expect(controller.filteredData.value, hasLength(5));
271296

272297
controller.setActiveFilter(query: 'k:stdout abc');
273-
expect(controller.data, hasLength(17));
298+
expect(controller.data, hasLength(18));
274299
expect(controller.filteredData.value, hasLength(3));
275300

276301
controller.setActiveFilter(query: 'k:stdout,flutter.navigation');
277-
expect(controller.data, hasLength(17));
302+
expect(controller.data, hasLength(18));
278303
expect(controller.filteredData.value, hasLength(7));
279304

280305
controller.setActiveFilter();
281-
expect(controller.data, hasLength(17));
282-
expect(controller.filteredData.value, hasLength(10));
306+
expect(controller.data, hasLength(18));
307+
expect(controller.filteredData.value, hasLength(11));
283308

284309
// Test setting filters.
285310
final minimumLogLevelFilter =
@@ -292,22 +317,22 @@ void main() {
292317

293318
verboseFlutterFrameworkFilter.setting.value = false;
294319
controller.setActiveFilter();
295-
expect(controller.data, hasLength(17));
296-
expect(controller.filteredData.value, hasLength(14));
320+
expect(controller.data, hasLength(18));
321+
expect(controller.filteredData.value, hasLength(15));
297322

298323
verboseFlutterServiceFilter.setting.value = false;
299324
controller.setActiveFilter();
300-
expect(controller.data, hasLength(17));
301-
expect(controller.filteredData.value, hasLength(15));
325+
expect(controller.data, hasLength(18));
326+
expect(controller.filteredData.value, hasLength(16));
302327

303328
gcFilter.setting.value = false;
304329
controller.setActiveFilter();
305-
expect(controller.data, hasLength(17));
306-
expect(controller.filteredData.value, hasLength(17));
330+
expect(controller.data, hasLength(18));
331+
expect(controller.filteredData.value, hasLength(18));
307332

308333
minimumLogLevelFilter.setting.value = Level.SEVERE.value;
309334
controller.setActiveFilter();
310-
expect(controller.data, hasLength(17));
335+
expect(controller.data, hasLength(18));
311336
expect(controller.filteredData.value, hasLength(3));
312337
});
313338

@@ -330,8 +355,8 @@ void main() {
330355
});
331356

332357
test('releaseMemory - partial release', () {
333-
expect(controller.data, hasLength(17));
334-
expect(controller.filteredData.value, hasLength(10));
358+
expect(controller.data, hasLength(18));
359+
expect(controller.filteredData.value, hasLength(11));
335360
controller.releaseMemory(partial: true);
336361
expect(controller.data, hasLength(9));
337362
expect(controller.filteredData.value, hasLength(2));

packages/devtools_test/lib/src/mocks/fake_vm_service_wrapper.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,4 +539,10 @@ class FakeVmServiceWrapper extends Fake implements VmServiceWrapper {
539539

540540
@override
541541
Stream<Event> get onIsolateEvent => const Stream.empty();
542+
543+
@override
544+
Stream<Event> get onTimerEvent => const Stream.empty();
545+
546+
@override
547+
Stream<Event> get onTimerEventWithHistorySafe => const Stream.empty();
542548
}

0 commit comments

Comments
 (0)