From e87f3407c83560fc5be5eea0cd018790cd2fdbb0 Mon Sep 17 00:00:00 2001 From: Ben Konyi Date: Thu, 3 Oct 2019 16:33:38 +0000 Subject: [PATCH] [ dart:developer ] Added optional `parent` parameter to `TimelineTask` constructors. Specifying a parent will result in an argument being added to 'start' events for that TimelineTask named 'parentId', which contains the task ID of the parent. This is to be used by DevTools to show relationships between asynchronous tasks that are not currently supported in the trace event format used by Catapult. Change-Id: Id0a030f018f5a6ac1e3b0ef2e89c1cd732790f02 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/119520 Commit-Queue: Ben Konyi Reviewed-by: Kenzie Schmoll Reviewed-by: Siva Annamalai --- CHANGELOG.md | 5 +++++ .../service/get_vm_timeline_rpc_test.dart | 7 +++--- sdk/lib/developer/timeline.dart | 22 ++++++++++++++++--- sdk_nnbd/lib/developer/timeline.dart | 22 ++++++++++++++++--- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81f49ec6e35..07947ae378c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,11 @@ main() { foo(() {}); } * Default values of parameters of abstract methods are no longer available via `dart:mirrors`. +#### `dart:developer` + +* Added optional `parent` paremeter to `TimelineTask` constructors to allow for + linking of asynchronous timeline events in the DevTools timeline view. + ### Dart VM ### Tools diff --git a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart index 3884a9b8078..420c912ee39 100644 --- a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart +++ b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart @@ -13,7 +13,8 @@ primeTimeline() { Timeline.startSync('apple'); Timeline.instantSync('ISYNC', arguments: {'fruit': 'banana'}); Timeline.finishSync(); - TimelineTask task = new TimelineTask(); + TimelineTask parentTask = TimelineTask.withTaskId(42); + TimelineTask task = TimelineTask(parent: parentTask); task.start('TASK1', arguments: {'task1-start-key': 'task1-start-value'}); task.instant('ITASK', arguments: {'task1-instant-key': 'task1-instant-value'}); @@ -126,8 +127,8 @@ var tests = [ eventsContains(dartEvents, 'i', 'ISYNC', {'fruit': 'banana'}), isTrue); expect(eventsContains(dartEvents, 'X', 'apple'), isTrue); expect( - eventsContains( - dartEvents, 'b', 'TASK1', {'task1-start-key': 'task1-start-value'}), + eventsContains(dartEvents, 'b', 'TASK1', + {'task1-start-key': 'task1-start-value', 'parentId': 42}), isTrue); expect( eventsContains(dartEvents, 'e', 'TASK1', diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart index 02f9c98c3fa..fec807a4857 100644 --- a/sdk/lib/developer/timeline.dart +++ b/sdk/lib/developer/timeline.dart @@ -180,11 +180,23 @@ class Timeline { /// [TimelineTask] in the other isolate. class TimelineTask { /// Create a task. The task ID will be set by the system. - TimelineTask() : _taskId = _getNextAsyncId() {} + /// + /// If [parent] is provided, the parent's task ID is provided as argument + /// 'parentId' when [start] is called. In DevTools, this argument will result + /// in this [TimelineTask] being linked to the [parent] [TimelineTask]. + TimelineTask({TimelineTask parent}) + : _parent = parent, + _taskId = _getNextAsyncId() {} /// Create a task with an explicit [taskId]. This is useful if you are /// passing a task from one isolate to another. - TimelineTask.withTaskId(int taskId) : _taskId = taskId { + /// + /// If [parent] is provided, the parent's task ID is provided as argument + /// 'parentId' when [start] is called. In DevTools, this argument will result + /// in this [TimelineTask] being linked to the [parent] [TimelineTask]. + TimelineTask.withTaskId(int taskId, {TimelineTask parent}) + : _parent = parent, + _taskId = taskId { ArgumentError.checkNotNull(taskId, 'taskId'); } @@ -195,7 +207,10 @@ class TimelineTask { ArgumentError.checkNotNull(name, 'name'); var block = new _AsyncBlock._(name, _taskId); _stack.add(block); - block._start(arguments); + block._start({ + if (arguments != null) ...arguments, + if (_parent != null) 'parentId': _parent._taskId, + }); } /// Emit an instant event for this task. @@ -237,6 +252,7 @@ class TimelineTask { return r; } + final TimelineTask _parent; final int _taskId; final List<_AsyncBlock> _stack = []; } diff --git a/sdk_nnbd/lib/developer/timeline.dart b/sdk_nnbd/lib/developer/timeline.dart index 2e5f4ecee8b..a7107c3b4e3 100644 --- a/sdk_nnbd/lib/developer/timeline.dart +++ b/sdk_nnbd/lib/developer/timeline.dart @@ -182,11 +182,23 @@ class Timeline { /// [TimelineTask] in the other isolate. class TimelineTask { /// Create a task. The task ID will be set by the system. - TimelineTask() : _taskId = _getNextAsyncId() {} + /// + /// If [parent] is provided, the parent's task ID is provided as argument + /// 'parentId' when [start] is called. In DevTools, this argument will result + /// in this [TimelineTask] being linked to the [parent] [TimelineTask]. + TimelineTask({TimelineTask parent}) + : _parent = parent, + _taskId = _getNextAsyncId() {} /// Create a task with an explicit [taskId]. This is useful if you are /// passing a task from one isolate to another. - TimelineTask.withTaskId(int taskId) : _taskId = taskId { + /// + /// If [parent] is provided, the parent's task ID is provided as argument + /// 'parentId' when [start] is called. In DevTools, this argument will result + /// in this [TimelineTask] being linked to the [parent] [TimelineTask]. + TimelineTask.withTaskId(int taskId, {TimelineTask parent}) + : _parent = parent, + _taskId = taskId { ArgumentError.checkNotNull(taskId, 'taskId'); } @@ -197,7 +209,10 @@ class TimelineTask { ArgumentError.checkNotNull(name, 'name'); var block = new _AsyncBlock._(name, _taskId); _stack.add(block); - block._start(arguments); + block._start({ + if (arguments != null) ...arguments, + if (_parent != null) 'parentId': _parent._taskId, + }); } /// Emit an instant event for this task. @@ -239,6 +254,7 @@ class TimelineTask { return r; } + final TimelineTask _parent; final int _taskId; final List<_AsyncBlock> _stack = []; }