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 = []; }