mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:31:58 +00:00
[ DDS ] Move package:dds/vm_service_extensions.dart into package:dds_service_extensions
Reduces dependency complexity for tools which don't need the full contents of package:dds Change-Id: Ib9c5ce93eea72421f56114ab8a8efaa0dca6ae02 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/225240 Reviewed-by: Kenzie (Schmoll) Davisson <kenzieschmoll@google.com>
This commit is contained in:
parent
8ee071f535
commit
9f5ef6d5bc
|
@ -258,6 +258,12 @@
|
||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "2.13"
|
"languageVersion": "2.13"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "dds_service_extensions",
|
||||||
|
"rootUri": "../pkg/dds_service_extensions",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.13"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "dev_compiler",
|
"name": "dev_compiler",
|
||||||
"rootUri": "../pkg/dev_compiler",
|
"rootUri": "../pkg/dev_compiler",
|
||||||
|
|
|
@ -38,6 +38,7 @@ dart_style:third_party/pkg_tested/dart_style/lib
|
||||||
dartdev:pkg/dartdev/lib
|
dartdev:pkg/dartdev/lib
|
||||||
dartdoc:third_party/pkg/dartdoc/lib
|
dartdoc:third_party/pkg/dartdoc/lib
|
||||||
dds:pkg/dds/lib
|
dds:pkg/dds/lib
|
||||||
|
dds_service_extensions:pkg/dds_service_extensions/lib
|
||||||
dev_compiler:pkg/dev_compiler/lib
|
dev_compiler:pkg/dev_compiler/lib
|
||||||
devtools_server:third_party/devtools/devtools_server/lib
|
devtools_server:third_party/devtools/devtools_server/lib
|
||||||
devtools_shared:third_party/devtools/devtools_shared/lib
|
devtools_shared:third_party/devtools/devtools_shared/lib
|
||||||
|
|
|
@ -2,275 +2,7 @@
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:async';
|
@Deprecated("Use 'package:dds_service_extensions' instead")
|
||||||
import 'dart:collection';
|
library vm_service_extensions;
|
||||||
|
|
||||||
import 'package:async/async.dart';
|
export 'package:dds_service_extensions/dds_service_extensions.dart';
|
||||||
import 'package:pedantic/pedantic.dart';
|
|
||||||
import 'package:vm_service/src/vm_service.dart';
|
|
||||||
|
|
||||||
extension DdsExtension on VmService {
|
|
||||||
static bool _factoriesRegistered = false;
|
|
||||||
static Version? _ddsVersion;
|
|
||||||
|
|
||||||
/// The [getDartDevelopmentServiceVersion] RPC is used to determine what version of
|
|
||||||
/// the Dart Development Service Protocol is served by a DDS instance.
|
|
||||||
///
|
|
||||||
/// The result of this call is cached for subsequent invocations.
|
|
||||||
Future<Version> getDartDevelopmentServiceVersion() async {
|
|
||||||
if (_ddsVersion == null) {
|
|
||||||
_ddsVersion = await _callHelper<Version>(
|
|
||||||
'getDartDevelopmentServiceVersion',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return _ddsVersion!;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The [getCachedCpuSamples] RPC is used to retrieve a cache of CPU samples
|
|
||||||
/// collected under a [UserTag] with name `userTag`.
|
|
||||||
Future<CachedCpuSamples> getCachedCpuSamples(
|
|
||||||
String isolateId, String userTag) async {
|
|
||||||
if (!(await _versionCheck(1, 3))) {
|
|
||||||
throw UnimplementedError('getCachedCpuSamples requires DDS version 1.3');
|
|
||||||
}
|
|
||||||
return _callHelper<CachedCpuSamples>('getCachedCpuSamples', args: {
|
|
||||||
'isolateId': isolateId,
|
|
||||||
'userTag': userTag,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The [getAvailableCachedCpuSamples] RPC is used to determine which caches of CPU samples
|
|
||||||
/// are available. Caches are associated with individual [UserTag] names and are specified
|
|
||||||
/// when DDS is started via the `cachedUserTags` parameter.
|
|
||||||
Future<AvailableCachedCpuSamples> getAvailableCachedCpuSamples() async {
|
|
||||||
if (!(await _versionCheck(1, 3))) {
|
|
||||||
throw UnimplementedError(
|
|
||||||
'getAvailableCachedCpuSamples requires DDS version 1.3',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return _callHelper<AvailableCachedCpuSamples>(
|
|
||||||
'getAvailableCachedCpuSamples',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieve the event history for `stream`.
|
|
||||||
///
|
|
||||||
/// If `stream` does not have event history collected, a parameter error is
|
|
||||||
/// returned.
|
|
||||||
Future<StreamHistory> getStreamHistory(String stream) async {
|
|
||||||
if (!(await _versionCheck(1, 2))) {
|
|
||||||
throw UnimplementedError('getStreamHistory requires DDS version 1.2');
|
|
||||||
}
|
|
||||||
return _callHelper<StreamHistory>('getStreamHistory', args: {
|
|
||||||
'stream': stream,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the stream for a given stream id which includes historical
|
|
||||||
/// events.
|
|
||||||
///
|
|
||||||
/// If `stream` does not have event history collected, a parameter error is
|
|
||||||
/// sent over the returned [Stream].
|
|
||||||
Stream<Event> onEventWithHistory(String stream) {
|
|
||||||
late StreamController<Event> controller;
|
|
||||||
late StreamQueue<Event> streamEvents;
|
|
||||||
|
|
||||||
controller = StreamController<Event>(onListen: () async {
|
|
||||||
streamEvents = StreamQueue<Event>(onEvent(stream));
|
|
||||||
final history = (await getStreamHistory(stream)).history;
|
|
||||||
Event? firstStreamEvent;
|
|
||||||
unawaited(streamEvents.peek.then((e) {
|
|
||||||
firstStreamEvent = e;
|
|
||||||
}));
|
|
||||||
for (final event in history) {
|
|
||||||
if (firstStreamEvent != null &&
|
|
||||||
event.timestamp! > firstStreamEvent!.timestamp!) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
controller.sink.add(event);
|
|
||||||
}
|
|
||||||
unawaited(controller.sink.addStream(streamEvents.rest));
|
|
||||||
}, onCancel: () {
|
|
||||||
try {
|
|
||||||
streamEvents.cancel();
|
|
||||||
} on StateError {
|
|
||||||
// Underlying stream may have already been cancelled.
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return controller.stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new [Stream<Event>] of `Logging` events which outputs
|
|
||||||
/// historical events before streaming real-time events.
|
|
||||||
///
|
|
||||||
/// Note: unlike [onLoggingEvent], the returned stream is a single
|
|
||||||
/// subscription stream and a new stream is created for each invocation of
|
|
||||||
/// this getter.
|
|
||||||
Stream<Event> get onLoggingEventWithHistory => onEventWithHistory('Logging');
|
|
||||||
|
|
||||||
/// Returns a new [Stream<Event>] of `Stdout` events which outputs
|
|
||||||
/// historical events before streaming real-time events.
|
|
||||||
///
|
|
||||||
/// Note: unlike [onStdoutEvent], the returned stream is a single
|
|
||||||
/// subscription stream and a new stream is created for each invocation of
|
|
||||||
/// this getter.
|
|
||||||
Stream<Event> get onStdoutEventWithHistory => onEventWithHistory('Stdout');
|
|
||||||
|
|
||||||
/// Returns a new [Stream<Event>] of `Stderr` events which outputs
|
|
||||||
/// historical events before streaming real-time events.
|
|
||||||
///
|
|
||||||
/// Note: unlike [onStderrEvent], the returned stream is a single
|
|
||||||
/// subscription stream and a new stream is created for each invocation of
|
|
||||||
/// this getter.
|
|
||||||
Stream<Event> get onStderrEventWithHistory => onEventWithHistory('Stderr');
|
|
||||||
|
|
||||||
/// Returns a new [Stream<Event>] of `Extension` events which outputs
|
|
||||||
/// historical events before streaming real-time events.
|
|
||||||
///
|
|
||||||
/// Note: unlike [onExtensionEvent], the returned stream is a single
|
|
||||||
/// subscription stream and a new stream is created for each invocation of
|
|
||||||
/// this getter.
|
|
||||||
Stream<Event> get onExtensionEventWithHistory =>
|
|
||||||
onEventWithHistory('Extension');
|
|
||||||
|
|
||||||
Future<bool> _versionCheck(int major, int minor) async {
|
|
||||||
if (_ddsVersion == null) {
|
|
||||||
_ddsVersion = await getDartDevelopmentServiceVersion();
|
|
||||||
}
|
|
||||||
return ((_ddsVersion!.major == major && _ddsVersion!.minor! >= minor) ||
|
|
||||||
(_ddsVersion!.major! > major));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<T> _callHelper<T>(String method,
|
|
||||||
{String? isolateId, Map args = const {}}) {
|
|
||||||
if (!_factoriesRegistered) {
|
|
||||||
_registerFactories();
|
|
||||||
}
|
|
||||||
return callMethod(
|
|
||||||
method,
|
|
||||||
args: {
|
|
||||||
if (isolateId != null) 'isolateId': isolateId,
|
|
||||||
...args,
|
|
||||||
},
|
|
||||||
).then((e) => e as T);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _registerFactories() {
|
|
||||||
addTypeFactory('StreamHistory', StreamHistory.parse);
|
|
||||||
addTypeFactory(
|
|
||||||
'AvailableCachedCpuSamples',
|
|
||||||
AvailableCachedCpuSamples.parse,
|
|
||||||
);
|
|
||||||
addTypeFactory('CachedCpuSamples', CachedCpuSamples.parse);
|
|
||||||
_factoriesRegistered = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A collection of historical [Event]s from some stream.
|
|
||||||
class StreamHistory extends Response {
|
|
||||||
static StreamHistory? parse(Map<String, dynamic>? json) =>
|
|
||||||
json == null ? null : StreamHistory._fromJson(json);
|
|
||||||
|
|
||||||
StreamHistory({required List<Event> history}) : _history = history;
|
|
||||||
|
|
||||||
StreamHistory._fromJson(Map<String, dynamic> json)
|
|
||||||
: _history = json['history']
|
|
||||||
.map(
|
|
||||||
(e) => Event.parse(e),
|
|
||||||
)
|
|
||||||
.toList()
|
|
||||||
.cast<Event>() {
|
|
||||||
this.json = json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get type => 'StreamHistory';
|
|
||||||
|
|
||||||
/// Historical [Event]s for a stream.
|
|
||||||
List<Event> get history => UnmodifiableListView(_history);
|
|
||||||
final List<Event> _history;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An extension of [CpuSamples] which represents a set of cached samples,
|
|
||||||
/// associated with a particular [UserTag] name.
|
|
||||||
class CachedCpuSamples extends CpuSamples {
|
|
||||||
static CachedCpuSamples? parse(Map<String, dynamic>? json) =>
|
|
||||||
json == null ? null : CachedCpuSamples._fromJson(json);
|
|
||||||
|
|
||||||
CachedCpuSamples({
|
|
||||||
required this.userTag,
|
|
||||||
this.truncated,
|
|
||||||
required int? samplePeriod,
|
|
||||||
required int? maxStackDepth,
|
|
||||||
required int? sampleCount,
|
|
||||||
required int? timeSpan,
|
|
||||||
required int? timeOriginMicros,
|
|
||||||
required int? timeExtentMicros,
|
|
||||||
required int? pid,
|
|
||||||
required List<ProfileFunction>? functions,
|
|
||||||
required List<CpuSample>? samples,
|
|
||||||
}) : super(
|
|
||||||
samplePeriod: samplePeriod,
|
|
||||||
maxStackDepth: maxStackDepth,
|
|
||||||
sampleCount: sampleCount,
|
|
||||||
timeSpan: timeSpan,
|
|
||||||
timeOriginMicros: timeOriginMicros,
|
|
||||||
timeExtentMicros: timeExtentMicros,
|
|
||||||
pid: pid,
|
|
||||||
functions: functions,
|
|
||||||
samples: samples,
|
|
||||||
);
|
|
||||||
|
|
||||||
CachedCpuSamples._fromJson(Map<String, dynamic> json)
|
|
||||||
: userTag = json['userTag']!,
|
|
||||||
truncated = json['truncated'],
|
|
||||||
super(
|
|
||||||
samplePeriod: json['samplePeriod'] ?? -1,
|
|
||||||
maxStackDepth: json['maxStackDepth'] ?? -1,
|
|
||||||
sampleCount: json['sampleCount'] ?? -1,
|
|
||||||
timeSpan: json['timeSpan'] ?? -1,
|
|
||||||
timeOriginMicros: json['timeOriginMicros'] ?? -1,
|
|
||||||
timeExtentMicros: json['timeExtentMicros'] ?? -1,
|
|
||||||
pid: json['pid'] ?? -1,
|
|
||||||
functions: List<ProfileFunction>.from(
|
|
||||||
createServiceObject(json['functions'], const ['ProfileFunction'])
|
|
||||||
as List? ??
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
samples: List<CpuSample>.from(
|
|
||||||
createServiceObject(json['samples'], const ['CpuSample'])
|
|
||||||
as List? ??
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get type => 'CachedCpuSamples';
|
|
||||||
|
|
||||||
/// The name of the [UserTag] associated with this cache of [CpuSamples].
|
|
||||||
final String userTag;
|
|
||||||
|
|
||||||
/// Provided if the CPU sample cache has filled and older samples have been
|
|
||||||
/// dropped.
|
|
||||||
final bool? truncated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A collection of [UserTag] names associated with caches of CPU samples.
|
|
||||||
class AvailableCachedCpuSamples extends Response {
|
|
||||||
static AvailableCachedCpuSamples? parse(Map<String, dynamic>? json) =>
|
|
||||||
json == null ? null : AvailableCachedCpuSamples._fromJson(json);
|
|
||||||
|
|
||||||
AvailableCachedCpuSamples({
|
|
||||||
required this.cacheNames,
|
|
||||||
});
|
|
||||||
|
|
||||||
AvailableCachedCpuSamples._fromJson(Map<String, dynamic> json)
|
|
||||||
: cacheNames = List<String>.from(json['cacheNames']);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get type => 'AvailableCachedUserTagCpuSamples';
|
|
||||||
|
|
||||||
/// A [List] of [UserTag] names associated with CPU sample caches.
|
|
||||||
final List<String> cacheNames;
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ environment:
|
||||||
dependencies:
|
dependencies:
|
||||||
async: ^2.4.1
|
async: ^2.4.1
|
||||||
collection: ^1.15.0
|
collection: ^1.15.0
|
||||||
|
dds_service_extensions: ^1.3.0
|
||||||
devtools_shared: ^2.3.0
|
devtools_shared: ^2.3.0
|
||||||
json_rpc_2: ^3.0.0
|
json_rpc_2: ^3.0.0
|
||||||
meta: ^1.1.8
|
meta: ^1.1.8
|
||||||
|
|
|
@ -7,7 +7,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:dds/dds.dart';
|
import 'package:dds/dds.dart';
|
||||||
import 'package:dds/src/utils/mutex.dart';
|
import 'package:dds/src/utils/mutex.dart';
|
||||||
import 'package:dds/vm_service_extensions.dart';
|
import 'package:dds_service_extensions/dds_service_extensions.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:vm_service/vm_service.dart';
|
import 'package:vm_service/vm_service.dart';
|
||||||
import 'package:vm_service/vm_service_io.dart';
|
import 'package:vm_service/vm_service_io.dart';
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dds/dds.dart';
|
import 'package:dds/dds.dart';
|
||||||
import 'package:dds/vm_service_extensions.dart';
|
import 'package:dds_service_extensions/dds_service_extensions.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:vm_service/vm_service_io.dart';
|
import 'package:vm_service/vm_service_io.dart';
|
||||||
import 'common/test_helper.dart';
|
import 'common/test_helper.dart';
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dds/dds.dart';
|
import 'package:dds/dds.dart';
|
||||||
import 'package:dds/vm_service_extensions.dart';
|
import 'package:dds_service_extensions/dds_service_extensions.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:vm_service/vm_service_io.dart';
|
import 'package:vm_service/vm_service_io.dart';
|
||||||
import 'common/test_helper.dart';
|
import 'common/test_helper.dart';
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dds/dds.dart';
|
import 'package:dds/dds.dart';
|
||||||
import 'package:dds/vm_service_extensions.dart';
|
import 'package:dds_service_extensions/dds_service_extensions.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:vm_service/vm_service_io.dart';
|
import 'package:vm_service/vm_service_io.dart';
|
||||||
import 'common/test_helper.dart';
|
import 'common/test_helper.dart';
|
||||||
|
|
10
pkg/dds_service_extensions/.gitignore
vendored
Normal file
10
pkg/dds_service_extensions/.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Files and directories created by pub.
|
||||||
|
.dart_tool/
|
||||||
|
.packages
|
||||||
|
|
||||||
|
# Conventional directory for build outputs.
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Omit committing pubspec.lock for library packages; see
|
||||||
|
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||||
|
pubspec.lock
|
3
pkg/dds_service_extensions/CHANGELOG.md
Normal file
3
pkg/dds_service_extensions/CHANGELOG.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
## 1.3.0
|
||||||
|
|
||||||
|
- Moved `package:dds/vm_service_extensions.dart` into a standalone package.
|
3
pkg/dds_service_extensions/README.md
Normal file
3
pkg/dds_service_extensions/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
A package used to expand the `package:vm_service` interface with support for RPCs added in the [Dart Developer Service (DDS) protocol][dds-protocol].
|
||||||
|
|
||||||
|
[dds-protocol]: https://github.com/dart-lang/sdk/blob/main/pkg/dds/dds_protocol.md
|
30
pkg/dds_service_extensions/analysis_options.yaml
Normal file
30
pkg/dds_service_extensions/analysis_options.yaml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# This file configures the static analysis results for your project (errors,
|
||||||
|
# warnings, and lints).
|
||||||
|
#
|
||||||
|
# This enables the 'recommended' set of lints from `package:lints`.
|
||||||
|
# This set helps identify many issues that may lead to problems when running
|
||||||
|
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
||||||
|
# style and format.
|
||||||
|
#
|
||||||
|
# If you want a smaller set of lints you can change this to specify
|
||||||
|
# 'package:lints/core.yaml'. These are just the most critical lints
|
||||||
|
# (the recommended set includes the core lints).
|
||||||
|
# The core lints are also what is used by pub.dev for scoring packages.
|
||||||
|
|
||||||
|
include: package:lints/recommended.yaml
|
||||||
|
|
||||||
|
# Uncomment the following section to specify additional rules.
|
||||||
|
|
||||||
|
# linter:
|
||||||
|
# rules:
|
||||||
|
# - camel_case_types
|
||||||
|
|
||||||
|
# analyzer:
|
||||||
|
# exclude:
|
||||||
|
# - path/to/excluded/files/**
|
||||||
|
|
||||||
|
# For more information about the core and recommended set of lints, see
|
||||||
|
# https://dart.dev/go/core-lints
|
||||||
|
|
||||||
|
# For additional information about configuring this file, see
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
272
pkg/dds_service_extensions/lib/dds_service_extensions.dart
Normal file
272
pkg/dds_service_extensions/lib/dds_service_extensions.dart
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:async/async.dart';
|
||||||
|
// ignore: implementation_imports
|
||||||
|
import 'package:vm_service/src/vm_service.dart';
|
||||||
|
|
||||||
|
extension DdsExtension on VmService {
|
||||||
|
static bool _factoriesRegistered = false;
|
||||||
|
static Version? _ddsVersion;
|
||||||
|
|
||||||
|
/// The [getDartDevelopmentServiceVersion] RPC is used to determine what version of
|
||||||
|
/// the Dart Development Service Protocol is served by a DDS instance.
|
||||||
|
///
|
||||||
|
/// The result of this call is cached for subsequent invocations.
|
||||||
|
Future<Version> getDartDevelopmentServiceVersion() async {
|
||||||
|
_ddsVersion ??= await _callHelper<Version>(
|
||||||
|
'getDartDevelopmentServiceVersion',
|
||||||
|
);
|
||||||
|
return _ddsVersion!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The [getCachedCpuSamples] RPC is used to retrieve a cache of CPU samples
|
||||||
|
/// collected under a [UserTag] with name `userTag`.
|
||||||
|
Future<CachedCpuSamples> getCachedCpuSamples(
|
||||||
|
String isolateId, String userTag) async {
|
||||||
|
if (!(await _versionCheck(1, 3))) {
|
||||||
|
throw UnimplementedError('getCachedCpuSamples requires DDS version 1.3');
|
||||||
|
}
|
||||||
|
return _callHelper<CachedCpuSamples>('getCachedCpuSamples', args: {
|
||||||
|
'isolateId': isolateId,
|
||||||
|
'userTag': userTag,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The [getAvailableCachedCpuSamples] RPC is used to determine which caches of CPU samples
|
||||||
|
/// are available. Caches are associated with individual [UserTag] names and are specified
|
||||||
|
/// when DDS is started via the `cachedUserTags` parameter.
|
||||||
|
Future<AvailableCachedCpuSamples> getAvailableCachedCpuSamples() async {
|
||||||
|
if (!(await _versionCheck(1, 3))) {
|
||||||
|
throw UnimplementedError(
|
||||||
|
'getAvailableCachedCpuSamples requires DDS version 1.3',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _callHelper<AvailableCachedCpuSamples>(
|
||||||
|
'getAvailableCachedCpuSamples',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the event history for `stream`.
|
||||||
|
///
|
||||||
|
/// If `stream` does not have event history collected, a parameter error is
|
||||||
|
/// returned.
|
||||||
|
Future<StreamHistory> getStreamHistory(String stream) async {
|
||||||
|
if (!(await _versionCheck(1, 2))) {
|
||||||
|
throw UnimplementedError('getStreamHistory requires DDS version 1.2');
|
||||||
|
}
|
||||||
|
return _callHelper<StreamHistory>('getStreamHistory', args: {
|
||||||
|
'stream': stream,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the stream for a given stream id which includes historical
|
||||||
|
/// events.
|
||||||
|
///
|
||||||
|
/// If `stream` does not have event history collected, a parameter error is
|
||||||
|
/// sent over the returned [Stream].
|
||||||
|
Stream<Event> onEventWithHistory(String stream) {
|
||||||
|
late StreamController<Event> controller;
|
||||||
|
late StreamQueue<Event> streamEvents;
|
||||||
|
|
||||||
|
controller = StreamController<Event>(onListen: () async {
|
||||||
|
streamEvents = StreamQueue<Event>(onEvent(stream));
|
||||||
|
final history = (await getStreamHistory(stream)).history;
|
||||||
|
Event? firstStreamEvent;
|
||||||
|
unawaited(streamEvents.peek.then((e) {
|
||||||
|
firstStreamEvent = e;
|
||||||
|
}));
|
||||||
|
for (final event in history) {
|
||||||
|
if (firstStreamEvent != null &&
|
||||||
|
event.timestamp! > firstStreamEvent!.timestamp!) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
controller.sink.add(event);
|
||||||
|
}
|
||||||
|
unawaited(controller.sink.addStream(streamEvents.rest));
|
||||||
|
}, onCancel: () {
|
||||||
|
try {
|
||||||
|
streamEvents.cancel();
|
||||||
|
} on StateError {
|
||||||
|
// Underlying stream may have already been cancelled.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return controller.stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [Stream<Event>] of `Logging` events which outputs
|
||||||
|
/// historical events before streaming real-time events.
|
||||||
|
///
|
||||||
|
/// Note: unlike [onLoggingEvent], the returned stream is a single
|
||||||
|
/// subscription stream and a new stream is created for each invocation of
|
||||||
|
/// this getter.
|
||||||
|
Stream<Event> get onLoggingEventWithHistory => onEventWithHistory('Logging');
|
||||||
|
|
||||||
|
/// Returns a new [Stream<Event>] of `Stdout` events which outputs
|
||||||
|
/// historical events before streaming real-time events.
|
||||||
|
///
|
||||||
|
/// Note: unlike [onStdoutEvent], the returned stream is a single
|
||||||
|
/// subscription stream and a new stream is created for each invocation of
|
||||||
|
/// this getter.
|
||||||
|
Stream<Event> get onStdoutEventWithHistory => onEventWithHistory('Stdout');
|
||||||
|
|
||||||
|
/// Returns a new [Stream<Event>] of `Stderr` events which outputs
|
||||||
|
/// historical events before streaming real-time events.
|
||||||
|
///
|
||||||
|
/// Note: unlike [onStderrEvent], the returned stream is a single
|
||||||
|
/// subscription stream and a new stream is created for each invocation of
|
||||||
|
/// this getter.
|
||||||
|
Stream<Event> get onStderrEventWithHistory => onEventWithHistory('Stderr');
|
||||||
|
|
||||||
|
/// Returns a new [Stream<Event>] of `Extension` events which outputs
|
||||||
|
/// historical events before streaming real-time events.
|
||||||
|
///
|
||||||
|
/// Note: unlike [onExtensionEvent], the returned stream is a single
|
||||||
|
/// subscription stream and a new stream is created for each invocation of
|
||||||
|
/// this getter.
|
||||||
|
Stream<Event> get onExtensionEventWithHistory =>
|
||||||
|
onEventWithHistory('Extension');
|
||||||
|
|
||||||
|
Future<bool> _versionCheck(int major, int minor) async {
|
||||||
|
_ddsVersion ??= await getDartDevelopmentServiceVersion();
|
||||||
|
return ((_ddsVersion!.major == major && _ddsVersion!.minor! >= minor) ||
|
||||||
|
(_ddsVersion!.major! > major));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<T> _callHelper<T>(String method,
|
||||||
|
{String? isolateId, Map args = const {}}) {
|
||||||
|
if (!_factoriesRegistered) {
|
||||||
|
_registerFactories();
|
||||||
|
}
|
||||||
|
return callMethod(
|
||||||
|
method,
|
||||||
|
args: {
|
||||||
|
if (isolateId != null) 'isolateId': isolateId,
|
||||||
|
...args,
|
||||||
|
},
|
||||||
|
).then((e) => e as T);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _registerFactories() {
|
||||||
|
addTypeFactory('StreamHistory', StreamHistory.parse);
|
||||||
|
addTypeFactory(
|
||||||
|
'AvailableCachedCpuSamples',
|
||||||
|
AvailableCachedCpuSamples.parse,
|
||||||
|
);
|
||||||
|
addTypeFactory('CachedCpuSamples', CachedCpuSamples.parse);
|
||||||
|
_factoriesRegistered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A collection of historical [Event]s from some stream.
|
||||||
|
class StreamHistory extends Response {
|
||||||
|
static StreamHistory? parse(Map<String, dynamic>? json) =>
|
||||||
|
json == null ? null : StreamHistory._fromJson(json);
|
||||||
|
|
||||||
|
StreamHistory({required List<Event> history}) : _history = history;
|
||||||
|
|
||||||
|
StreamHistory._fromJson(Map<String, dynamic> json)
|
||||||
|
: _history = json['history']
|
||||||
|
.map(
|
||||||
|
(e) => Event.parse(e),
|
||||||
|
)
|
||||||
|
.toList()
|
||||||
|
.cast<Event>() {
|
||||||
|
this.json = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get type => 'StreamHistory';
|
||||||
|
|
||||||
|
/// Historical [Event]s for a stream.
|
||||||
|
List<Event> get history => UnmodifiableListView(_history);
|
||||||
|
final List<Event> _history;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An extension of [CpuSamples] which represents a set of cached samples,
|
||||||
|
/// associated with a particular [UserTag] name.
|
||||||
|
class CachedCpuSamples extends CpuSamples {
|
||||||
|
static CachedCpuSamples? parse(Map<String, dynamic>? json) =>
|
||||||
|
json == null ? null : CachedCpuSamples._fromJson(json);
|
||||||
|
|
||||||
|
CachedCpuSamples({
|
||||||
|
required this.userTag,
|
||||||
|
this.truncated,
|
||||||
|
required int? samplePeriod,
|
||||||
|
required int? maxStackDepth,
|
||||||
|
required int? sampleCount,
|
||||||
|
required int? timeSpan,
|
||||||
|
required int? timeOriginMicros,
|
||||||
|
required int? timeExtentMicros,
|
||||||
|
required int? pid,
|
||||||
|
required List<ProfileFunction>? functions,
|
||||||
|
required List<CpuSample>? samples,
|
||||||
|
}) : super(
|
||||||
|
samplePeriod: samplePeriod,
|
||||||
|
maxStackDepth: maxStackDepth,
|
||||||
|
sampleCount: sampleCount,
|
||||||
|
timeSpan: timeSpan,
|
||||||
|
timeOriginMicros: timeOriginMicros,
|
||||||
|
timeExtentMicros: timeExtentMicros,
|
||||||
|
pid: pid,
|
||||||
|
functions: functions,
|
||||||
|
samples: samples,
|
||||||
|
);
|
||||||
|
|
||||||
|
CachedCpuSamples._fromJson(Map<String, dynamic> json)
|
||||||
|
: userTag = json['userTag']!,
|
||||||
|
truncated = json['truncated'],
|
||||||
|
super(
|
||||||
|
samplePeriod: json['samplePeriod'] ?? -1,
|
||||||
|
maxStackDepth: json['maxStackDepth'] ?? -1,
|
||||||
|
sampleCount: json['sampleCount'] ?? -1,
|
||||||
|
timeSpan: json['timeSpan'] ?? -1,
|
||||||
|
timeOriginMicros: json['timeOriginMicros'] ?? -1,
|
||||||
|
timeExtentMicros: json['timeExtentMicros'] ?? -1,
|
||||||
|
pid: json['pid'] ?? -1,
|
||||||
|
functions: List<ProfileFunction>.from(
|
||||||
|
createServiceObject(json['functions'], const ['ProfileFunction'])
|
||||||
|
as List? ??
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
samples: List<CpuSample>.from(
|
||||||
|
createServiceObject(json['samples'], const ['CpuSample'])
|
||||||
|
as List? ??
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get type => 'CachedCpuSamples';
|
||||||
|
|
||||||
|
/// The name of the [UserTag] associated with this cache of [CpuSamples].
|
||||||
|
final String userTag;
|
||||||
|
|
||||||
|
/// Provided if the CPU sample cache has filled and older samples have been
|
||||||
|
/// dropped.
|
||||||
|
final bool? truncated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A collection of [UserTag] names associated with caches of CPU samples.
|
||||||
|
class AvailableCachedCpuSamples extends Response {
|
||||||
|
static AvailableCachedCpuSamples? parse(Map<String, dynamic>? json) =>
|
||||||
|
json == null ? null : AvailableCachedCpuSamples._fromJson(json);
|
||||||
|
|
||||||
|
AvailableCachedCpuSamples({
|
||||||
|
required this.cacheNames,
|
||||||
|
});
|
||||||
|
|
||||||
|
AvailableCachedCpuSamples._fromJson(Map<String, dynamic> json)
|
||||||
|
: cacheNames = List<String>.from(json['cacheNames']);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get type => 'AvailableCachedUserTagCpuSamples';
|
||||||
|
|
||||||
|
/// A [List] of [UserTag] names associated with CPU sample caches.
|
||||||
|
final List<String> cacheNames;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
// TODO: Put public facing types in this file.
|
||||||
|
|
||||||
|
/// Checks if you are awesome. Spoiler: you are.
|
||||||
|
class Awesome {
|
||||||
|
bool get isAwesome => true;
|
||||||
|
}
|
18
pkg/dds_service_extensions/pubspec.yaml
Normal file
18
pkg/dds_service_extensions/pubspec.yaml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
name: dds_service_extensions
|
||||||
|
description: >-
|
||||||
|
Extension methods for `package:vm_service`, used to make requests a
|
||||||
|
Dart Development Service (DDS) instance.
|
||||||
|
|
||||||
|
version: 1.3.0
|
||||||
|
|
||||||
|
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds_service_extensions
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: '>=2.13.0 <3.0.0'
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
async: ^2.4.1
|
||||||
|
vm_service: ^8.1.0
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
lints: ^1.0.0
|
1
pkg/dds_service_extensions/test/README
Normal file
1
pkg/dds_service_extensions/test/README
Normal file
|
@ -0,0 +1 @@
|
||||||
|
NOTE: Tests for this package can be found in `package:dds`.
|
|
@ -3442,6 +3442,15 @@
|
||||||
"pkg/dds"
|
"pkg/dds"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "analyze pkg/dds_service_extensions",
|
||||||
|
"script": "out/ReleaseX64/dart-sdk/bin/dart",
|
||||||
|
"arguments": [
|
||||||
|
"analyze",
|
||||||
|
"--fatal-infos",
|
||||||
|
"pkg/dds_service_extensions"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "analyze runtime/observatory",
|
"name": "analyze runtime/observatory",
|
||||||
"script": "out/ReleaseX64/dart-sdk/bin/dart",
|
"script": "out/ReleaseX64/dart-sdk/bin/dart",
|
||||||
|
|
Loading…
Reference in a new issue