Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,11 @@ class LoggingController extends DevToolsScreenController
autoDisposeStreamSubscription(
service.onExtensionEventWithHistorySafe.listen(_handleExtensionEvent),
);

// Log timer events.
autoDisposeStreamSubscription(
service.onTimerEventWithHistorySafe.listen(_handleTimerEvent),
);
}

void _handleExtensionEvent(Event e) {
Expand Down Expand Up @@ -425,6 +430,18 @@ class LoggingController extends DevToolsScreenController
}
}

void _handleTimerEvent(Event e) {
log(
LogData(
e.kind!,
jsonEncode(e.json),
e.timestamp,
summary: e.details,
isolateRef: e.isolateRef,
),
);
}

void _handleGCEvent(Event e) {
final newSpace = HeapSpace.parse(e.json!['new'])!;
final oldSpace = HeapSpace.parse(e.json!['old'])!;
Expand Down
3 changes: 3 additions & 0 deletions packages/devtools_app/lib/src/screens/logging/metadata.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:devtools_app_shared/service.dart';
import 'package:devtools_app_shared/ui.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:vm_service/vm_service.dart' show EventKind;

import '../../shared/primitives/utils.dart';
import 'logging_controller.dart';
Expand Down Expand Up @@ -201,6 +202,8 @@ class KindMetaDataChip extends MetadataChip {
String? kindIconAsset;
if (kind == 'stdout' || kind == 'stderr') {
kindIcon = Icons.terminal_rounded;
} else if (kind == EventKind.kTimerSignificantlyOverdue) {
Comment thread
derekxu16 marked this conversation as resolved.
kindIcon = Icons.timer_rounded;
} else if (RegExp(r'^flutter\..*$').hasMatch(kind)) {
kindIconAsset = 'icons/flutter.png';
kindIcon = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ class VmServiceWrapper extends VmService {
);
}

Stream<Event> get onTimerEventWithHistorySafe {
return _maybeReturnStreamWithHistory(
onTimerEventWithHistory,
fallbackStream: onTimerEvent,
);
}

Stream<Event> _maybeReturnStreamWithHistory(
Stream<Event> ddsStream, {
required Stream<Event> fallbackStream,
Expand Down
4 changes: 2 additions & 2 deletions packages/devtools_app/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ dependencies:
collection: ^1.15.0
dap: ^1.1.0
dart_service_protocol_shared: ^0.0.3
dds_service_extensions: ^2.0.0
dds_service_extensions: ^2.0.2
devtools_app_shared:
devtools_extensions:
devtools_shared:
Expand Down Expand Up @@ -53,7 +53,7 @@ dependencies:
stack_trace: ^1.12.0
string_scanner: ^1.4.0
unified_analytics: ^7.0.0
vm_service: '>=15.0.0 <16.0.0'
vm_service: ^15.0.2
vm_service_protos: ^1.0.0
vm_snapshot_analysis: ^0.7.6
web: ^1.0.0
Expand Down
3 changes: 2 additions & 1 deletion packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ TODO: Remove this section if there are not any general updates.

## Logging updates

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

## App size tool updates

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ void main() {
);
}

void addTimerData(String message, {required IsolateRef isolateRef}) {
controller.log(
LogData(
EventKind.kTimerSignificantlyOverdue,
jsonEncode({
'kind': EventKind.kTimerSignificantlyOverdue,
'details': message,
'isolateRef': isolateRef.toJson(),
}),
++timestampCounter,
summary: message,
isolateRef: isolateRef,
),
);
}

void addGcData(String message) {
controller.log(
LogData(
Expand Down Expand Up @@ -109,6 +125,15 @@ void main() {
isSystemIsolate: false,
),
);
addTimerData(
'timer event',
isolateRef: IsolateRef(
id: 'isolates/123',
number: '1',
name: 'abc-isolate',
isSystemIsolate: false,
),
);

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

expect(controller.filteredData.value, hasLength(10));
expect(controller.matchesForSearch('abc').length, equals(4));
expect(controller.filteredData.value, hasLength(11));
expect(controller.matchesForSearch('abc').length, equals(5));
expect(controller.matchesForSearch('ghi').length, equals(2));
expect(controller.matchesForSearch('abcd').length, equals(0));
expect(controller.matchesForSearch('Flutter*').length, equals(2));
Expand All @@ -190,7 +215,7 @@ void main() {
expect(controller.matchesForSearch('severe').length, equals(3));

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

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

expect(controller.filteredData.value, hasLength(17));
expect(controller.matchesForSearch('abc').length, equals(5));
expect(controller.filteredData.value, hasLength(18));
expect(controller.matchesForSearch('abc').length, equals(6));
expect(controller.matchesForSearch('ghi').length, equals(3));
expect(controller.matchesForSearch('abcd').length, equals(0));
expect(controller.matchesForSearch('Flutter*').length, equals(7));
Expand All @@ -219,7 +244,7 @@ void main() {
expect(controller.matchesForSearch('severe').length, equals(3));

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

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

expect(controller.filteredData.value, hasLength(10));
expect(controller.filteredData.value, hasLength(11));
controller.search = 'abc';
var matches = controller.searchMatches.value;
expect(matches.length, equals(4));
expect(matches.length, equals(5));
verifyIsSearchMatch(controller.filteredData.value, matches);

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

// At this point data is filtered by the default setting filter values.
expect(controller.data, hasLength(17));
expect(controller.filteredData.value, hasLength(10));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(11));

controller.setActiveFilter(query: 'abc');
expect(controller.data, hasLength(17));
expect(controller.filteredData.value, hasLength(4));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(5));

controller.setActiveFilter(query: 'def');
expect(controller.data, hasLength(17));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(2));

controller.setActiveFilter(query: 'abc def');
expect(controller.data, hasLength(17));
expect(controller.filteredData.value, hasLength(6));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(7));

controller.setActiveFilter(query: 'k:stdout');
expect(controller.data, hasLength(17));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(6));

controller.setActiveFilter(query: '-k:stdout');
expect(controller.data, hasLength(17));
expect(controller.filteredData.value, hasLength(4));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(5));

controller.setActiveFilter(query: 'k:stdout abc');
expect(controller.data, hasLength(17));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(3));

