forked from unoplatform/uno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Instrument dev-server to expose in diagnostics in client
- Loading branch information
Showing
15 changed files
with
721 additions
and
82 deletions.
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
src/Uno.UI.RemoteControl.Messaging/DevServerDiagnostics.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#nullable enable | ||
using System; | ||
using System.Linq; | ||
using System.Threading; | ||
using Uno.UI.RemoteControl.HotReload.Messages; | ||
|
||
namespace Uno.UI.RemoteControl; | ||
|
||
public static class DevServerDiagnostics | ||
{ | ||
private static readonly AsyncLocal<ISink> _current = new(); | ||
|
||
/// <summary> | ||
/// Gets the current (async-local) sink for dev-server diagnostics. | ||
/// </summary> | ||
public static ISink Current | ||
{ | ||
get => _current.Value ?? NullSink.Instance; | ||
set => _current.Value = value; | ||
} | ||
|
||
public interface ISink | ||
{ | ||
void ReportInvalidFrame<TContent>(Frame frame); | ||
} | ||
|
||
private class NullSink : ISink | ||
{ | ||
public static NullSink Instance { get; } = new(); | ||
|
||
public void ReportInvalidFrame<TContent>(Frame frame) | ||
{ | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,88 @@ | ||
using System; | ||
#nullable enable | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.IO; | ||
using System.Text; | ||
using Newtonsoft.Json; | ||
|
||
namespace Uno.UI.RemoteControl.HotReload.Messages | ||
namespace Uno.UI.RemoteControl.HotReload.Messages; | ||
|
||
[DebuggerDisplay("{Name}-{Scope}")] | ||
public class Frame | ||
{ | ||
[DebuggerDisplay("{Name}-{Scope}")] | ||
public class Frame | ||
public Frame(short version, string scope, string name, string content) | ||
{ | ||
public Frame(short version, string scope, string name, string content) | ||
{ | ||
Version = version; | ||
Scope = scope; | ||
Name = name; | ||
Content = content; | ||
} | ||
Version = version; | ||
Scope = scope; | ||
Name = name; | ||
Content = content; | ||
} | ||
|
||
public int Version { get; } | ||
public int Version { get; } | ||
|
||
public string Scope { get; } | ||
public string Scope { get; } | ||
|
||
public string Name { get; } | ||
public string Name { get; } | ||
|
||
public string Content { get; } | ||
public string Content { get; } | ||
|
||
public static Frame Read(Stream stream) | ||
public static Frame Read(Stream stream) | ||
{ | ||
using (var reader = new BinaryReader(stream, Encoding.UTF8)) | ||
{ | ||
using (var reader = new BinaryReader(stream, Encoding.UTF8)) | ||
{ | ||
var version = reader.ReadInt16(); | ||
var scope = reader.ReadString(); | ||
var name = reader.ReadString(); | ||
var content = reader.ReadString(); | ||
var version = reader.ReadInt16(); | ||
var scope = reader.ReadString(); | ||
var name = reader.ReadString(); | ||
var content = reader.ReadString(); | ||
|
||
return new Frame(version, scope, name, content); | ||
} | ||
return new Frame(version, scope, name, content); | ||
} | ||
} | ||
|
||
public static Frame Create<T>(short version, string scope, string name, T content) | ||
=> new Frame( | ||
version, | ||
scope, | ||
name, | ||
JsonConvert.SerializeObject(content) | ||
); | ||
public static Frame Create<T>(short version, string scope, string name, T content) | ||
=> new Frame( | ||
version, | ||
scope, | ||
name, | ||
JsonConvert.SerializeObject(content) | ||
); | ||
|
||
public void WriteTo(Stream stream) | ||
{ | ||
var writer = new BinaryWriter(stream, Encoding.UTF8); | ||
public T GetContent<T>() | ||
=> TryGetContent<T>(out var content) ? content : throw new InvalidOperationException("Invalid frame"); | ||
|
||
writer.Write((short)Version); | ||
writer.Write(Scope); | ||
writer.Write(Name); | ||
writer.Write(Content); | ||
public bool TryGetContent<T>([NotNullWhen(true)] out T? content) | ||
{ | ||
try | ||
{ | ||
content = JsonConvert.DeserializeObject<T>(Content); | ||
if (content is not null) | ||
{ | ||
return true; | ||
} | ||
else | ||
{ | ||
DevServerDiagnostics.Current.ReportInvalidFrame<T>(this); | ||
return false; | ||
} | ||
} | ||
catch (Exception) | ||
{ | ||
DevServerDiagnostics.Current.ReportInvalidFrame<T>(this); | ||
content = default; | ||
return false; | ||
} | ||
} | ||
|
||
public void WriteTo(Stream stream) | ||
{ | ||
var writer = new BinaryWriter(stream, Encoding.UTF8); | ||
|
||
writer.Write((short)Version); | ||
writer.Write(Scope); | ||
writer.Write(Name); | ||
writer.Write(Content); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#nullable enable | ||
using System; | ||
using System.Linq; | ||
|
||
namespace Uno.UI.RemoteControl; | ||
|
||
public static class WellKnownScopes | ||
{ | ||
/// <summary> | ||
/// Reserved for internal usage of communication channel between dev-server and IDE (i.e. KeepAliveIdeMessage). | ||
/// </summary> | ||
public const string IdeChannel = "IdeChannel"; | ||
|
||
/// <summary> | ||
/// Reserved for internal usage of communication channel between dev-server and client (i.e. KeepAliveMessage). | ||
/// </summary> | ||
public const string DevServerChannel = "RemoteControlServer"; | ||
|
||
/// <summary> | ||
/// For hot-reload messages, client, server and IDE. | ||
/// </summary> | ||
public const string HotReload = "HotReload"; | ||
|
||
/// <summary> | ||
/// For messages used for testing purpose (e.g. UpdateFile) | ||
/// </summary> | ||
public const string Testing = "UnoRuntimeTests"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#nullable enable | ||
using System; | ||
using System.Linq; | ||
|
||
namespace System.Runtime.CompilerServices; | ||
|
||
internal static class IsExternalInit | ||
{ | ||
} |
25 changes: 25 additions & 0 deletions
25
src/Uno.UI.RemoteControl.Messaging/_Compat/NotNullWhenAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#nullable enable | ||
using System; | ||
using System.Linq; | ||
|
||
namespace System.Diagnostics.CodeAnalysis; | ||
|
||
/// <summary> | ||
/// Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it. | ||
/// </summary> | ||
[global::System.AttributeUsage(global::System.AttributeTargets.Parameter, Inherited = false)] | ||
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] | ||
internal sealed class NotNullWhenAttribute : global::System.Attribute | ||
{ | ||
/// <summary> | ||
/// Initializes the attribute with the specified return value condition. | ||
/// </summary> | ||
/// <param name="returnValue">The return value condition. If the method returns this value, the associated parameter will not be null.</param> | ||
public NotNullWhenAttribute(bool returnValue) | ||
{ | ||
ReturnValue = returnValue; | ||
} | ||
|
||
/// <summary>Gets the return value condition.</summary> | ||
public bool ReturnValue { get; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Reflection; | ||
|
||
namespace Uno.UI.RemoteControl.Helpers; | ||
|
||
internal class VersionHelper | ||
{ | ||
public static string GetVersion(Type type) | ||
=> GetVersion(type.Assembly); | ||
|
||
public static string GetVersion(Assembly assembly) | ||
{ | ||
if (assembly | ||
.GetCustomAttributesData() | ||
.FirstOrDefault(data => data.AttributeType.Name.Contains("AssemblyInformationalVersion", StringComparison.OrdinalIgnoreCase)) | ||
?.ConstructorArguments | ||
.FirstOrDefault() | ||
.Value | ||
?.ToString() is { Length: > 0 } informationalVersion) | ||
{ | ||
return informationalVersion; | ||
} | ||
|
||
if (assembly.GetName().Version is { } assemblyVersion) | ||
{ | ||
return assemblyVersion.ToString(); | ||
} | ||
|
||
return "--unknown--"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,28 @@ | ||
namespace Uno.UI.RemoteControl.Messages | ||
using System; | ||
using Uno.UI.RemoteControl.Helpers; | ||
|
||
namespace Uno.UI.RemoteControl.Messages; | ||
|
||
public record KeepAliveMessage : IMessage | ||
{ | ||
public class KeepAliveMessage : IMessage | ||
{ | ||
public const string Name = nameof(KeepAliveMessage); | ||
private static readonly string _localVersion = VersionHelper.GetVersion(typeof(KeepAliveMessage)); | ||
|
||
public const string Name = nameof(KeepAliveMessage); | ||
|
||
public string Scope => WellKnownScopes.DevServerChannel; | ||
|
||
string IMessage.Name => Name; | ||
|
||
public KeepAliveMessage() | ||
{ | ||
} | ||
/// <summary> | ||
/// The version of the dev-server version of the sender. | ||
/// </summary> | ||
public string? AssemblyVersion { get; init; } = _localVersion; | ||
|
||
public string Scope => "RemoteControlServer"; | ||
/// <summary> | ||
/// Sequence ID of the ping. | ||
/// </summary> | ||
public ulong SequenceId { get; init; } | ||
|
||
string IMessage.Name => Name; | ||
} | ||
public KeepAliveMessage Next() | ||
=> this with { SequenceId = SequenceId + 1 }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,22 @@ | ||
namespace Uno.UI.RemoteControl.Messages | ||
using static Uno.UI.RemoteControl.Messages.ProcessorsDiscoveryResponse; | ||
|
||
namespace Uno.UI.RemoteControl.Messages; | ||
|
||
public class ProcessorsDiscovery : IMessage | ||
{ | ||
public class ProcessorsDiscovery : IMessage | ||
{ | ||
public const string Name = nameof(ProcessorsDiscovery); | ||
public const string Name = nameof(ProcessorsDiscovery); | ||
|
||
public ProcessorsDiscovery(string basePath, string appInstanceId = "") | ||
{ | ||
BasePath = basePath; | ||
AppInstanceId = appInstanceId; | ||
} | ||
public ProcessorsDiscovery(string basePath, string appInstanceId = "") | ||
{ | ||
BasePath = basePath; | ||
AppInstanceId = appInstanceId; | ||
} | ||
|
||
public string Scope => "RemoteControlServer"; | ||
public string Scope => WellKnownScopes.DevServerChannel; | ||
|
||
string IMessage.Name => Name; | ||
string IMessage.Name => Name; | ||
|
||
public string BasePath { get; } | ||
public string BasePath { get; } | ||
|
||
public string AppInstanceId { get; } | ||
} | ||
public string AppInstanceId { get; } | ||
} |
16 changes: 16 additions & 0 deletions
16
src/Uno.UI.RemoteControl/Messages/ProcessorsDiscoveryResponse.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using System; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
|
||
namespace Uno.UI.RemoteControl.Messages; | ||
|
||
public record ProcessorsDiscoveryResponse(IImmutableList<string> Assemblies, IImmutableList<DiscoveredProcessor> Processors) : IMessage | ||
{ | ||
public const string Name = nameof(ProcessorsDiscoveryResponse); | ||
|
||
public string Scope => WellKnownScopes.DevServerChannel; | ||
|
||
string IMessage.Name => Name; | ||
} | ||
|
||
public record DiscoveredProcessor(string AssemblyPath, string Type, string Version, bool IsLoaded, string? LoadError = null); |
Oops, something went wrong.