[dds] Support logging VM Service traffic to the client from DAP
Change-Id: Id9f6b2158dcf1603468b989ed2f900b390b9b259
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/209546
Reviewed-by: Ben Konyi <bkonyi@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
diff --git a/pkg/dds/lib/src/dap/adapters/dart.dart b/pkg/dds/lib/src/dap/adapters/dart.dart
index e61c8c4..27ad157 100644
--- a/pkg/dds/lib/src/dap/adapters/dart.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart.dart
@@ -176,6 +176,8 @@
/// VM Service closing).
bool _hasSentTerminatedEvent = false;
+ late final sendLogsToClient = args.sendLogsToClient ?? false;
+
DartDebugAdapter(
ByteStreamServerChannel channel, {
this.ipv6 = false,
@@ -305,8 +307,7 @@
logger?.call('Connecting to debugger at $uri');
sendOutput('console', 'Connecting to VM Service at $uri\n');
- final vmService =
- await _vmServiceConnectUri(uri.toString(), logger: logger);
+ final vmService = await _vmServiceConnectUri(uri.toString());
logger?.call('Connected to debugger at $uri!');
// TODO(dantup): VS Code currently depends on a custom dart.debuggerUris
@@ -1313,6 +1314,13 @@
}
}
+ void _logTraffic(String data) {
+ logger?.call(data);
+ if (sendLogsToClient) {
+ sendEvent(RawEventBody(data), eventType: 'dart.log');
+ }
+ }
+
/// Performs some setup that is common to both [launchRequest] and
/// [attachRequest].
Future<void> _prepareForLaunchOrAttach() async {
@@ -1352,17 +1360,15 @@
/// A wrapper around the same name function from package:vm_service that
/// allows logging all traffic over the VM Service.
- Future<vm.VmService> _vmServiceConnectUri(
- String wsUri, {
- Logger? logger,
- }) async {
+ Future<vm.VmService> _vmServiceConnectUri(String wsUri) async {
final socket = await WebSocket.connect(wsUri);
final controller = StreamController();
final streamClosedCompleter = Completer();
+ final logger = this.logger;
socket.listen(
(data) {
- logger?.call('<== [VM] $data');
+ _logTraffic('<== [VM] $data');
controller.add(data);
},
onDone: () => streamClosedCompleter.complete(),
@@ -1372,6 +1378,7 @@
controller.stream,
(String message) {
logger?.call('==> [VM] $message');
+ _logTraffic('==> [VM] $message');
socket.add(message);
},
log: logger != null ? VmServiceLogger(logger) : null,
diff --git a/pkg/dds/lib/src/dap/base_debug_adapter.dart b/pkg/dds/lib/src/dap/base_debug_adapter.dart
index 6b15fac..1071fee 100644
--- a/pkg/dds/lib/src/dap/base_debug_adapter.dart
+++ b/pkg/dds/lib/src/dap/base_debug_adapter.dart
@@ -167,10 +167,10 @@
/// Sends an event, lookup up the event type based on the runtimeType of
/// [body].
- void sendEvent(EventBody body) {
+ void sendEvent(EventBody body, {String? eventType}) {
final event = Event(
seq: _sequence++,
- event: eventTypes[body.runtimeType]!,
+ event: eventType ?? eventTypes[body.runtimeType]!,
body: body,
);
_channel.sendEvent(event);
diff --git a/pkg/dds/lib/src/dap/protocol_common.dart b/pkg/dds/lib/src/dap/protocol_common.dart
index f9c09f4..9a20311 100644
--- a/pkg/dds/lib/src/dap/protocol_common.dart
+++ b/pkg/dds/lib/src/dap/protocol_common.dart
@@ -2,12 +2,35 @@
// 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:convert';
+
/// A base class for (spec-generated) classes that represent the `body` of a an
/// event.
abstract class EventBody {
static bool canParse(Object? obj) => obj is Map<String, Object?>?;
}
+/// A generic event body class that just supplies an object directly.
+///
+/// Used to support custom events sent by the debug adapter such as 'dart.log'.
+///
+/// The supplied [body] must be convertable to JSON.
+class RawEventBody extends EventBody {
+ final Object body;
+
+ RawEventBody(this.body)
+ : assert(() {
+ try {
+ jsonEncode(body);
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }(), 'body should be JSON encodable');
+
+ Object toJson() => body;
+}
+
/// A generic arguments class that just supplies the arguments map directly.
///
/// Used to support custom requests that may be provided by other implementing
diff --git a/pkg/dds/test/dap/integration/test_server.dart b/pkg/dds/test/dap/integration/test_server.dart
index ffaabf2..3e4cb72 100644
--- a/pkg/dds/test/dap/integration/test_server.dart
+++ b/pkg/dds/test/dap/integration/test_server.dart
@@ -53,7 +53,6 @@
}) async {
return InProcessDapTestServer._([
...?additionalArgs,
- if (logger != null) '--verbose',
]);
}
}
@@ -107,12 +106,7 @@
final _process = await Process.start(
Platform.resolvedExecutable,
- [
- dapServerScript,
- 'dap',
- ...?additionalArgs,
- if (logger != null) '--verbose'
- ],
+ [dapServerScript, 'dap', ...?additionalArgs],
);
return OutOfProcessDapTestServer._(_process, logger);
diff --git a/pkg/dds/test/dap/integration/test_support.dart b/pkg/dds/test/dap/integration/test_support.dart
index 4f8fac1..9fd5a88 100644
--- a/pkg/dds/test/dap/integration/test_support.dart
+++ b/pkg/dds/test/dap/integration/test_support.dart
@@ -23,6 +23,13 @@
/// simplified in VS Code by using a launch config with custom CodeLens links).
final useInProcessDap = Platform.environment['DAP_TEST_INTERNAL'] == 'true';
+/// Whether to print all protocol traffic to stdout while running tests.
+///
+/// This is useful for debugging locally or on the bots and will include both
+/// DAP traffic (between the test DAP client and the DAP server) and the VM
+/// Service traffic (wrapped in a custom 'dart.log' event).
+final verboseLogging = Platform.environment['DAP_TEST_VERBOSE'] == 'true';
+
/// A [RegExp] that matches the `path` part of a VM Service URI that contains
/// an authentication token.
final vmServiceAuthCodePathPattern = RegExp(r'^/[\w_\-=]{5,15}/ws$');
@@ -141,8 +148,11 @@
static Future<DapTestSession> setUp({List<String>? additionalArgs}) async {
final server = await _startServer(additionalArgs: additionalArgs);
- final client =
- await DapTestClient.connect(server, captureVmServiceTraffic: true);
+ final client = await DapTestClient.connect(
+ server,
+ captureVmServiceTraffic: verboseLogging,
+ logger: verboseLogging ? print : null,
+ );
return DapTestSession._(server, client);
}
diff --git a/pkg/dds/tool/dap/run_server.dart b/pkg/dds/tool/dap/run_server.dart
index ba22d72..0178e85 100644
--- a/pkg/dds/tool/dap/run_server.dart
+++ b/pkg/dds/tool/dap/run_server.dart
@@ -26,7 +26,6 @@
static const argIpv6 = 'ipv6';
static const argDds = 'dds';
static const argAuthCodes = 'auth-codes';
- static const argVerbose = 'verbose';
final Stream<List<int>> _inputStream;
final StreamSink<List<int>> _outputSink;