controller.setActiveFilter(query: 'k:stdout,flutter.navigation');
expect(controller.data, hasLength(17));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(7));

controller.setActiveFilter();
expect(controller.data, hasLength(17));
expect(controller.filteredData.value, hasLength(10));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(11));

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

verboseFlutterFrameworkFilter.setting.value = false;
controller.setActiveFilter();
expect(controller.data, hasLength(17));
expect(controller.filteredData.value, hasLength(14));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(15));

verboseFlutterServiceFilter.setting.value = false;
controller.setActiveFilter();
expect(controller.data, hasLength(17));
expect(controller.filteredData.value, hasLength(15));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(16));

gcFilter.setting.value = false;
controller.setActiveFilter();
expect(controller.data, hasLength(17));
expect(controller.filteredData.value, hasLength(17));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(18));

minimumLogLevelFilter.setting.value = Level.SEVERE.value;
controller.setActiveFilter();
expect(controller.data, hasLength(17));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(3));
});

Expand All @@ -330,8 +355,8 @@ void main() {
});

test('releaseMemory - partial release', () {
expect(controller.data, hasLength(17));
expect(controller.filteredData.value, hasLength(10));
expect(controller.data, hasLength(18));
expect(controller.filteredData.value, hasLength(11));
controller.releaseMemory(partial: true);
expect(controller.data, hasLength(9));
expect(controller.filteredData.value, hasLength(2));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,4 +539,10 @@ class FakeVmServiceWrapper extends Fake implements VmServiceWrapper {

@override
Stream<Event> get onIsolateEvent => const Stream.empty();

@override
Stream<Event> get onTimerEvent => const Stream.empty();

@override
Stream<Event> get onTimerEventWithHistorySafe => const Stream.empty();
}