diff options
author | Steve Sanderson <SteveSandersonMS@users.noreply.github.com> | 2020-02-26 21:52:36 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-26 21:52:36 +0300 |
commit | 3b0e35d1bcdd91c160277c71b0bc4acad3747ce8 (patch) | |
tree | 75fbabbf2394515958e3f55453afb41a2199229a /sdks | |
parent | 6c5a18ba50dd97ceb15a478f5cca997ecf8b7765 (diff) |
Debug proxy updates (#19026)
Currently, the Mono WebAssembly debug proxy logic is treated as "shared source" with ASP.NET Core. Each time we update by copying the sources from this repo into the ASP.NET Core repo, we need to make some updates to avoid problems. The intention of this PR is to make the updates here at source, so we can simply copy the sources as-is and don't need to update them each time.
The changes are:
Making everything internal, since this is not intended as public API surface for ASP.NET Core developers. It's an internal implementation detail of the framework.
To retain convenience for the ProxyDriver and Mono test code, this PR also adds a simple public entrypoint called DebuggerProxy. This exposes nothing except the ability to connect a debugger proxy instance to a websocket. In the ASP.NET Core code, we'll simply omit this file since it's not needed, but even if we did get it in the future when the proxy feature is published as a package, it would still be fine since it doesn't expose any public API that would be expensive to support and maintain.
Replacing all the Console.WriteLine calls with use of ILogger from the standard Microsoft.Extensions.Logging package, as used by most .NET Core-based application frameworks including ASP.NET Core.
This allows external code to control what happens with log output, what severity levels are filtered in/out, etc. In ProxyDriver and Mono test code, I've configured it to behave just like before: it logs to console, and doesn't filter out anything.
This has the benefit that various bits of commented-out logging code no longer need to be commented out. Instead, when calling the logger.Log* methods, each call site can specify a severity level and then (for example) the filter level could be set to Debug so that all Trace items are filtered out by default.
Diffstat (limited to 'sdks')
-rw-r--r-- | sdks/wasm/DebuggerTestSuite/DevToolsClient.cs (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsClient.cs) | 11 | ||||
-rw-r--r-- | sdks/wasm/DebuggerTestSuite/InspectorClient.cs (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/InspectorClient.cs) | 5 | ||||
-rw-r--r-- | sdks/wasm/DebuggerTestSuite/Support.cs | 5 | ||||
-rw-r--r-- | sdks/wasm/Mono.WebAssembly.DebuggerProxy/AssemblyInfo.cs | 3 | ||||
-rw-r--r-- | sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebugStore.cs | 19 | ||||
-rw-r--r-- | sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebuggerProxy.cs | 22 | ||||
-rw-r--r-- | sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs | 29 | ||||
-rw-r--r-- | sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj | 1 | ||||
-rw-r--r-- | sdks/wasm/Mono.WebAssembly.DebuggerProxy/MonoProxy.cs | 11 | ||||
-rw-r--r-- | sdks/wasm/ProxyDriver/Startup.cs | 5 | ||||
-rw-r--r-- | sdks/wasm/ProxyDriver/TestHarnessStartup.cs | 5 |
11 files changed, 86 insertions, 30 deletions
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsClient.cs b/sdks/wasm/DebuggerTestSuite/DevToolsClient.cs index 92272f9ae34..4fb0fd0f866 100644 --- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsClient.cs +++ b/sdks/wasm/DebuggerTestSuite/DevToolsClient.cs @@ -6,16 +6,19 @@ using System.Threading; using System.IO; using System.Text; using System.Collections.Generic; +using Microsoft.Extensions.Logging; namespace WebAssembly.Net.Debugging { - public class DevToolsClient: IDisposable { + internal class DevToolsClient: IDisposable { ClientWebSocket socket; List<Task> pending_ops = new List<Task> (); TaskCompletionSource<bool> side_exit = new TaskCompletionSource<bool> (); List<byte []> pending_writes = new List<byte []> (); Task current_write; + readonly ILogger logger; - public DevToolsClient () { + public DevToolsClient (ILogger logger) { + this.logger = logger; } ~DevToolsClient() { @@ -99,7 +102,7 @@ namespace WebAssembly.Net.Debugging { Func<CancellationToken, Task> send, CancellationToken token) { - Console.WriteLine ("connecting to {0}", uri); + logger.LogDebug ("connecting to {0}", uri); this.socket = new ClientWebSocket (); this.socket.Options.KeepAliveInterval = Timeout.InfiniteTimeSpan; @@ -133,7 +136,7 @@ namespace WebAssembly.Net.Debugging { protected virtual void Log (string priority, string msg) { - // + // } } } diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/InspectorClient.cs b/sdks/wasm/DebuggerTestSuite/InspectorClient.cs index 7454aa6d871..814ea7fdf75 100644 --- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/InspectorClient.cs +++ b/sdks/wasm/DebuggerTestSuite/InspectorClient.cs @@ -8,13 +8,16 @@ using System.Threading; using System.IO; using System.Text; using System.Collections.Generic; +using Microsoft.Extensions.Logging; namespace WebAssembly.Net.Debugging { - public class InspectorClient : DevToolsClient { + internal class InspectorClient : DevToolsClient { List<(int, TaskCompletionSource<Result>)> pending_cmds = new List<(int, TaskCompletionSource<Result>)> (); Func<string, JObject, CancellationToken, Task> onEvent; int next_cmd_id; + public InspectorClient (ILogger logger) : base(logger) {} + Task HandleMessage (string msg, CancellationToken token) { var res = JObject.Parse (msg); diff --git a/sdks/wasm/DebuggerTestSuite/Support.cs b/sdks/wasm/DebuggerTestSuite/Support.cs index a9ffeff99be..8fc1bc8e5b9 100644 --- a/sdks/wasm/DebuggerTestSuite/Support.cs +++ b/sdks/wasm/DebuggerTestSuite/Support.cs @@ -8,6 +8,7 @@ using System.IO; using System.Text; using System.Collections.Generic; +using Microsoft.Extensions.Logging; using WebAssembly.Net.Debugging; using Newtonsoft.Json.Linq; using Xunit; @@ -72,7 +73,9 @@ namespace DebuggerTests using (var cts = new CancellationTokenSource ()) { cts.CancelAfter (span?.Milliseconds ?? 60 * 1000); //tests have 1 minute to complete by default var uri = new Uri ($"ws://{TestHarnessProxy.Endpoint.Authority}/launch-chrome-and-connect"); - using (var client = new InspectorClient ()) { + using var loggerFactory = LoggerFactory.Create( + builder => builder.AddConsole().AddFilter(null, LogLevel.Trace)); + using (var client = new InspectorClient (loggerFactory.CreateLogger<Inspector>())) { await client.Connect (uri, OnMessage, async token => { Task[] init_cmds = { client.SendCommand ("Profiler.enable", null, token), diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/AssemblyInfo.cs b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/AssemblyInfo.cs new file mode 100644 index 00000000000..8e935c7ed0d --- /dev/null +++ b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo ("DebuggerTestSuite")] diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebugStore.cs b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebugStore.cs index eb09140742b..1932bc2044d 100644 --- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebugStore.cs +++ b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebugStore.cs @@ -11,6 +11,7 @@ using Newtonsoft.Json; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Threading; +using Microsoft.Extensions.Logging; namespace WebAssembly.Net.Debugging { internal class BreakpointRequest { @@ -292,6 +293,7 @@ namespace WebAssembly.Net.Debugging { static int next_id; ModuleDefinition image; readonly int id; + readonly ILogger logger; Dictionary<int, MethodInfo> methods = new Dictionary<int, MethodInfo> (); Dictionary<string, string> sourceLinkMappings = new Dictionary<string, string>(); readonly List<SourceFile> sources = new List<SourceFile>(); @@ -314,7 +316,7 @@ namespace WebAssembly.Net.Debugging { this.image = ModuleDefinition.ReadModule (new MemoryStream (assembly), rp); } catch (BadImageFormatException ex) { - Console.WriteLine ($"Failed to read assembly as portable PDB: {ex.Message}"); + logger.LogWarning ($"Failed to read assembly as portable PDB: {ex.Message}"); } catch (ArgumentNullException) { if (pdb != null) throw; @@ -337,8 +339,9 @@ namespace WebAssembly.Net.Debugging { Populate (); } - public AssemblyInfo () + public AssemblyInfo (ILogger logger) { + this.logger = logger; } void Populate () @@ -524,6 +527,11 @@ namespace WebAssembly.Net.Debugging { internal class DebugStore { List<AssemblyInfo> assemblies = new List<AssemblyInfo> (); HttpClient client = new HttpClient (); + readonly ILogger logger; + + public DebugStore (ILogger logger) { + this.logger = logger; + } class DebugItem { public string Url { get; set; } @@ -554,7 +562,7 @@ namespace WebAssembly.Net.Debugging { Data = Task.WhenAll (client.GetByteArrayAsync (url), pdb != null ? client.GetByteArrayAsync (pdb) : Task.FromResult<byte []> (null)) }); } catch (Exception e) { - Console.WriteLine ($"Failed to read {url} ({e.Message})"); + logger.LogDebug ($"Failed to read {url} ({e.Message})"); } } @@ -563,7 +571,7 @@ namespace WebAssembly.Net.Debugging { var bytes = await step.Data; assemblies.Add (new AssemblyInfo (step.Url, bytes[0], bytes[1])); } catch (Exception e) { - Console.WriteLine ($"Failed to Load {step.Url} ({e.Message})"); + logger.LogDebug ($"Failed to Load {step.Url} ({e.Message})"); } } } @@ -611,8 +619,7 @@ namespace WebAssembly.Net.Debugging { var res = new List<SourceLocation> (); if (doc == null) { - //FIXME we need to write up logging here - Console.WriteLine ($"Could not find document {src_id}"); + logger.LogDebug ($"Could not find document {src_id}"); return res; } diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebuggerProxy.cs b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebuggerProxy.cs new file mode 100644 index 00000000000..74566c56024 --- /dev/null +++ b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebuggerProxy.cs @@ -0,0 +1,22 @@ +using System; +using System.Net.WebSockets; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace WebAssembly.Net.Debugging { + + // This type is the public entrypoint that allows external code to attach the debugger proxy + // to a given websocket listener. Everything else in this package can be internal. + + public class DebuggerProxy { + private readonly MonoProxy proxy; + + public DebuggerProxy (ILoggerFactory loggerFactory) { + proxy = new MonoProxy(loggerFactory); + } + + public Task Run (Uri browserUri, WebSocket ideSocket) { + return proxy.Run (browserUri, ideSocket); + } + } +} diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs index e849dc18e07..158fdcc1dfb 100644 --- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs +++ b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs @@ -8,17 +8,18 @@ using System.Threading; using System.IO; using System.Text; using System.Collections.Generic; +using Microsoft.Extensions.Logging; namespace WebAssembly.Net.Debugging { - public class SessionId { + internal class SessionId { public string sessionId; } - public class MessageId : SessionId { + internal class MessageId : SessionId { public int id; } - public struct Result { + internal struct Result { public JObject Value { get; private set; } public JObject Error { get; private set; } @@ -93,7 +94,7 @@ namespace WebAssembly.Net.Debugging { if (pending.Count == 1) { if (current_send != null) throw new Exception ("current_send MUST BE NULL IF THERE'S no pending send"); - //Console.WriteLine ("sending {0} bytes", bytes.Length); + //logger.LogTrace ("sending {0} bytes", bytes.Length); current_send = Ws.SendAsync (new ArraySegment<byte> (bytes), WebSocketMessageType.Text, true, token); return current_send; } @@ -116,7 +117,7 @@ namespace WebAssembly.Net.Debugging { } } - public class DevToolsProxy { + internal class DevToolsProxy { TaskCompletionSource<bool> side_exception = new TaskCompletionSource<bool> (); TaskCompletionSource<bool> client_initiated_close = new TaskCompletionSource<bool> (); List<(MessageId, TaskCompletionSource<Result>)> pending_cmds = new List<(MessageId, TaskCompletionSource<Result>)> (); @@ -125,6 +126,12 @@ namespace WebAssembly.Net.Debugging { int next_cmd_id; List<Task> pending_ops = new List<Task> (); List<DevToolsQueue> queues = new List<DevToolsQueue> (); + protected readonly ILogger logger; + + public DevToolsProxy (ILoggerFactory loggerFactory) + { + logger = loggerFactory.CreateLogger<DevToolsProxy>(); + } protected virtual Task<bool> AcceptEvent (SessionId sessionId, string method, JObject args, CancellationToken token) { @@ -188,7 +195,7 @@ namespace WebAssembly.Net.Debugging { { try { if (!await AcceptEvent (sessionId, method, args, token)) { - //Console.WriteLine ("proxy browser: {0}::{1}",method, args); + //logger.LogDebug ("proxy browser: {0}::{1}",method, args); SendEventInternal (sessionId, method, args, token); } } catch (Exception e) { @@ -210,7 +217,7 @@ namespace WebAssembly.Net.Debugging { void OnResponse (MessageId id, Result result) { - //Console.WriteLine ("got id {0} res {1}", id, result); + //logger.LogTrace ("got id {0} res {1}", id, result); // Fixme var idx = pending_cmds.FindIndex (e => e.Item1.id == id.id && e.Item1.sessionId == id.sessionId); var item = pending_cmds [idx]; @@ -317,7 +324,7 @@ namespace WebAssembly.Net.Debugging { try { while (!x.IsCancellationRequested) { var task = await Task.WhenAny (pending_ops.ToArray ()); - //Console.WriteLine ("pump {0} {1}", task, pending_ops.IndexOf (task)); + //logger.LogTrace ("pump {0} {1}", task, pending_ops.IndexOf (task)); if (task == pending_ops [0]) { var msg = ((Task<string>)task).Result; if (msg != null) { @@ -363,16 +370,16 @@ namespace WebAssembly.Net.Debugging { { switch (priority) { case "protocol": - //Console.WriteLine (msg); + //logger.LogTrace (msg); break; case "verbose": - //Console.WriteLine (msg); + //logger.LogDebug (msg); break; case "info": case "warning": case "error": default: - Console.WriteLine (msg); + logger.LogDebug (msg); break; } } diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj index bc412ecf0f3..033d2460c05 100644 --- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj +++ b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj @@ -6,6 +6,7 @@ </PropertyGroup> <ItemGroup> + <PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.2" /> <PackageReference Include="Mono.Cecil" Version="0.11.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> </ItemGroup> diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/MonoProxy.cs b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/MonoProxy.cs index f36680bb2a5..c38705692c6 100644 --- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/MonoProxy.cs +++ b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/MonoProxy.cs @@ -7,6 +7,7 @@ using System.Threading; using System.IO; using System.Collections.Generic; using System.Net; +using Microsoft.Extensions.Logging; namespace WebAssembly.Net.Debugging { @@ -51,7 +52,7 @@ namespace WebAssembly.Net.Debugging { => new MonoCommands ($"MONO.mono_wasm_remove_breakpoint({breakpointId})"); } - public enum MonoErrorCodes { + internal enum MonoErrorCodes { BpNotFound = 100000, } @@ -134,10 +135,10 @@ namespace WebAssembly.Net.Debugging { } } - public class MonoProxy : DevToolsProxy { + internal class MonoProxy : DevToolsProxy { Dictionary<string, ExecutionContext> contexts = new Dictionary<string, ExecutionContext> (); - public MonoProxy () { } + public MonoProxy (ILoggerFactory loggerFactory) : base(loggerFactory) { } ExecutionContext GetContext (SessionId sessionId) { @@ -600,7 +601,7 @@ namespace WebAssembly.Net.Debugging { { var context = GetContext (sessionId); - if (Interlocked.CompareExchange (ref context.store, new DebugStore (), null) != null) { + if (Interlocked.CompareExchange (ref context.store, new DebugStore (logger), null) != null) { return await context.Source.Task; } @@ -775,7 +776,7 @@ namespace WebAssembly.Net.Debugging { await res.WriteAsync (doc); source = res.ToString (); - } + } SendResponse (msg_id, Result.OkFromObject (new { scriptSource = source }), token); } catch (Exception e) { diff --git a/sdks/wasm/ProxyDriver/Startup.cs b/sdks/wasm/ProxyDriver/Startup.cs index 59898ce444a..fee6e30552a 100644 --- a/sdks/wasm/ProxyDriver/Startup.cs +++ b/sdks/wasm/ProxyDriver/Startup.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; using System.Net.Http; using System.Collections.Generic; using System.Linq; @@ -122,7 +123,9 @@ namespace WebAssembly.Net.Debugging { var endpoint = new Uri ($"ws://{devToolsHost.Authority}{context.Request.Path.ToString ()}"); try { - var proxy = new MonoProxy (); + using var loggerFactory = LoggerFactory.Create( + builder => builder.AddConsole().AddFilter(null, LogLevel.Trace)); + var proxy = new DebuggerProxy (loggerFactory); var ideSocket = await context.WebSockets.AcceptWebSocketAsync (); await proxy.Run (endpoint, ideSocket); diff --git a/sdks/wasm/ProxyDriver/TestHarnessStartup.cs b/sdks/wasm/ProxyDriver/TestHarnessStartup.cs index 8434f2308f3..bbaf4007663 100644 --- a/sdks/wasm/ProxyDriver/TestHarnessStartup.cs +++ b/sdks/wasm/ProxyDriver/TestHarnessStartup.cs @@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.AspNetCore.StaticFiles; using Newtonsoft.Json.Linq; @@ -101,7 +102,9 @@ namespace WebAssembly.Net.Debugging { Console.WriteLine ($"lauching proxy for {con_str}"); - var proxy = new MonoProxy (); + using var loggerFactory = LoggerFactory.Create( + builder => builder.AddConsole().AddFilter(null, LogLevel.Trace)); + var proxy = new DebuggerProxy (loggerFactory); var browserUri = new Uri (con_str); var ideSocket = await context.WebSockets.AcceptWebSocketAsync (); |