From 814cd9aadf5798baac5549a16bce644473375941 Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:01:21 -0500 Subject: [PATCH 01/10] add analytics --- Editor/Api/AnalyticsApi.cs | 79 ++++++++++++ Editor/Api/AnalyticsApi.cs.meta | 2 + Editor/EdgegapWindowV2.cs | 218 ++++++++++++++++++++++++++++++-- 3 files changed, 289 insertions(+), 10 deletions(-) create mode 100644 Editor/Api/AnalyticsApi.cs create mode 100644 Editor/Api/AnalyticsApi.cs.meta diff --git a/Editor/Api/AnalyticsApi.cs b/Editor/Api/AnalyticsApi.cs new file mode 100644 index 0000000..318cc0c --- /dev/null +++ b/Editor/Api/AnalyticsApi.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using UnityEngine; + +namespace Edgegap.Editor.Api +{ + public class AnalyticsApi + { + private readonly HttpClient _httpClient = new HttpClient(); + private string _url = "https://us.i.posthog.com/i/v0/e/"; + private string _Key = "phc_sjDOXB5OakYZu0h70u4GLcFR7hZ55XfnnDef5xaeDws"; + private string _Event = "Plugin Button Click"; + private string _DistinctId; + + private class AnalyticsPayload + { + [JsonProperty("api_key")] + public string ApiKey { get; set; } + + [JsonProperty("event")] + public string Event { get; set; } + + [JsonProperty("distinct_id")] + public string DistinctId { get; set; } + + [JsonProperty("properties")] + public Dictionary Properties { get; set; } + + public AnalyticsPayload( + string apiKey, + string ev, + string disctinctId, + Dictionary properties + ) + { + this.ApiKey = apiKey; + this.Event = ev; + this.DistinctId = disctinctId; + this.Properties = properties; + } + + public override string ToString() => JsonConvert.SerializeObject(this); + } + + public AnalyticsApi(string distinctId) + { + this._httpClient.BaseAddress = new Uri(_url); + this._httpClient.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/json") + ); + this._DistinctId = distinctId; + } + + public async Task PostAsync(Dictionary properties) + { + AnalyticsPayload payload = new AnalyticsPayload(_Key, _Event, _DistinctId, properties); + StringContent stringContent = new StringContent( + payload.ToString(), + Encoding.UTF8, + "application/json" + ); + + try + { + return await _httpClient.PostAsync(_httpClient.BaseAddress, stringContent); + } + catch (Exception e) + { + Debug.LogError($"Error: {e}"); + throw; + } + } + } +} diff --git a/Editor/Api/AnalyticsApi.cs.meta b/Editor/Api/AnalyticsApi.cs.meta new file mode 100644 index 0000000..c45facf --- /dev/null +++ b/Editor/Api/AnalyticsApi.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f145b77191ba04842a4e0f94261d1c35 \ No newline at end of file diff --git a/Editor/EdgegapWindowV2.cs b/Editor/EdgegapWindowV2.cs index d5b9a2e..90b24cd 100644 --- a/Editor/EdgegapWindowV2.cs +++ b/Editor/EdgegapWindowV2.cs @@ -900,12 +900,21 @@ private async Task checkForUpdates() /// /// "Sign out" btn click /// - private void OnSignOutBtnClickAsync() + private async void OnSignOutBtnClickAsync() { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", "1. Connect Edgegap Account > Sign out" }, + { "utm_source", "plugin_unity" }, + }; + string distinctId = getDistinctId(); + EditorPrefs.DeleteKey(EdgegapWindowMetadata.API_TOKEN_KEY_STR); EditorPrefs.DeleteKey(EdgegapWindowMetadata.SELECTED_NETCODE_KEY_STR); _apiTokenInput.SetValueWithoutNotify(""); ResetState(); + await analyticsApi.PostAsync(properties); } /// @@ -967,8 +976,16 @@ private async void OnInstallLinuxBtnClick() /// /// Open Unity build settings btn click /// - private void OnOpenBuildParamsBtnClick() + private async void OnOpenBuildParamsBtnClick() { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", "2. Build Game Server > Edit Settings" }, + { "utm_source", "plugin_unity" }, + }; + await analyticsApi.PostAsync(properties); + #if UNITY_2021_3_OR_NEWER EditorWindow.GetWindow( System.Type.GetType("UnityEditor.BuildPlayerWindow,UnityEditor") @@ -992,6 +1009,23 @@ private void OnFolderNameInputFocusOut(FocusOutEvent evt) /// private void OnBuildServerBtnClick() { + _ = BuildServer(); + } + + private async Task BuildServer(string buttonName = "2. Build Game Server > Build") + { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", buttonName }, + { "utm_source", "plugin_unity" }, + }; + + if (buttonName.Contains("Rebuild from Source")) + { + properties.Add("rebuild_step", "Build"); + } + try { _serverBuildBtn.SetEnabled(false); @@ -1026,6 +1060,8 @@ private void OnBuildServerBtnClick() else { OnBuildContainerizeUploadSuccess(_serverBuildResultLabel, "Build succeeded."); + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(properties); } _containerizeFoldout.SetValueWithoutNotify(true); @@ -1033,6 +1069,11 @@ private void OnBuildServerBtnClick() } catch (Exception e) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(properties); + Debug.LogError($"OnBuildServerBtnClick Error: {e}"); ShowErrorDialog(e.Message, _serverBuildResultLabel, "Build failed (see logs)."); } @@ -1053,11 +1094,18 @@ private void OnDockerInfoClick() => /// private void OnValidateDockerBtnClick() { - _ = ValidateDockerRequirement(); + _ = ValidateDockerRequirement(true); } - private async Task ValidateDockerRequirement() + private async Task ValidateDockerRequirement(bool runAnalytics) { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", "3. Containerize Server > Validate Docker" }, + { "utm_source", "plugin_unity" }, + }; + _validateDockerRequirementsBtn.SetEnabled(false); hideResultLabels(); string error; @@ -1070,6 +1118,14 @@ private async Task ValidateDockerRequirement() catch (Exception e) { error = e.Message; + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + + if (runAnalytics) + { + await analyticsApi.PostAsync(properties); + } } _validateDockerRequirementsBtn.SetEnabled(true); @@ -1097,6 +1153,7 @@ private async Task ValidateDockerRequirement() _dockerRequirementsResultLabel, "There was a problem." ); + return error; } else @@ -1105,6 +1162,12 @@ private async Task ValidateDockerRequirement() _dockerRequirementsResultLabel, "Docker is running." ); + properties.Add("succeeded", true.ToString()); + + if (runAnalytics) + { + await analyticsApi.PostAsync(properties); + } } return null; } @@ -1225,10 +1288,29 @@ private void OnContainerizeBtnClick() _ = ContainerizeServerAsync(); } - private async Task ContainerizeServerAsync() + private async Task ContainerizeServerAsync( + string buttonName = "3. Containerize Server > Containerize" + ) { - if (!string.IsNullOrEmpty(await ValidateDockerRequirement())) + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", buttonName }, + { "utm_source", "plugin_unity" }, + { "docker_params", _optionalDockerParamsInput.value }, + }; + + if (buttonName.Contains("Rebuild from Source")) + { + properties.Add("rebuild_step", "Containerize"); + } + + if (!string.IsNullOrEmpty(await ValidateDockerRequirement(false))) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", "Docker validation failed"); + await analyticsApi.PostAsync(properties); + return; } try @@ -1270,6 +1352,8 @@ private async Task ContainerizeServerAsync() _containerizeImageTagInput.value == _containerizeImageTagInputDefault ? nowUTC : _containerizeImageTagInput.value; + properties.Add("image_name", imageName); + properties.Add("image_tag", tag); await EdgegapBuildUtils.RunCommand_DockerBuild( dockerfilePath, @@ -1300,9 +1384,17 @@ await EdgegapBuildUtils.RunCommand_DockerBuild( { _localTestImageShowDropdownBtn.SetEnabled(true); } + + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(properties); } catch (Exception e) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(properties); + Debug.LogError($"Containerization Error: {e}"); ShowErrorDialog( e.Message, @@ -1392,6 +1484,15 @@ private bool CheckFilledLocalTestInputs() private async void OnLocalTestDeployClick() { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", "4. Test Locally > Deploy" }, + { "utm_source", "plugin_unity" }, + { "server_image", _localTestImageInput.value }, + { "docker_params", _localTestDockerRunInput.value }, + }; + try { hideResultLabels(); @@ -1429,6 +1530,8 @@ private async void OnLocalTestDeployClick() true ); _createAppFoldout.SetValueWithoutNotify(true); + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(properties); } catch (Exception e) { @@ -1444,6 +1547,10 @@ private async void OnLocalTestDeployClick() labelMsg = "There was an issue while deploying. See more in Docker Desktop or Docker CLI."; Debug.LogError($"OnLocalTestDeploy Error: {e}"); + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(properties); } OnLocalDeploymentResult(labelMsg, false); @@ -1452,6 +1559,15 @@ private async void OnLocalTestDeployClick() private async void OnLocalTestTerminateCLick() { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", "4. Test Locally > Terminate" }, + { "utm_source", "plugin_unity" }, + { "server_image", _localTestImageInput.value }, + { "docker_params", _localTestDockerRunInput.value }, + }; + try { hideResultLabels(); @@ -1463,6 +1579,8 @@ private async void OnLocalTestTerminateCLick() OnLocalDeploymentResult("Container terminated successfully.", true); _createAppFoldout.SetValueWithoutNotify(true); + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(properties); } catch (Exception e) { @@ -1477,6 +1595,10 @@ private async void OnLocalTestTerminateCLick() "There was an issue while terminating. See more in Docker Desktop or Docker CLI.", false ); + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(properties); } } } @@ -1593,8 +1715,25 @@ private void OnUploadImageCreateAppBtnClick() _ = UploadImageCreateAppAsync(); } - private async Task UploadImageCreateAppAsync() + private async Task UploadImageCreateAppAsync( + string buttonName = "5. Upload to Edgegap > Upload and Create App" + ) { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", buttonName }, + { "utm_source", "plugin_unity" }, + { "app_name", _createAppNameInput.value }, + { "image_name", _serverImageNameInput.value }, + { "image_tag", _serverImageTagInput.value }, + }; + + if (buttonName.Contains("Rebuild from Source")) + { + properties.Add("rebuild_step", "Upload and Create App"); + } + try { _uploadImageCreateAppBtn.SetEnabled(false); @@ -1634,6 +1773,9 @@ private async Task UploadImageCreateAppAsync() throw new Exception("Unable to push docker image to registry (see logs)."); } + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(properties); + ShowWorkInProgress("Create Application", "Updating server info on Edgegap"); if (IsLogLevelDebug) @@ -1693,6 +1835,11 @@ private async Task UploadImageCreateAppAsync() } catch (Exception e) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(properties); + if ( e.Message.Contains("Docker authorization failed") || e.Message.Contains("Unable to push docker image") @@ -1740,7 +1887,7 @@ private async void OnRebuildFromSrcBtnClickAsync() hideResultLabels(); //Build - OnBuildServerBtnClick(); + await BuildServer("5. Upload to Edgegap > Rebuild from Source"); if (_serverBuildResultLabel.text.Contains(EdgegapWindowMetadata.FAIL_COLOR_HEX)) { @@ -1754,7 +1901,7 @@ private async void OnRebuildFromSrcBtnClickAsync() _containerizeImageTagInput.SetValueWithoutNotify(_containerizeImageTagInputDefault); } - await ContainerizeServerAsync(); + await ContainerizeServerAsync("5. Upload to Edgegap > Rebuild from Source"); if ( _containerizeServerResultLabel.text.Contains(EdgegapWindowMetadata.FAIL_COLOR_HEX) @@ -1768,7 +1915,7 @@ private async void OnRebuildFromSrcBtnClickAsync() } //Upload - await UploadImageCreateAppAsync(); + await UploadImageCreateAppAsync("5. Upload to Edgegap > Rebuild from Source"); } #endregion @@ -1930,6 +2077,15 @@ private async void OnDeploymentCreateBtnClick() /// private async Task CreateDeploymentStartServer() { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", "6. Deploy > Start" }, + { "utm_source", "plugin_unity" }, + { "app_name", _deployAppNameInput.value }, + { "app_version", _deployAppVersionInput.value }, + }; + if (IsLogLevelDebug) Debug.Log("createDeploymentStartServerAsync"); @@ -1972,6 +2128,10 @@ private async Task CreateDeploymentStartServer() await deployApi.CreateDeploymentAsync(createDeploymentReq); if (!createDeploymentResponse.IsResultCode202) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", createDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(properties); + OnCreateDeploymentStartServerFail(createDeploymentResponse.Error.ErrorMessage); return; } @@ -2002,9 +2162,15 @@ await deployApi.AwaitReadyStatusAsync( EdgegapWindowMetadata.StatusColors.Success ); _deployResultLabel.style.display = DisplayStyle.Flex; + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(properties); } else { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", getDeploymentStatusResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(properties); + OnCreateDeploymentStartServerFail(getDeploymentStatusResponse.Error.ErrorMessage); } } @@ -2032,6 +2198,15 @@ private void OnCreateDeploymentStartServerFail(string message = null) /// private async void OnStopLastDeployClick() { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", "6. Deploy > Stop" }, + { "utm_source", "plugin_unity" }, + { "app_name", _deployAppNameInput.value }, + { "app_version", _deployAppVersionInput.value }, + }; + try { hideResultLabels(); @@ -2069,6 +2244,10 @@ private async void OnStopLastDeployClick() if (!stopDeploymentResponse.IsResultCode200) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(properties); + OnGetStopLastDeploymentResult(stopDeploymentResponse.Error.ErrorMessage, false); return; } @@ -2085,10 +2264,17 @@ private async void OnStopLastDeployClick() //Process response if (!stopDeploymentResponse.IsResultCode410) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(properties); + OnGetStopLastDeploymentResult(stopDeploymentResponse.Error.ErrorMessage, false); } else { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(properties); + OnGetStopLastDeploymentResult("Deployment stopped successfully", true); } @@ -2096,6 +2282,11 @@ private async void OnStopLastDeployClick() } catch (Exception e) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(properties); + OnGetStopLastDeploymentResult(e.Message, false); OpenEdgegapURL(EdgegapWindowMetadata.EDGEGAP_DEPLOY_APP_URL); } @@ -2559,6 +2750,13 @@ public static string Base64Decode(string base64EncodedText) return Encoding.UTF8.GetString(base64Bytes); } #endregion + + #region Utility / Analytics + private AnalyticsApi getAnalyticsApi() => new AnalyticsApi(getDistinctId()); + + //TODO - replace with hash + private string getDistinctId() => "marjorie.dudemaine@edgegap.com"; + #endregion } } From 65d89fc4f5c922779d21bfdfe126d781e276b4ca Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Mon, 19 Jan 2026 11:43:40 -0500 Subject: [PATCH 02/10] refactor analytics code --- Editor/EdgegapWindowV2.cs | 111 ++++++++++++++++++++++++-------------- 1 file changed, 72 insertions(+), 39 deletions(-) diff --git a/Editor/EdgegapWindowV2.cs b/Editor/EdgegapWindowV2.cs index 90b24cd..3d8bada 100644 --- a/Editor/EdgegapWindowV2.cs +++ b/Editor/EdgegapWindowV2.cs @@ -908,13 +908,12 @@ private async void OnSignOutBtnClickAsync() { "button_name", "1. Connect Edgegap Account > Sign out" }, { "utm_source", "plugin_unity" }, }; - string distinctId = getDistinctId(); + await analyticsApi.PostAsync(properties); EditorPrefs.DeleteKey(EdgegapWindowMetadata.API_TOKEN_KEY_STR); EditorPrefs.DeleteKey(EdgegapWindowMetadata.SELECTED_NETCODE_KEY_STR); _apiTokenInput.SetValueWithoutNotify(""); ResetState(); - await analyticsApi.PostAsync(properties); } /// @@ -1020,7 +1019,6 @@ private async Task BuildServer(string buttonName = "2. Build Game Server > Build { "button_name", buttonName }, { "utm_source", "plugin_unity" }, }; - if (buttonName.Contains("Rebuild from Source")) { properties.Add("rebuild_step", "Build"); @@ -1056,10 +1054,15 @@ private async Task BuildServer(string buttonName = "2. Build Game Server > Build if (buildResult.summary.result != BuildResult.Succeeded) { Debug.LogWarning(buildResult.summary.result.ToString()); + + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", buildResult.summary.result.ToString()); + await analyticsApi.PostAsync(properties); } else { OnBuildContainerizeUploadSuccess(_serverBuildResultLabel, "Build succeeded."); + properties.Add("succeeded", true.ToString()); await analyticsApi.PostAsync(properties); } @@ -1118,12 +1121,12 @@ private async Task ValidateDockerRequirement(bool runAnalytics) catch (Exception e) { error = e.Message; - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - + if (runAnalytics) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); await analyticsApi.PostAsync(properties); } } @@ -1162,10 +1165,10 @@ private async Task ValidateDockerRequirement(bool runAnalytics) _dockerRequirementsResultLabel, "Docker is running." ); - properties.Add("succeeded", true.ToString()); if (runAnalytics) { + properties.Add("succeeded", true.ToString()); await analyticsApi.PostAsync(properties); } } @@ -1293,22 +1296,20 @@ private async Task ContainerizeServerAsync( ) { AnalyticsApi analyticsApi = getAnalyticsApi(); - Dictionary properties = new Dictionary() - { - { "button_name", buttonName }, - { "utm_source", "plugin_unity" }, - { "docker_params", _optionalDockerParamsInput.value }, - }; - - if (buttonName.Contains("Rebuild from Source")) - { - properties.Add("rebuild_step", "Containerize"); - } - + if (!string.IsNullOrEmpty(await ValidateDockerRequirement(false))) { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", "Docker validation failed"); + Dictionary properties = new Dictionary() + { + { "button_name", buttonName }, + { "utm_source", "plugin_unity" }, + { "succeeded", false.ToString() }, + { "error_message", "Docker validation failed"} + }; + if (buttonName.Contains("Rebuild from Source")) + { + properties.Add("rebuild_step", "Containerize"); + } await analyticsApi.PostAsync(properties); return; @@ -1352,8 +1353,6 @@ private async Task ContainerizeServerAsync( _containerizeImageTagInput.value == _containerizeImageTagInputDefault ? nowUTC : _containerizeImageTagInput.value; - properties.Add("image_name", imageName); - properties.Add("image_tag", tag); await EdgegapBuildUtils.RunCommand_DockerBuild( dockerfilePath, @@ -1385,14 +1384,44 @@ await EdgegapBuildUtils.RunCommand_DockerBuild( _localTestImageShowDropdownBtn.SetEnabled(true); } - properties.Add("succeeded", true.ToString()); + Dictionary properties = new Dictionary() + { + { "button_name", buttonName }, + { "utm_source", "plugin_unity" }, + { "docker_params", _optionalDockerParamsInput.value }, + { "image_name", imageName }, + { "image_tag", tag }, + { "succeeded", true.ToString() } + }; + if (buttonName.Contains("Rebuild from Source")) + { + properties.Add("rebuild_step", "Containerize"); + } await analyticsApi.PostAsync(properties); } catch (Exception e) { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); + string imageName = Tokenize(_containerizeImageNameInput.value); + string tag = + _containerizeImageTagInput.value == _containerizeImageTagInputDefault + ? nowUTC + : _containerizeImageTagInput.value; + + Dictionary properties = new Dictionary() + { + { "button_name", buttonName }, + { "utm_source", "plugin_unity" }, + { "docker_params", _optionalDockerParamsInput.value }, + { "image_name", imageName }, + { "image_tag", tag }, + { "succeeded", false.ToString() }, + { "error_message", e.Message }, + { "stack_trace", e.StackTrace } + }; + if (buttonName.Contains("Rebuild from Source")) + { + properties.Add("rebuild_step", "Containerize"); + } await analyticsApi.PostAsync(properties); Debug.LogError($"Containerization Error: {e}"); @@ -1530,6 +1559,7 @@ private async void OnLocalTestDeployClick() true ); _createAppFoldout.SetValueWithoutNotify(true); + properties.Add("succeeded", true.ToString()); await analyticsApi.PostAsync(properties); } @@ -1547,6 +1577,7 @@ private async void OnLocalTestDeployClick() labelMsg = "There was an issue while deploying. See more in Docker Desktop or Docker CLI."; Debug.LogError($"OnLocalTestDeploy Error: {e}"); + properties.Add("succeeded", false.ToString()); properties.Add("error_message", e.Message); properties.Add("stack_trace", e.StackTrace); @@ -1577,8 +1608,8 @@ private async void OnLocalTestTerminateCLick() await EdgegapBuildUtils.RunCommand_DockerStop(); OnLocalDeploymentResult("Container terminated successfully.", true); - _createAppFoldout.SetValueWithoutNotify(true); + properties.Add("succeeded", true.ToString()); await analyticsApi.PostAsync(properties); } @@ -1595,6 +1626,7 @@ private async void OnLocalTestTerminateCLick() "There was an issue while terminating. See more in Docker Desktop or Docker CLI.", false ); + properties.Add("succeeded", false.ToString()); properties.Add("error_message", e.Message); properties.Add("stack_trace", e.StackTrace); @@ -1728,7 +1760,6 @@ private async Task UploadImageCreateAppAsync( { "image_name", _serverImageNameInput.value }, { "image_tag", _serverImageTagInput.value }, }; - if (buttonName.Contains("Rebuild from Source")) { properties.Add("rebuild_step", "Upload and Create App"); @@ -2077,15 +2108,6 @@ private async void OnDeploymentCreateBtnClick() /// private async Task CreateDeploymentStartServer() { - AnalyticsApi analyticsApi = getAnalyticsApi(); - Dictionary properties = new Dictionary() - { - { "button_name", "6. Deploy > Start" }, - { "utm_source", "plugin_unity" }, - { "app_name", _deployAppNameInput.value }, - { "app_version", _deployAppVersionInput.value }, - }; - if (IsLogLevelDebug) Debug.Log("createDeploymentStartServerAsync"); @@ -2126,6 +2148,16 @@ private async Task CreateDeploymentStartServer() // Request to deploy (it won't be active, yet) => EdgegapHttpResult createDeploymentResponse = await deployApi.CreateDeploymentAsync(createDeploymentReq); + + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "button_name", "6. Deploy > Start" }, + { "utm_source", "plugin_unity" }, + { "app_name", _deployAppNameInput.value }, + { "app_version", _deployAppVersionInput.value }, + }; + if (!createDeploymentResponse.IsResultCode202) { properties.Add("succeeded", false.ToString()); @@ -2162,6 +2194,7 @@ await deployApi.AwaitReadyStatusAsync( EdgegapWindowMetadata.StatusColors.Success ); _deployResultLabel.style.display = DisplayStyle.Flex; + properties.Add("succeeded", true.ToString()); await analyticsApi.PostAsync(properties); } From d6ae6760a2d389b1ca8b442546dab478c014653b Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Thu, 26 Mar 2026 16:11:53 -0400 Subject: [PATCH 03/10] update analytics integration; --- Editor/Api/AnalyticsApi.cs | 13 +- Editor/Api/EdgegapWizardApi.cs | 33 +- .../GetOrganizationInformationResult.cs | 19 + Editor/EdgegapWindowV2.cs | 346 ++++++++++++------ 4 files changed, 290 insertions(+), 121 deletions(-) create mode 100644 Editor/Api/Models/Results/GetOrganizationInformationResult.cs diff --git a/Editor/Api/AnalyticsApi.cs b/Editor/Api/AnalyticsApi.cs index 318cc0c..fb8fac2 100644 --- a/Editor/Api/AnalyticsApi.cs +++ b/Editor/Api/AnalyticsApi.cs @@ -12,10 +12,9 @@ namespace Edgegap.Editor.Api public class AnalyticsApi { private readonly HttpClient _httpClient = new HttpClient(); - private string _url = "https://us.i.posthog.com/i/v0/e/"; + private string _url = "https://r.edgegap.net/"; private string _Key = "phc_sjDOXB5OakYZu0h70u4GLcFR7hZ55XfnnDef5xaeDws"; private string _Event = "Plugin Button Click"; - private string _DistinctId; private class AnalyticsPayload { @@ -47,18 +46,20 @@ Dictionary properties public override string ToString() => JsonConvert.SerializeObject(this); } - public AnalyticsApi(string distinctId) + public AnalyticsApi() { this._httpClient.BaseAddress = new Uri(_url); this._httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json") ); - this._DistinctId = distinctId; } - public async Task PostAsync(Dictionary properties) + public async Task PostAsync( + string distinctId, + Dictionary properties + ) { - AnalyticsPayload payload = new AnalyticsPayload(_Key, _Event, _DistinctId, properties); + AnalyticsPayload payload = new AnalyticsPayload(_Key, _Event, distinctId, properties); StringContent stringContent = new StringContent( payload.ToString(), Encoding.UTF8, diff --git a/Editor/Api/EdgegapWizardApi.cs b/Editor/Api/EdgegapWizardApi.cs index 5d4a25f..3d71470 100644 --- a/Editor/Api/EdgegapWizardApi.cs +++ b/Editor/Api/EdgegapWizardApi.cs @@ -10,13 +10,11 @@ public class EdgegapWizardApi : EdgegapApiBase { /// Extended path after the base uri public EdgegapWizardApi( - ApiEnvironment apiEnvironment, - string apiToken, - EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error) - : base(apiEnvironment, apiToken, logLevel) - { - } - + ApiEnvironment apiEnvironment, + string apiToken, + EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error + ) + : base(apiEnvironment, apiToken, logLevel) { } #region API Methods /// POST to v1/wizard/init-quick-start @@ -32,7 +30,7 @@ public async Task InitQuickStart() return result; } - + /// GET to v1/wizard/registry-credentials /// /// - Http info with GetRegistryCredentialsResult data model @@ -43,7 +41,24 @@ public async Task InitQuickStart() public async Task> GetRegistryCredentials() { HttpResponseMessage response = await GetAsync("v1/wizard/registry-credentials"); - EdgegapHttpResult result = new EdgegapHttpResult(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020 + EdgegapHttpResult result = + new EdgegapHttpResult(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020 + + return result; + } + + /// GET to /v1/wizard/organization-information + /// + /// - Http info with GetOrganizationInformationResult data model + /// - Success: 200 + /// + public async Task< + EdgegapHttpResult + > GetOrganizationInformation() + { + HttpResponseMessage response = await GetAsync("/v1/wizard/organization-information"); + EdgegapHttpResult result = + new EdgegapHttpResult(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020 return result; } diff --git a/Editor/Api/Models/Results/GetOrganizationInformationResult.cs b/Editor/Api/Models/Results/GetOrganizationInformationResult.cs new file mode 100644 index 0000000..2b405da --- /dev/null +++ b/Editor/Api/Models/Results/GetOrganizationInformationResult.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; + +namespace Edgegap.Editor.Api.Models.Results +{ + /// + /// Result model for `GET /v1/wizard/organization-information`. + /// + public class GetOrganizationInformationResult + { + [JsonProperty("distinct_id")] + public string DistinctId { get; set; } + + [JsonProperty("identifier")] + public string Identifier { get; set; } + + [JsonProperty("provider")] + public string Provider { get; set; } + } +} diff --git a/Editor/EdgegapWindowV2.cs b/Editor/EdgegapWindowV2.cs index 3d8bada..c151b59 100644 --- a/Editor/EdgegapWindowV2.cs +++ b/Editor/EdgegapWindowV2.cs @@ -52,12 +52,14 @@ public class EdgegapWindowV2 : EditorWindow private string _containerProject; private string _containerUsername; private string _containerToken; + private GetOrganizationInformationResult _organizationInfo; private List _localImages = null; private List _storedAppNames = null; private List _storedAppVersions = null; EdgegapDeploymentsApi _deployAPI; + AnalyticsApi _analyticsApi; #endregion #region UI @@ -704,6 +706,7 @@ private void ResetState() _isApiTokenVerified = false; _credentials = null; + _organizationInfo = null; _userExternalIp = null; _containerRegistryUrl = null; _containerProject = null; @@ -862,6 +865,14 @@ private async Task verifyApiTokenGetRegistryCreds() _containerUsername = _credentials.Username; _containerToken = _credentials.Token; Debug.Log("Edgegap API token verified successfully."); + + EdgegapHttpResult getOrganizationInformationResult = + await wizardApi.GetOrganizationInformation(); + + if (getOrganizationInformationResult.IsResultCode200) + { + _organizationInfo = getOrganizationInformationResult.Data; + } } else { @@ -902,13 +913,18 @@ private async Task checkForUpdates() /// private async void OnSignOutBtnClickAsync() { - AnalyticsApi analyticsApi = getAnalyticsApi(); - Dictionary properties = new Dictionary() + if (_organizationInfo is not null) { - { "button_name", "1. Connect Edgegap Account > Sign out" }, - { "utm_source", "plugin_unity" }, - }; - await analyticsApi.PostAsync(properties); + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", "1. Connect Edgegap Account > Sign out" }, + { "utm_source", "plugin_unity" }, + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } EditorPrefs.DeleteKey(EdgegapWindowMetadata.API_TOKEN_KEY_STR); EditorPrefs.DeleteKey(EdgegapWindowMetadata.SELECTED_NETCODE_KEY_STR); @@ -977,13 +993,18 @@ private async void OnInstallLinuxBtnClick() /// private async void OnOpenBuildParamsBtnClick() { - AnalyticsApi analyticsApi = getAnalyticsApi(); - Dictionary properties = new Dictionary() + if (_organizationInfo is not null) { - { "button_name", "2. Build Game Server > Edit Settings" }, - { "utm_source", "plugin_unity" }, - }; - await analyticsApi.PostAsync(properties); + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", "2. Build Game Server > Edit Settings" }, + { "utm_source", "plugin_unity" }, + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } #if UNITY_2021_3_OR_NEWER EditorWindow.GetWindow( @@ -1023,6 +1044,11 @@ private async Task BuildServer(string buttonName = "2. Build Game Server > Build { properties.Add("rebuild_step", "Build"); } + if (_organizationInfo is not null) + { + properties.Add("identifier", _organizationInfo.Identifier); + properties.Add("provider", _organizationInfo.Provider); + } try { @@ -1055,16 +1081,22 @@ private async Task BuildServer(string buttonName = "2. Build Game Server > Build { Debug.LogWarning(buildResult.summary.result.ToString()); - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", buildResult.summary.result.ToString()); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", buildResult.summary.result.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } else { OnBuildContainerizeUploadSuccess(_serverBuildResultLabel, "Build succeeded."); - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } _containerizeFoldout.SetValueWithoutNotify(true); @@ -1072,10 +1104,13 @@ private async Task BuildServer(string buttonName = "2. Build Game Server > Build } catch (Exception e) { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } Debug.LogError($"OnBuildServerBtnClick Error: {e}"); ShowErrorDialog(e.Message, _serverBuildResultLabel, "Build failed (see logs)."); @@ -1108,6 +1143,11 @@ private async Task ValidateDockerRequirement(bool runAnalytics) { "button_name", "3. Containerize Server > Validate Docker" }, { "utm_source", "plugin_unity" }, }; + if (_organizationInfo is not null) + { + properties.Add("identifier", _organizationInfo.Identifier); + properties.Add("provider", _organizationInfo.Provider); + } _validateDockerRequirementsBtn.SetEnabled(false); hideResultLabels(); @@ -1121,13 +1161,13 @@ private async Task ValidateDockerRequirement(bool runAnalytics) catch (Exception e) { error = e.Message; - - if (runAnalytics) + + if (runAnalytics && _organizationInfo is not null) { properties.Add("succeeded", false.ToString()); properties.Add("error_message", e.Message); properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(properties); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } } _validateDockerRequirementsBtn.SetEnabled(true); @@ -1166,10 +1206,10 @@ private async Task ValidateDockerRequirement(bool runAnalytics) "Docker is running." ); - if (runAnalytics) + if (runAnalytics && _organizationInfo is not null) { properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(properties); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } } return null; @@ -1296,21 +1336,26 @@ private async Task ContainerizeServerAsync( ) { AnalyticsApi analyticsApi = getAnalyticsApi(); - + if (!string.IsNullOrEmpty(await ValidateDockerRequirement(false))) { - Dictionary properties = new Dictionary() - { - { "button_name", buttonName }, - { "utm_source", "plugin_unity" }, - { "succeeded", false.ToString() }, - { "error_message", "Docker validation failed"} - }; - if (buttonName.Contains("Rebuild from Source")) + if (_organizationInfo is not null) { - properties.Add("rebuild_step", "Containerize"); + Dictionary properties = new Dictionary() + { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", buttonName }, + { "utm_source", "plugin_unity" }, + { "succeeded", false.ToString() }, + { "error_message", "Docker validation failed" }, + }; + if (buttonName.Contains("Rebuild from Source")) + { + properties.Add("rebuild_step", "Containerize"); + } + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } - await analyticsApi.PostAsync(properties); return; } @@ -1384,20 +1429,25 @@ await EdgegapBuildUtils.RunCommand_DockerBuild( _localTestImageShowDropdownBtn.SetEnabled(true); } - Dictionary properties = new Dictionary() + if (_organizationInfo is not null) { - { "button_name", buttonName }, - { "utm_source", "plugin_unity" }, - { "docker_params", _optionalDockerParamsInput.value }, - { "image_name", imageName }, - { "image_tag", tag }, - { "succeeded", true.ToString() } - }; - if (buttonName.Contains("Rebuild from Source")) - { - properties.Add("rebuild_step", "Containerize"); + Dictionary properties = new Dictionary() + { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", buttonName }, + { "utm_source", "plugin_unity" }, + { "docker_params", _optionalDockerParamsInput.value }, + { "image_name", imageName }, + { "image_tag", tag }, + { "succeeded", true.ToString() }, + }; + if (buttonName.Contains("Rebuild from Source")) + { + properties.Add("rebuild_step", "Containerize"); + } + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } - await analyticsApi.PostAsync(properties); } catch (Exception e) { @@ -1407,22 +1457,27 @@ await EdgegapBuildUtils.RunCommand_DockerBuild( ? nowUTC : _containerizeImageTagInput.value; - Dictionary properties = new Dictionary() + if (_organizationInfo is not null) { - { "button_name", buttonName }, - { "utm_source", "plugin_unity" }, - { "docker_params", _optionalDockerParamsInput.value }, - { "image_name", imageName }, - { "image_tag", tag }, - { "succeeded", false.ToString() }, - { "error_message", e.Message }, - { "stack_trace", e.StackTrace } - }; - if (buttonName.Contains("Rebuild from Source")) - { - properties.Add("rebuild_step", "Containerize"); + Dictionary properties = new Dictionary() + { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", buttonName }, + { "utm_source", "plugin_unity" }, + { "docker_params", _optionalDockerParamsInput.value }, + { "image_name", imageName }, + { "image_tag", tag }, + { "succeeded", false.ToString() }, + { "error_message", e.Message }, + { "stack_trace", e.StackTrace }, + }; + if (buttonName.Contains("Rebuild from Source")) + { + properties.Add("rebuild_step", "Containerize"); + } + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } - await analyticsApi.PostAsync(properties); Debug.LogError($"Containerization Error: {e}"); ShowErrorDialog( @@ -1516,11 +1571,18 @@ private async void OnLocalTestDeployClick() AnalyticsApi analyticsApi = getAnalyticsApi(); Dictionary properties = new Dictionary() { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, { "button_name", "4. Test Locally > Deploy" }, { "utm_source", "plugin_unity" }, { "server_image", _localTestImageInput.value }, { "docker_params", _localTestDockerRunInput.value }, }; + if (_organizationInfo is not null) + { + properties.Add("identifier", _organizationInfo.Identifier); + properties.Add("provider", _organizationInfo.Provider); + } try { @@ -1560,8 +1622,11 @@ private async void OnLocalTestDeployClick() ); _createAppFoldout.SetValueWithoutNotify(true); - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } catch (Exception e) { @@ -1578,10 +1643,13 @@ private async void OnLocalTestDeployClick() "There was an issue while deploying. See more in Docker Desktop or Docker CLI."; Debug.LogError($"OnLocalTestDeploy Error: {e}"); - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } OnLocalDeploymentResult(labelMsg, false); @@ -1593,11 +1661,18 @@ private async void OnLocalTestTerminateCLick() AnalyticsApi analyticsApi = getAnalyticsApi(); Dictionary properties = new Dictionary() { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, { "button_name", "4. Test Locally > Terminate" }, { "utm_source", "plugin_unity" }, { "server_image", _localTestImageInput.value }, { "docker_params", _localTestDockerRunInput.value }, }; + if (_organizationInfo is not null) + { + properties.Add("identifier", _organizationInfo.Identifier); + properties.Add("provider", _organizationInfo.Provider); + } try { @@ -1610,8 +1685,11 @@ private async void OnLocalTestTerminateCLick() OnLocalDeploymentResult("Container terminated successfully.", true); _createAppFoldout.SetValueWithoutNotify(true); - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } catch (Exception e) { @@ -1627,10 +1705,13 @@ private async void OnLocalTestTerminateCLick() false ); - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } } } @@ -1754,6 +1835,8 @@ private async Task UploadImageCreateAppAsync( AnalyticsApi analyticsApi = getAnalyticsApi(); Dictionary properties = new Dictionary() { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, { "button_name", buttonName }, { "utm_source", "plugin_unity" }, { "app_name", _createAppNameInput.value }, @@ -1764,6 +1847,11 @@ private async Task UploadImageCreateAppAsync( { properties.Add("rebuild_step", "Upload and Create App"); } + if (_organizationInfo is not null) + { + properties.Add("identifier", _organizationInfo.Identifier); + properties.Add("provider", _organizationInfo.Provider); + } try { @@ -1804,8 +1892,11 @@ private async Task UploadImageCreateAppAsync( throw new Exception("Unable to push docker image to registry (see logs)."); } - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } ShowWorkInProgress("Create Application", "Updating server info on Edgegap"); @@ -1866,10 +1957,13 @@ private async Task UploadImageCreateAppAsync( } catch (Exception e) { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } if ( e.Message.Contains("Docker authorization failed") @@ -2148,21 +2242,31 @@ private async Task CreateDeploymentStartServer() // Request to deploy (it won't be active, yet) => EdgegapHttpResult createDeploymentResponse = await deployApi.CreateDeploymentAsync(createDeploymentReq); - + AnalyticsApi analyticsApi = getAnalyticsApi(); Dictionary properties = new Dictionary() { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, { "button_name", "6. Deploy > Start" }, { "utm_source", "plugin_unity" }, { "app_name", _deployAppNameInput.value }, { "app_version", _deployAppVersionInput.value }, }; - + if (_organizationInfo is not null) + { + properties.Add("identifier", _organizationInfo.Identifier); + properties.Add("provider", _organizationInfo.Provider); + } + if (!createDeploymentResponse.IsResultCode202) { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", createDeploymentResponse.Error.ErrorMessage); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", createDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } OnCreateDeploymentStartServerFail(createDeploymentResponse.Error.ErrorMessage); return; @@ -2195,14 +2299,20 @@ await deployApi.AwaitReadyStatusAsync( ); _deployResultLabel.style.display = DisplayStyle.Flex; - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } else { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", getDeploymentStatusResponse.Error.ErrorMessage); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", getDeploymentStatusResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } OnCreateDeploymentStartServerFail(getDeploymentStatusResponse.Error.ErrorMessage); } @@ -2234,11 +2344,18 @@ private async void OnStopLastDeployClick() AnalyticsApi analyticsApi = getAnalyticsApi(); Dictionary properties = new Dictionary() { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, { "button_name", "6. Deploy > Stop" }, { "utm_source", "plugin_unity" }, { "app_name", _deployAppNameInput.value }, { "app_version", _deployAppVersionInput.value }, }; + if (_organizationInfo is not null) + { + properties.Add("identifier", _organizationInfo.Identifier); + properties.Add("provider", _organizationInfo.Provider); + } try { @@ -2277,9 +2394,12 @@ private async void OnStopLastDeployClick() if (!stopDeploymentResponse.IsResultCode200) { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } OnGetStopLastDeploymentResult(stopDeploymentResponse.Error.ErrorMessage, false); return; @@ -2297,16 +2417,22 @@ private async void OnStopLastDeployClick() //Process response if (!stopDeploymentResponse.IsResultCode410) { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } OnGetStopLastDeploymentResult(stopDeploymentResponse.Error.ErrorMessage, false); } else { - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } OnGetStopLastDeploymentResult("Deployment stopped successfully", true); } @@ -2315,10 +2441,13 @@ private async void OnStopLastDeployClick() } catch (Exception e) { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(properties); + if (_organizationInfo is not null) + { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } OnGetStopLastDeploymentResult(e.Message, false); OpenEdgegapURL(EdgegapWindowMetadata.EDGEGAP_DEPLOY_APP_URL); @@ -2785,10 +2914,15 @@ public static string Base64Decode(string base64EncodedText) #endregion #region Utility / Analytics - private AnalyticsApi getAnalyticsApi() => new AnalyticsApi(getDistinctId()); + private AnalyticsApi getAnalyticsApi() + { + if (_analyticsApi is null) + { + _analyticsApi = new AnalyticsApi(); + } - //TODO - replace with hash - private string getDistinctId() => "marjorie.dudemaine@edgegap.com"; + return _analyticsApi; + } #endregion } } From 1b5933f33a1cbe43b0e8d5238095015646e0785b Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Fri, 27 Mar 2026 09:04:00 -0400 Subject: [PATCH 04/10] use metadata default tag --- Editor/EdgegapWindowMetadata.cs | 2 +- Editor/EdgegapWindowV2.cs | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Editor/EdgegapWindowMetadata.cs b/Editor/EdgegapWindowMetadata.cs index 8745302..3f7ce1c 100644 --- a/Editor/EdgegapWindowMetadata.cs +++ b/Editor/EdgegapWindowMetadata.cs @@ -84,7 +84,7 @@ public enum LogLevel public const string EDGEGAP_DOC_MATCHMAKER_PATH = "learn/matchmaking/getting-started"; public const string SCALING_LIFECYCLE_INFO_URL = "learn/advanced-features/deployments"; - private const string DEFAULT_UTM_SOURCE_TAG = "plugin_unity"; + public const string DEFAULT_UTM_SOURCE_TAG = "plugin_unity"; private const string DEFAULT_UTM_MEDIUM_TAG = "servers_quickstart_plugin"; private const string DEFAULT_UTM_CONTENT_TAG = "plugin_button"; public const string DEFAULT_UTM_TAGS = diff --git a/Editor/EdgegapWindowV2.cs b/Editor/EdgegapWindowV2.cs index c151b59..3544d26 100644 --- a/Editor/EdgegapWindowV2.cs +++ b/Editor/EdgegapWindowV2.cs @@ -921,7 +921,7 @@ private async void OnSignOutBtnClickAsync() { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", "1. Connect Edgegap Account > Sign out" }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, }; await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } @@ -1001,7 +1001,7 @@ private async void OnOpenBuildParamsBtnClick() { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", "2. Build Game Server > Edit Settings" }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, }; await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } @@ -1038,7 +1038,7 @@ private async Task BuildServer(string buttonName = "2. Build Game Server > Build Dictionary properties = new Dictionary() { { "button_name", buttonName }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, }; if (buttonName.Contains("Rebuild from Source")) { @@ -1141,7 +1141,7 @@ private async Task ValidateDockerRequirement(bool runAnalytics) Dictionary properties = new Dictionary() { { "button_name", "3. Containerize Server > Validate Docker" }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, }; if (_organizationInfo is not null) { @@ -1346,7 +1346,7 @@ private async Task ContainerizeServerAsync( { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", buttonName }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "succeeded", false.ToString() }, { "error_message", "Docker validation failed" }, }; @@ -1436,7 +1436,7 @@ await EdgegapBuildUtils.RunCommand_DockerBuild( { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", buttonName }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "docker_params", _optionalDockerParamsInput.value }, { "image_name", imageName }, { "image_tag", tag }, @@ -1464,7 +1464,7 @@ await EdgegapBuildUtils.RunCommand_DockerBuild( { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", buttonName }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "docker_params", _optionalDockerParamsInput.value }, { "image_name", imageName }, { "image_tag", tag }, @@ -1574,7 +1574,7 @@ private async void OnLocalTestDeployClick() { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", "4. Test Locally > Deploy" }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "server_image", _localTestImageInput.value }, { "docker_params", _localTestDockerRunInput.value }, }; @@ -1664,7 +1664,7 @@ private async void OnLocalTestTerminateCLick() { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", "4. Test Locally > Terminate" }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "server_image", _localTestImageInput.value }, { "docker_params", _localTestDockerRunInput.value }, }; @@ -1838,7 +1838,7 @@ private async Task UploadImageCreateAppAsync( { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", buttonName }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "app_name", _createAppNameInput.value }, { "image_name", _serverImageNameInput.value }, { "image_tag", _serverImageTagInput.value }, @@ -2249,7 +2249,7 @@ private async Task CreateDeploymentStartServer() { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", "6. Deploy > Start" }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "app_name", _deployAppNameInput.value }, { "app_version", _deployAppVersionInput.value }, }; @@ -2347,7 +2347,7 @@ private async void OnStopLastDeployClick() { "identifier", _organizationInfo.Identifier }, { "provider", _organizationInfo.Provider }, { "button_name", "6. Deploy > Stop" }, - { "utm_source", "plugin_unity" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "app_name", _deployAppNameInput.value }, { "app_version", _deployAppVersionInput.value }, }; From 4e55ff5afc2e9c3b7b19bfae01ef5c4deb40bd69 Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:15:09 -0400 Subject: [PATCH 05/10] 2nd round review --- Editor/EdgegapWindowV2.cs | 362 +++++++++++++------------------------- 1 file changed, 126 insertions(+), 236 deletions(-) diff --git a/Editor/EdgegapWindowV2.cs b/Editor/EdgegapWindowV2.cs index 3544d26..99ccae9 100644 --- a/Editor/EdgegapWindowV2.cs +++ b/Editor/EdgegapWindowV2.cs @@ -872,6 +872,7 @@ private async Task verifyApiTokenGetRegistryCreds() if (getOrganizationInformationResult.IsResultCode200) { _organizationInfo = getOrganizationInformationResult.Data; + Debug.Log($"DistincId: {_organizationInfo.DistinctId}"); //TODO remove after testing } } else @@ -913,18 +914,15 @@ private async Task checkForUpdates() /// private async void OnSignOutBtnClickAsync() { - if (_organizationInfo is not null) + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() { - AnalyticsApi analyticsApi = getAnalyticsApi(); - Dictionary properties = new Dictionary() - { - { "identifier", _organizationInfo.Identifier }, - { "provider", _organizationInfo.Provider }, - { "button_name", "1. Connect Edgegap Account > Sign out" }, - { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, - }; - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", "1. Connect Edgegap Account > Sign out" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); EditorPrefs.DeleteKey(EdgegapWindowMetadata.API_TOKEN_KEY_STR); EditorPrefs.DeleteKey(EdgegapWindowMetadata.SELECTED_NETCODE_KEY_STR); @@ -993,18 +991,15 @@ private async void OnInstallLinuxBtnClick() /// private async void OnOpenBuildParamsBtnClick() { - if (_organizationInfo is not null) + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() { - AnalyticsApi analyticsApi = getAnalyticsApi(); - Dictionary properties = new Dictionary() - { - { "identifier", _organizationInfo.Identifier }, - { "provider", _organizationInfo.Provider }, - { "button_name", "2. Build Game Server > Edit Settings" }, - { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, - }; - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", "2. Build Game Server > Edit Settings" }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); #if UNITY_2021_3_OR_NEWER EditorWindow.GetWindow( @@ -1039,16 +1034,9 @@ private async Task BuildServer(string buttonName = "2. Build Game Server > Build { { "button_name", buttonName }, { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, }; - if (buttonName.Contains("Rebuild from Source")) - { - properties.Add("rebuild_step", "Build"); - } - if (_organizationInfo is not null) - { - properties.Add("identifier", _organizationInfo.Identifier); - properties.Add("provider", _organizationInfo.Provider); - } try { @@ -1081,22 +1069,16 @@ private async Task BuildServer(string buttonName = "2. Build Game Server > Build { Debug.LogWarning(buildResult.summary.result.ToString()); - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", buildResult.summary.result.ToString()); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", buildResult.summary.result.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } else { OnBuildContainerizeUploadSuccess(_serverBuildResultLabel, "Build succeeded."); - if (_organizationInfo is not null) - { - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } _containerizeFoldout.SetValueWithoutNotify(true); @@ -1104,13 +1086,10 @@ private async Task BuildServer(string buttonName = "2. Build Game Server > Build } catch (Exception e) { - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); Debug.LogError($"OnBuildServerBtnClick Error: {e}"); ShowErrorDialog(e.Message, _serverBuildResultLabel, "Build failed (see logs)."); @@ -1142,12 +1121,9 @@ private async Task ValidateDockerRequirement(bool runAnalytics) { { "button_name", "3. Containerize Server > Validate Docker" }, { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, }; - if (_organizationInfo is not null) - { - properties.Add("identifier", _organizationInfo.Identifier); - properties.Add("provider", _organizationInfo.Provider); - } _validateDockerRequirementsBtn.SetEnabled(false); hideResultLabels(); @@ -1162,13 +1138,10 @@ private async Task ValidateDockerRequirement(bool runAnalytics) { error = e.Message; - if (runAnalytics && _organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } _validateDockerRequirementsBtn.SetEnabled(true); @@ -1206,11 +1179,8 @@ private async Task ValidateDockerRequirement(bool runAnalytics) "Docker is running." ); - if (runAnalytics && _organizationInfo is not null) - { - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } return null; } @@ -1336,26 +1306,20 @@ private async Task ContainerizeServerAsync( ) { AnalyticsApi analyticsApi = getAnalyticsApi(); + string validateDockerError = await ValidateDockerRequirement(false); - if (!string.IsNullOrEmpty(await ValidateDockerRequirement(false))) + if (!string.IsNullOrEmpty(validateDockerError)) { - if (_organizationInfo is not null) + Dictionary properties = new Dictionary() { - Dictionary properties = new Dictionary() - { - { "identifier", _organizationInfo.Identifier }, - { "provider", _organizationInfo.Provider }, - { "button_name", buttonName }, - { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, - { "succeeded", false.ToString() }, - { "error_message", "Docker validation failed" }, - }; - if (buttonName.Contains("Rebuild from Source")) - { - properties.Add("rebuild_step", "Containerize"); - } - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", buttonName }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "succeeded", false.ToString() }, + { "error_message", $"Docker validation failed: {validateDockerError}" }, //TODO test + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); return; } @@ -1429,25 +1393,18 @@ await EdgegapBuildUtils.RunCommand_DockerBuild( _localTestImageShowDropdownBtn.SetEnabled(true); } - if (_organizationInfo is not null) + Dictionary properties = new Dictionary() { - Dictionary properties = new Dictionary() - { - { "identifier", _organizationInfo.Identifier }, - { "provider", _organizationInfo.Provider }, - { "button_name", buttonName }, - { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, - { "docker_params", _optionalDockerParamsInput.value }, - { "image_name", imageName }, - { "image_tag", tag }, - { "succeeded", true.ToString() }, - }; - if (buttonName.Contains("Rebuild from Source")) - { - properties.Add("rebuild_step", "Containerize"); - } - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", buttonName }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "docker_params", _optionalDockerParamsInput.value }, + { "image_name", imageName }, + { "image_tag", tag }, + { "succeeded", true.ToString() }, + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } catch (Exception e) { @@ -1457,27 +1414,20 @@ await EdgegapBuildUtils.RunCommand_DockerBuild( ? nowUTC : _containerizeImageTagInput.value; - if (_organizationInfo is not null) + Dictionary properties = new Dictionary() { - Dictionary properties = new Dictionary() - { - { "identifier", _organizationInfo.Identifier }, - { "provider", _organizationInfo.Provider }, - { "button_name", buttonName }, - { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, - { "docker_params", _optionalDockerParamsInput.value }, - { "image_name", imageName }, - { "image_tag", tag }, - { "succeeded", false.ToString() }, - { "error_message", e.Message }, - { "stack_trace", e.StackTrace }, - }; - if (buttonName.Contains("Rebuild from Source")) - { - properties.Add("rebuild_step", "Containerize"); - } - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", buttonName }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "docker_params", _optionalDockerParamsInput.value }, + { "image_name", imageName }, + { "image_tag", tag }, + { "succeeded", false.ToString() }, + { "error_message", e.Message }, + { "stack_trace", e.StackTrace }, + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); Debug.LogError($"Containerization Error: {e}"); ShowErrorDialog( @@ -1577,12 +1527,9 @@ private async void OnLocalTestDeployClick() { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "server_image", _localTestImageInput.value }, { "docker_params", _localTestDockerRunInput.value }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, }; - if (_organizationInfo is not null) - { - properties.Add("identifier", _organizationInfo.Identifier); - properties.Add("provider", _organizationInfo.Provider); - } try { @@ -1622,11 +1569,8 @@ private async void OnLocalTestDeployClick() ); _createAppFoldout.SetValueWithoutNotify(true); - if (_organizationInfo is not null) - { - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } catch (Exception e) { @@ -1643,13 +1587,10 @@ private async void OnLocalTestDeployClick() "There was an issue while deploying. See more in Docker Desktop or Docker CLI."; Debug.LogError($"OnLocalTestDeploy Error: {e}"); - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } OnLocalDeploymentResult(labelMsg, false); @@ -1661,18 +1602,13 @@ private async void OnLocalTestTerminateCLick() AnalyticsApi analyticsApi = getAnalyticsApi(); Dictionary properties = new Dictionary() { - { "identifier", _organizationInfo.Identifier }, - { "provider", _organizationInfo.Provider }, { "button_name", "4. Test Locally > Terminate" }, { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "server_image", _localTestImageInput.value }, { "docker_params", _localTestDockerRunInput.value }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, }; - if (_organizationInfo is not null) - { - properties.Add("identifier", _organizationInfo.Identifier); - properties.Add("provider", _organizationInfo.Provider); - } try { @@ -1685,11 +1621,8 @@ private async void OnLocalTestTerminateCLick() OnLocalDeploymentResult("Container terminated successfully.", true); _createAppFoldout.SetValueWithoutNotify(true); - if (_organizationInfo is not null) - { - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } catch (Exception e) { @@ -1705,13 +1638,10 @@ private async void OnLocalTestTerminateCLick() false ); - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } } } @@ -1842,16 +1772,9 @@ private async Task UploadImageCreateAppAsync( { "app_name", _createAppNameInput.value }, { "image_name", _serverImageNameInput.value }, { "image_tag", _serverImageTagInput.value }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, }; - if (buttonName.Contains("Rebuild from Source")) - { - properties.Add("rebuild_step", "Upload and Create App"); - } - if (_organizationInfo is not null) - { - properties.Add("identifier", _organizationInfo.Identifier); - properties.Add("provider", _organizationInfo.Provider); - } try { @@ -1892,11 +1815,8 @@ private async Task UploadImageCreateAppAsync( throw new Exception("Unable to push docker image to registry (see logs)."); } - if (_organizationInfo is not null) - { - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); ShowWorkInProgress("Create Application", "Updating server info on Edgegap"); @@ -1957,13 +1877,10 @@ private async Task UploadImageCreateAppAsync( } catch (Exception e) { - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); if ( e.Message.Contains("Docker authorization failed") @@ -2012,7 +1929,7 @@ private async void OnRebuildFromSrcBtnClickAsync() hideResultLabels(); //Build - await BuildServer("5. Upload to Edgegap > Rebuild from Source"); + await BuildServer("5. Upload to Edgegap > Rebuild from Source > Build"); if (_serverBuildResultLabel.text.Contains(EdgegapWindowMetadata.FAIL_COLOR_HEX)) { @@ -2026,7 +1943,9 @@ private async void OnRebuildFromSrcBtnClickAsync() _containerizeImageTagInput.SetValueWithoutNotify(_containerizeImageTagInputDefault); } - await ContainerizeServerAsync("5. Upload to Edgegap > Rebuild from Source"); + await ContainerizeServerAsync( + "5. Upload to Edgegap > Rebuild from Source > Containerize" + ); if ( _containerizeServerResultLabel.text.Contains(EdgegapWindowMetadata.FAIL_COLOR_HEX) @@ -2040,7 +1959,9 @@ private async void OnRebuildFromSrcBtnClickAsync() } //Upload - await UploadImageCreateAppAsync("5. Upload to Edgegap > Rebuild from Source"); + await UploadImageCreateAppAsync( + "5. Upload to Edgegap > Rebuild from Source > Upload and Create App" + ); } #endregion @@ -2246,27 +2167,19 @@ private async Task CreateDeploymentStartServer() AnalyticsApi analyticsApi = getAnalyticsApi(); Dictionary properties = new Dictionary() { - { "identifier", _organizationInfo.Identifier }, - { "provider", _organizationInfo.Provider }, { "button_name", "6. Deploy > Start" }, { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "app_name", _deployAppNameInput.value }, { "app_version", _deployAppVersionInput.value }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, }; - if (_organizationInfo is not null) - { - properties.Add("identifier", _organizationInfo.Identifier); - properties.Add("provider", _organizationInfo.Provider); - } if (!createDeploymentResponse.IsResultCode202) { - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", createDeploymentResponse.Error.ErrorMessage); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", createDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); OnCreateDeploymentStartServerFail(createDeploymentResponse.Error.ErrorMessage); return; @@ -2299,20 +2212,14 @@ await deployApi.AwaitReadyStatusAsync( ); _deployResultLabel.style.display = DisplayStyle.Flex; - if (_organizationInfo is not null) - { - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } else { - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", getDeploymentStatusResponse.Error.ErrorMessage); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", getDeploymentStatusResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); OnCreateDeploymentStartServerFail(getDeploymentStatusResponse.Error.ErrorMessage); } @@ -2344,18 +2251,13 @@ private async void OnStopLastDeployClick() AnalyticsApi analyticsApi = getAnalyticsApi(); Dictionary properties = new Dictionary() { - { "identifier", _organizationInfo.Identifier }, - { "provider", _organizationInfo.Provider }, { "button_name", "6. Deploy > Stop" }, { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "app_name", _deployAppNameInput.value }, { "app_version", _deployAppVersionInput.value }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, }; - if (_organizationInfo is not null) - { - properties.Add("identifier", _organizationInfo.Identifier); - properties.Add("provider", _organizationInfo.Provider); - } try { @@ -2394,12 +2296,9 @@ private async void OnStopLastDeployClick() if (!stopDeploymentResponse.IsResultCode200) { - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); OnGetStopLastDeploymentResult(stopDeploymentResponse.Error.ErrorMessage, false); return; @@ -2417,22 +2316,16 @@ private async void OnStopLastDeployClick() //Process response if (!stopDeploymentResponse.IsResultCode410) { - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); OnGetStopLastDeploymentResult(stopDeploymentResponse.Error.ErrorMessage, false); } else { - if (_organizationInfo is not null) - { - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); OnGetStopLastDeploymentResult("Deployment stopped successfully", true); } @@ -2441,13 +2334,10 @@ private async void OnStopLastDeployClick() } catch (Exception e) { - if (_organizationInfo is not null) - { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); - } + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); OnGetStopLastDeploymentResult(e.Message, false); OpenEdgegapURL(EdgegapWindowMetadata.EDGEGAP_DEPLOY_APP_URL); From 21574de492645cdb6d606fe0b5252810c7b4c2c2 Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:24:41 -0400 Subject: [PATCH 06/10] missing meta --- .../Api/Models/Results/GetOrganizationInformationResult.cs.meta | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Editor/Api/Models/Results/GetOrganizationInformationResult.cs.meta diff --git a/Editor/Api/Models/Results/GetOrganizationInformationResult.cs.meta b/Editor/Api/Models/Results/GetOrganizationInformationResult.cs.meta new file mode 100644 index 0000000..40269e0 --- /dev/null +++ b/Editor/Api/Models/Results/GetOrganizationInformationResult.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 94627fefb00c12046aa52fcf096c115e \ No newline at end of file From 94ca54f6c2147bb7719ffc6259856e73ace027ba Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:59:38 -0400 Subject: [PATCH 07/10] missing conditional check --- Editor/EdgegapWindowV2.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Editor/EdgegapWindowV2.cs b/Editor/EdgegapWindowV2.cs index 99ccae9..1a218b3 100644 --- a/Editor/EdgegapWindowV2.cs +++ b/Editor/EdgegapWindowV2.cs @@ -872,7 +872,6 @@ private async Task verifyApiTokenGetRegistryCreds() if (getOrganizationInformationResult.IsResultCode200) { _organizationInfo = getOrganizationInformationResult.Data; - Debug.Log($"DistincId: {_organizationInfo.DistinctId}"); //TODO remove after testing } } else @@ -1138,10 +1137,12 @@ private async Task ValidateDockerRequirement(bool runAnalytics) { error = e.Message; - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); - properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + if (runAnalytics) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", e.Message); + properties.Add("stack_trace", e.StackTrace); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } _validateDockerRequirementsBtn.SetEnabled(true); @@ -1179,8 +1180,10 @@ private async Task ValidateDockerRequirement(bool runAnalytics) "Docker is running." ); - properties.Add("succeeded", true.ToString()); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + if (runAnalytics) { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } return null; } @@ -1317,7 +1320,7 @@ private async Task ContainerizeServerAsync( { "button_name", buttonName }, { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, { "succeeded", false.ToString() }, - { "error_message", $"Docker validation failed: {validateDockerError}" }, //TODO test + { "error_message", $"Docker validation failed: {validateDockerError}" }, }; await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); From 25de4797d0b73c2543185d11a5012fb0791d11ff Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Mon, 13 Apr 2026 07:25:49 -0400 Subject: [PATCH 08/10] url fix --- Editor/Api/AnalyticsApi.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Editor/Api/AnalyticsApi.cs b/Editor/Api/AnalyticsApi.cs index fb8fac2..b436362 100644 --- a/Editor/Api/AnalyticsApi.cs +++ b/Editor/Api/AnalyticsApi.cs @@ -12,7 +12,7 @@ namespace Edgegap.Editor.Api public class AnalyticsApi { private readonly HttpClient _httpClient = new HttpClient(); - private string _url = "https://r.edgegap.net/"; + private string _url = "https://r.edgegap.net/i/v0/e/"; private string _Key = "phc_sjDOXB5OakYZu0h70u4GLcFR7hZ55XfnnDef5xaeDws"; private string _Event = "Plugin Button Click"; From 4ffbc17682703a02e3af306fdeeca02fc4386bf5 Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Mon, 13 Apr 2026 07:51:04 -0400 Subject: [PATCH 09/10] add docker validation check --- Editor/EdgegapBuildUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Editor/EdgegapBuildUtils.cs b/Editor/EdgegapBuildUtils.cs index 8dcfad6..2121a6d 100644 --- a/Editor/EdgegapBuildUtils.cs +++ b/Editor/EdgegapBuildUtils.cs @@ -79,7 +79,7 @@ await RunCommand_DockerVersion(msg => output = msg, await RunCommand_DockerPS(null, (msg) => { - if (msg.ToLowerInvariant().Contains("error") || msg.ToLowerInvariant().Contains("invalid")) + if (msg.ToLowerInvariant().Contains("error") || msg.ToLowerInvariant().Contains("invalid") || msg.ToLowerInvariant().Contains("failed to connect")) { error = msg; } From 8d11dea8deb633da5ad695a405ce6d3192ba9919 Mon Sep 17 00:00:00 2001 From: edge-marge <141053702+edge-marge@users.noreply.github.com> Date: Mon, 13 Apr 2026 08:01:35 -0400 Subject: [PATCH 10/10] edit docker analytics --- Editor/EdgegapWindowV2.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Editor/EdgegapWindowV2.cs b/Editor/EdgegapWindowV2.cs index 1a218b3..57b8ab4 100644 --- a/Editor/EdgegapWindowV2.cs +++ b/Editor/EdgegapWindowV2.cs @@ -1136,18 +1136,21 @@ private async Task ValidateDockerRequirement(bool runAnalytics) catch (Exception e) { error = e.Message; - + if (runAnalytics) { - properties.Add("succeeded", false.ToString()); - properties.Add("error_message", e.Message); properties.Add("stack_trace", e.StackTrace); - await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } } _validateDockerRequirementsBtn.SetEnabled(true); if (!string.IsNullOrEmpty(error)) { + if (runAnalytics) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", error); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } + ShowErrorDialog( error.Contains("docker daemon is not running") || error.Contains("dockerDesktop")