diff --git a/Editor/Api/AnalyticsApi.cs b/Editor/Api/AnalyticsApi.cs new file mode 100644 index 0000000..b436362 --- /dev/null +++ b/Editor/Api/AnalyticsApi.cs @@ -0,0 +1,80 @@ +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://r.edgegap.net/i/v0/e/"; + private string _Key = "phc_sjDOXB5OakYZu0h70u4GLcFR7hZ55XfnnDef5xaeDws"; + private string _Event = "Plugin Button Click"; + + 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() + { + this._httpClient.BaseAddress = new Uri(_url); + this._httpClient.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/json") + ); + } + + public async Task PostAsync( + string distinctId, + 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/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/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 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; } 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 d5b9a2e..57b8ab4 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 { @@ -900,8 +911,18 @@ private async Task checkForUpdates() /// /// "Sign out" btn click /// - private void OnSignOutBtnClickAsync() + private async void OnSignOutBtnClickAsync() { + 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); + EditorPrefs.DeleteKey(EdgegapWindowMetadata.API_TOKEN_KEY_STR); EditorPrefs.DeleteKey(EdgegapWindowMetadata.SELECTED_NETCODE_KEY_STR); _apiTokenInput.SetValueWithoutNotify(""); @@ -967,8 +988,18 @@ private async void OnInstallLinuxBtnClick() /// /// Open Unity build settings btn click /// - private void OnOpenBuildParamsBtnClick() + private async void OnOpenBuildParamsBtnClick() { + 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); + #if UNITY_2021_3_OR_NEWER EditorWindow.GetWindow( System.Type.GetType("UnityEditor.BuildPlayerWindow,UnityEditor") @@ -992,6 +1023,20 @@ 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", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + }; + try { _serverBuildBtn.SetEnabled(false); @@ -1022,10 +1067,17 @@ private void OnBuildServerBtnClick() 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(_organizationInfo.DistinctId, properties); } else { OnBuildContainerizeUploadSuccess(_serverBuildResultLabel, "Build succeeded."); + + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } _containerizeFoldout.SetValueWithoutNotify(true); @@ -1033,6 +1085,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(_organizationInfo.DistinctId, properties); + Debug.LogError($"OnBuildServerBtnClick Error: {e}"); ShowErrorDialog(e.Message, _serverBuildResultLabel, "Build failed (see logs)."); } @@ -1053,11 +1110,20 @@ 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", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + }; + _validateDockerRequirementsBtn.SetEnabled(false); hideResultLabels(); string error; @@ -1070,11 +1136,21 @@ private async Task ValidateDockerRequirement() catch (Exception e) { error = e.Message; + + if (runAnalytics) { + properties.Add("stack_trace", e.StackTrace); + } } _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") @@ -1097,6 +1173,7 @@ private async Task ValidateDockerRequirement() _dockerRequirementsResultLabel, "There was a problem." ); + return error; } else @@ -1105,6 +1182,11 @@ private async Task ValidateDockerRequirement() _dockerRequirementsResultLabel, "Docker is running." ); + + if (runAnalytics) { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + } } return null; } @@ -1225,10 +1307,26 @@ 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(); + string validateDockerError = await ValidateDockerRequirement(false); + + if (!string.IsNullOrEmpty(validateDockerError)) { + 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: {validateDockerError}" }, + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + return; } try @@ -1300,9 +1398,43 @@ await EdgegapBuildUtils.RunCommand_DockerBuild( { _localTestImageShowDropdownBtn.SetEnabled(true); } + + 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() }, + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } catch (Exception e) { + string imageName = Tokenize(_containerizeImageNameInput.value); + string tag = + _containerizeImageTagInput.value == _containerizeImageTagInputDefault + ? nowUTC + : _containerizeImageTagInput.value; + + 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 }, + }; + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + Debug.LogError($"Containerization Error: {e}"); ShowErrorDialog( e.Message, @@ -1392,6 +1524,19 @@ private bool CheckFilledLocalTestInputs() 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", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "server_image", _localTestImageInput.value }, + { "docker_params", _localTestDockerRunInput.value }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + }; + try { hideResultLabels(); @@ -1429,6 +1574,9 @@ private async void OnLocalTestDeployClick() true ); _createAppFoldout.SetValueWithoutNotify(true); + + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } catch (Exception e) { @@ -1444,6 +1592,11 @@ 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(_organizationInfo.DistinctId, properties); } OnLocalDeploymentResult(labelMsg, false); @@ -1452,6 +1605,17 @@ private async void OnLocalTestDeployClick() private async void OnLocalTestTerminateCLick() { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "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 }, + }; + try { hideResultLabels(); @@ -1461,8 +1625,10 @@ private async void OnLocalTestTerminateCLick() await EdgegapBuildUtils.RunCommand_DockerStop(); OnLocalDeploymentResult("Container terminated successfully.", true); - _createAppFoldout.SetValueWithoutNotify(true); + + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); } catch (Exception e) { @@ -1477,6 +1643,11 @@ 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(_organizationInfo.DistinctId, properties); } } } @@ -1593,8 +1764,24 @@ 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() + { + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + { "button_name", buttonName }, + { "utm_source", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "app_name", _createAppNameInput.value }, + { "image_name", _serverImageNameInput.value }, + { "image_tag", _serverImageTagInput.value }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + }; + try { _uploadImageCreateAppBtn.SetEnabled(false); @@ -1634,6 +1821,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(_organizationInfo.DistinctId, properties); + ShowWorkInProgress("Create Application", "Updating server info on Edgegap"); if (IsLogLevelDebug) @@ -1693,6 +1883,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(_organizationInfo.DistinctId, properties); + if ( e.Message.Contains("Docker authorization failed") || e.Message.Contains("Unable to push docker image") @@ -1740,7 +1935,7 @@ private async void OnRebuildFromSrcBtnClickAsync() hideResultLabels(); //Build - OnBuildServerBtnClick(); + await BuildServer("5. Upload to Edgegap > Rebuild from Source > Build"); if (_serverBuildResultLabel.text.Contains(EdgegapWindowMetadata.FAIL_COLOR_HEX)) { @@ -1754,7 +1949,9 @@ private async void OnRebuildFromSrcBtnClickAsync() _containerizeImageTagInput.SetValueWithoutNotify(_containerizeImageTagInputDefault); } - await ContainerizeServerAsync(); + await ContainerizeServerAsync( + "5. Upload to Edgegap > Rebuild from Source > Containerize" + ); if ( _containerizeServerResultLabel.text.Contains(EdgegapWindowMetadata.FAIL_COLOR_HEX) @@ -1768,7 +1965,9 @@ private async void OnRebuildFromSrcBtnClickAsync() } //Upload - await UploadImageCreateAppAsync(); + await UploadImageCreateAppAsync( + "5. Upload to Edgegap > Rebuild from Source > Upload and Create App" + ); } #endregion @@ -1970,8 +2169,24 @@ 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", EdgegapWindowMetadata.DEFAULT_UTM_SOURCE_TAG }, + { "app_name", _deployAppNameInput.value }, + { "app_version", _deployAppVersionInput.value }, + { "identifier", _organizationInfo.Identifier }, + { "provider", _organizationInfo.Provider }, + }; + if (!createDeploymentResponse.IsResultCode202) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", createDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + OnCreateDeploymentStartServerFail(createDeploymentResponse.Error.ErrorMessage); return; } @@ -2002,9 +2217,16 @@ await deployApi.AwaitReadyStatusAsync( EdgegapWindowMetadata.StatusColors.Success ); _deployResultLabel.style.display = DisplayStyle.Flex; + + 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(_organizationInfo.DistinctId, properties); + OnCreateDeploymentStartServerFail(getDeploymentStatusResponse.Error.ErrorMessage); } } @@ -2032,6 +2254,17 @@ private void OnCreateDeploymentStartServerFail(string message = null) /// private async void OnStopLastDeployClick() { + AnalyticsApi analyticsApi = getAnalyticsApi(); + Dictionary properties = new Dictionary() + { + { "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 }, + }; + try { hideResultLabels(); @@ -2069,6 +2302,10 @@ private async void OnStopLastDeployClick() if (!stopDeploymentResponse.IsResultCode200) { + properties.Add("succeeded", false.ToString()); + properties.Add("error_message", stopDeploymentResponse.Error.ErrorMessage); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + OnGetStopLastDeploymentResult(stopDeploymentResponse.Error.ErrorMessage, false); return; } @@ -2085,10 +2322,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(_organizationInfo.DistinctId, properties); + OnGetStopLastDeploymentResult(stopDeploymentResponse.Error.ErrorMessage, false); } else { + properties.Add("succeeded", true.ToString()); + await analyticsApi.PostAsync(_organizationInfo.DistinctId, properties); + OnGetStopLastDeploymentResult("Deployment stopped successfully", true); } @@ -2096,6 +2340,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(_organizationInfo.DistinctId, properties); + OnGetStopLastDeploymentResult(e.Message, false); OpenEdgegapURL(EdgegapWindowMetadata.EDGEGAP_DEPLOY_APP_URL); } @@ -2559,6 +2808,18 @@ public static string Base64Decode(string base64EncodedText) return Encoding.UTF8.GetString(base64Bytes); } #endregion + + #region Utility / Analytics + private AnalyticsApi getAnalyticsApi() + { + if (_analyticsApi is null) + { + _analyticsApi = new AnalyticsApi(); + } + + return _analyticsApi; + } + #endregion } }