-
Notifications
You must be signed in to change notification settings - Fork 821
App Launch monitoring #21560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+4,730
−498
Merged
App Launch monitoring #21560
Changes from 47 commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
f1a0efa
feat: Introduce `ApplicationLaunchMonitor` for correlating app launch…
carldebilly 481c22c
fix(remote-control): use TimeProvider timers and stabilize launch tim…
carldebilly 76abdaf
refactor(remote-control): Simplify `ServerProcessor` attribute usage …
carldebilly 7e00f51
chore: Improve uni test assembly discovery helpers
carldebilly d967317
feat(app-launch): Add support for tracking application launches and r…
carldebilly 4aff59c
refactor(hot-reload): Remove unused field from `FileUpdateProcessor` …
carldebilly 63cf93e
docs: Update contribution and telemetry guidelines
carldebilly 80c9c36
refactor: Improved telemetry testing. No functional changes
carldebilly 12b87aa
feat(dev-server): Add `AssemblyInfoReader` and improve app launch con…
carldebilly 5b8ed56
ci: Fix build
carldebilly 290ff58
ci: Another try to fix build (net9 vs net10)
carldebilly b6905e6
feat(app-launch): Add scavenging for stale launches and enhance conne…
carldebilly 30cc2fc
ci: Trying to fix tests on CI
carldebilly 3fd4550
fix(logging): Ensure consistent naming for binlog files and remove re…
carldebilly 4d1995f
chore: Temporary add output for failing test - will be removed
carldebilly 37ce641
ci: Trying to fix the build again
carldebilly c0e15d3
feat(app-launch): Introduce `VsAppLaunchStateService` for determinist…
carldebilly f8e491f
refactor(tests): Convert test namespace and class declarations to fil…
carldebilly d429acf
feat(app-launch): Add `VsAppLaunchIdeBridge` to integrate Play/Build …
carldebilly 17fb9ae
feat(app-launch): Preserve original instance during state transitions…
carldebilly 38d094f
feat(app-launch): Add retention handling for unmatched launches and t…
carldebilly cc11a72
fix(app-launch): Dispose of `_scavengeTimer` to prevent resource leak…
carldebilly b9b3008
feat(app-launch): Add new endpoint to register app launches via assem…
carldebilly a9ef47d
fix(app-launch): Ensure interception only occurs for debug builds in …
carldebilly a239cd2
fix(app-launch): Update endpoint to use encoded paths and align with …
carldebilly 5219c6a
feat(app-launch): Refactor app launch endpoints and improve platform …
carldebilly a3e7149
feat(app-launch): Add IDE and plugin metadata support across launch r…
carldebilly 90f0a5d
feat(app-launch): Added new integration test to validate timeout beha…
carldebilly 4eca719
feat(app-launch): Add UnoNotifyAppLaunch MSBuild target for IDE integ…
carldebilly 60e4e53
fix(app-launch): Enforce Debug configuration for UnoNotifyAppLaunch t…
carldebilly 3d89e97
fix(app-launch): Update telemetry event properties for clarity and co…
carldebilly 1db41d4
feat(telemetry): Enhance telemetry documentation with source links an…
carldebilly 7be8c13
fix(logs): Suppress WebSocket closure noise in logs
carldebilly 8c5b065
feat(app-launch): Improve late-match classification for app launches
carldebilly e87d18d
chore(build): Update target frameworks and project references for com…
carldebilly 1c10409
docs(telemetry): Adjust documentation about telemetry events
carldebilly c514182
fix(tests): Remove unnecessary null-forgiveness operators
carldebilly e93cef3
chore(remote-control): Correct typos
carldebilly a7f26a6
feat(app-launch): Include IDE version in app launch state consumer in…
carldebilly 7c4c963
chore(code-style): Apply consistent formatting across tests and helpers
carldebilly 78612c8
chore(tests): Pin MessagePack dependency to version 3.1.4
carldebilly e4349c2
chore(build): Post-rebase conflict solving.
carldebilly cc11309
fix(logging): Include assembly file name in error message for failed …
carldebilly 3feb2ad
fix(remote-control): Replace recursive re-scheduling with single peri…
carldebilly 354bba8
fix(remote-control): Signal connection establishment once and handle …
carldebilly e58847c
fix(app-launch): Make IsDebug optional and default to false instead o…
carldebilly 602a481
chore(app-launch): Apply PR review suggestions
carldebilly 130d34b
feat(remote-control): Introduce configuration helpers for parsing and…
carldebilly b626a6d
fix(app-launch): Rename MSBuild task properties for consistent Uno-pr…
carldebilly File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,87 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Net; | ||
| using System.Net.Http; | ||
| using Microsoft.Build.Framework; | ||
| using Microsoft.Build.Utilities; | ||
|
|
||
| namespace Uno.Sdk.Tasks; | ||
|
|
||
| public sealed class UnoNotifyAppLaunchToDevServer_v0 : Task | ||
| { | ||
| [Required] public string Port { get; set; } = string.Empty; | ||
| [Required] public string TargetPath { get; set; } = string.Empty; | ||
| public string IsDebug { get; set; } = string.Empty; | ||
| public string Ide { get; set; } = string.Empty; | ||
| public string Plugin { get; set; } = string.Empty; | ||
|
|
||
| [Output] public bool Success { get; set; } | ||
| [Output] public string ResponseContent { get; set; } = string.Empty; | ||
|
|
||
| public override bool Execute() | ||
| { | ||
| // Validate | ||
| if (string.IsNullOrWhiteSpace(Port) || !ushort.TryParse(Port, out var portNum) || portNum == 0) | ||
| { | ||
| Log.LogError("UnoRemoteControlPort must be a valid port number between 1 and 65535."); | ||
| return Success = false; | ||
| } | ||
| if (string.IsNullOrWhiteSpace(TargetPath)) | ||
| { | ||
| Log.LogError("TargetPath is required."); | ||
| return Success = false; | ||
| } | ||
|
|
||
| var encodedPath = WebUtility.UrlEncode(TargetPath); | ||
|
|
||
| var parts = new List<string>(); | ||
| void Add(string name, string value) | ||
| { | ||
| if (!string.IsNullOrEmpty(value)) | ||
| parts.Add($"{name}={Uri.EscapeDataString(value)}"); | ||
| } | ||
|
|
||
| Add("ide", Ide); | ||
| Add("plugin", Plugin); | ||
|
|
||
| // IsDebug is optional: treat empty/null as "false" | ||
| var isDebugValue = false; | ||
| if (!string.IsNullOrEmpty(IsDebug) && bool.TryParse(IsDebug, out var parsed)) | ||
| { | ||
| isDebugValue = parsed; | ||
| } | ||
| Add("isDebug", isDebugValue ? "true" : "false"); | ||
|
|
||
| var qs = parts.Count > 0 ? "?" + string.Join("&", parts) : string.Empty; | ||
| var url = $"http://localhost:{portNum}/applaunch/asm/{encodedPath}{qs}"; | ||
|
|
||
| try | ||
| { | ||
| using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(5) }; | ||
| var response = client.GetAsync(url).GetAwaiter().GetResult(); | ||
|
|
||
| Log.LogMessage(MessageImportance.High, | ||
| $"[NotifyDevServer] GET {url} -> {(int)response.StatusCode} {response.ReasonPhrase}"); | ||
|
|
||
| if (response.IsSuccessStatusCode) | ||
| { | ||
| ResponseContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); | ||
| Success = true; | ||
| return true; | ||
| } | ||
| else | ||
| { | ||
| Success = false; | ||
| ResponseContent = string.Empty; | ||
| return false; | ||
| } | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Log.LogWarning($"[NotifyDevServer] GET {url} failed: {ex.GetType().Name}: {ex.Message}"); | ||
| Success = false; | ||
| ResponseContent = string.Empty; | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or 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,72 @@ | ||
| <?xml version="1.0" encoding="utf-8" ?> | ||
| <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
|
|
||
| <!-- | ||
| This file defines the UnoNotifyAppLaunch target used to notify the DevServer (RemoteControl) | ||
| when an application has been launched, so that the DevServer can monitor that the launched app | ||
| connects back in a timely manner. This is used to detect launch failures and report them to telemetry. | ||
|
|
||
| This target is intended to be invoked after the application has been built, but before it is launched, by | ||
| the IDE tooling (e.g. Visual Studio Code, Rider, etc). Is it not required for VisualStudio, which is using | ||
| a different mechanism to do the same thing. The implementation in this version is in the `AppLaunch` folder | ||
| of the `Uno.UI.RemoteControl.VS` project. | ||
|
|
||
| IMPORTANT: This target should only be called with Debug configuration (-c:Debug or -p:Configuration=Debug). | ||
| It will fail with an error if called with any other configuration (e.g., Release). | ||
|
|
||
| Other IDEs will call this target by specifying the `UnoRemoteControlPort` property using the following command: | ||
|
|
||
| ```shell | ||
| dotnet build <app csproj> -c:Debug -t:UnoNotifyAppLaunch -p:TargetFramework=<tfm to launch> -p:NoBuild=true -restore:false -v:d -noLogo -low -p:Ide=<ide info> -p:Plugin=<Uno plugin version> -p:IsDebug=false | ||
| ``` | ||
|
|
||
| To retrieve the HTTP response content (MVID and target framework info), use -getProperty: | ||
|
|
||
| ```shell | ||
| dotnet build <app csproj> -c:Debug -t:UnoNotifyAppLaunch -getProperty:UnoNotifyAppLaunchHttpResponse -p:TargetFramework=<tfm> -p:NoBuild=true -restore:false -p:Ide=<ide> -p:Plugin=<version> -p:IsDebug=false | ||
| ``` | ||
| --> | ||
|
|
||
| <PropertyGroup> | ||
| <UnoNotifyAppLaunchDependsOn>$(UnoNotifyAppLaunchDependsOn);GetTargetPath</UnoNotifyAppLaunchDependsOn> | ||
| </PropertyGroup> | ||
|
|
||
| <UsingTask TaskName="Uno.Sdk.Tasks.UnoNotifyAppLaunchToDevServer_v0" | ||
| AssemblyFile="$(MSBuildThisFileDirectory)netstandard2.0\Uno.Sdk_v0.dll" /> | ||
| <Target Name="UnoNotifyAppLaunch" | ||
| DependsOnTargets="$(UnoNotifyAppLaunchDependsOn)" | ||
| Condition="'$(TargetFramework)'!=''"> | ||
|
|
||
| <Message Importance="Low" | ||
| Text="NotifyAppLaunch: TFM=$(TargetFramework) TargetPath=$(TargetPath) Configuration=$(Configuration)"/> | ||
|
|
||
| <Error Text="UnoNotifyAppLaunch target should only be called with Debug configuration. Current configuration: $(Configuration)" | ||
| Condition="'$(Configuration)' != 'Debug'"/> | ||
|
|
||
| <Error Text="UnoRemoteControlPort property must be defined to use UnoNotifyAppLaunch target." | ||
| Condition="'$(UnoRemoteControlPort)' == ''"/> | ||
|
|
||
| <Error Text="Target assembly file not found: $(TargetPath)" | ||
| Condition="!Exists('$(TargetPath)')"/> | ||
|
|
||
| <!-- Pass the new properties --> | ||
| <UnoNotifyAppLaunchToDevServer_v0 | ||
| Port="$(UnoRemoteControlPort)" | ||
| TargetPath="$(TargetPath)" | ||
| Ide="$(Ide)" | ||
| Plugin="$(Plugin)" | ||
| IsDebug="$(IsDebug)"> | ||
| <Output TaskParameter="Success" PropertyName="_UnoLaunchSuccess"/> | ||
| <Output TaskParameter="ResponseContent" PropertyName="UnoNotifyAppLaunchHttpResponse"/> | ||
| </UnoNotifyAppLaunchToDevServer_v0> | ||
|
|
||
| <Error Text="Failed to notify devserver for assembly: $(TargetPath)" Importance="High" Condition="'$(_UnoLaunchSuccess)' != 'True'"/> | ||
carldebilly marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| <Message Text="Successfully notified devserver for assembly: $(TargetPath)" | ||
| Condition="'$(_UnoLaunchSuccess)' == 'True'"/> | ||
|
|
||
| <Message Text="DevServer response: $(UnoNotifyAppLaunchHttpResponse)" | ||
| Condition="'$(_UnoLaunchSuccess)' == 'True' AND '$(UnoNotifyAppLaunchHttpResponse)' != ''"/> | ||
| </Target> | ||
|
|
||
| </Project> | ||
This file contains hidden or 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 hidden or 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 hidden or 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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.