Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Further develop on telemetry #3246

Merged
merged 8 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 104 additions & 19 deletions src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
using System.ComponentModel.Design;
using System.Net;
using UniGetUI.Core.Data;
using UniGetUI.Core.Language;
using UniGetUI.Core.Logging;
using UniGetUI.Core.SettingsEngine;
using UniGetUI.Core.Tools;
using UniGetUI.PackageEngine;
using UniGetUI.PackageEngine.Enums;
using UniGetUI.PackageEngine.Interfaces;

namespace UniGetUI.Interface.Telemetry;

public enum TEL_InstallReferral
{
DIRECT_SEARCH,
FROM_BUNDLE,
FROM_WEB_SHARE,
ALREADY_INSTALLED,
}

public enum TEL_OP_RESULT
{
SUCCESS,
FAILED,
CANCELED
}

public static class TelemetryHandler
{
private const string HOST = "https://marticliment.com/unigetui/statistics";

private const string HOST = "https://marticliment.com/unigetui/statistics";
private static string[] SettingsToSend =
{
"DisableAutoUpdateWingetUI",
Expand All @@ -30,19 +48,15 @@ public static class TelemetryHandler
"SP2" // UniGetUI was started as daemon
};

// -------------------------------------------------------------------------

public static async void Initialize()
{
try
{
if (Settings.Get("DisableTelemetry")) return;
await CoreTools.WaitForInternetConnection();

if (Settings.GetValue("TelemetryClientToken").Length != 64)
{
Settings.SetValue("TelemetryClientToken", CoreTools.RandomString(64));
}

string ID = Settings.GetValue("TelemetryClientToken");
string ID = GetRandomizedId();

int mask = 0x1;
int ManagerMagicValue = 0;
Expand Down Expand Up @@ -102,43 +116,114 @@ public static async void Initialize()
}
}

public static async void PackageInstalled(IPackage package)
// -------------------------------------------------------------------------

public static void InstallPackage(IPackage package, TEL_OP_RESULT status, TEL_InstallReferral source)
=> PackageEndpoint(package, "install", status, source.ToString());

public static void UpdatePackage(IPackage package, TEL_OP_RESULT status)
=> PackageEndpoint(package, "update", status);

public static void DownloadPackage(IPackage package, TEL_OP_RESULT status, TEL_InstallReferral source)
=> PackageEndpoint(package, "download", status, source.ToString());

public static void UninstallPackage(IPackage package, TEL_OP_RESULT status)
=> PackageEndpoint(package, "uninstall", status);

public static void PackageDetails(IPackage package, string eventSource)
=> PackageEndpoint(package, "details", eventSource: eventSource);

public static void SharedPackage(IPackage package, string eventSource)
=> PackageEndpoint(package, "share", eventSource: eventSource);

private static async void PackageEndpoint(IPackage package, string endpoint, TEL_OP_RESULT? result = null, string? eventSource = null)
{
if (result is null && eventSource is null) throw new NullReferenceException("result and eventSource cannot be both null!");

try
{
if (Settings.Get("DisableTelemetry")) return;
await CoreTools.WaitForInternetConnection();
string ID = GetRandomizedId();

var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/package/{endpoint}");

request.Headers.Add("clientId", ID);
request.Headers.Add("packageId", package.Id);
request.Headers.Add("managerName", package.Manager.Name);
request.Headers.Add("sourceName", package.Source.Name);
if(result is not null) request.Headers.Add("operationResult", result.ToString());
if(eventSource is not null) request.Headers.Add("eventSource", eventSource);

HttpClient _httpClient = new(CoreData.GenericHttpClientParameters);
HttpResponseMessage response = await _httpClient.SendAsync(request);

if (Settings.GetValue("TelemetryClientToken").Length != 64)
if (response.IsSuccessStatusCode)
{
Logger.Debug($"[Telemetry] Call to /package/{endpoint} succeeded");
}
else
{
Settings.SetValue("TelemetryClientToken", CoreTools.RandomString(64));
Logger.Warn($"[Telemetry] Call to /package/{endpoint} failed with error code {response.StatusCode}");
}
}
catch (Exception ex)
{
Logger.Error($"[Telemetry] Hard crash when calling /package/{endpoint}");
Logger.Error(ex);
}
}


string ID = Settings.GetValue("TelemetryClientToken");
// -------------------------------------------------------------------------

var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/install");
public static void ImportBundle(BundleFormatType type)
=> BundlesEndpoint("import", type);

public static void ExportBundle(BundleFormatType type)
=> BundlesEndpoint("export", type);

private static async void BundlesEndpoint(string endpoint, BundleFormatType type)
{
try
{
if (Settings.Get("DisableTelemetry")) return;
await CoreTools.WaitForInternetConnection();
string ID = GetRandomizedId();

var request = new HttpRequestMessage(HttpMethod.Post, $"{HOST}/bundles/{endpoint}");

request.Headers.Add("clientId", ID);
request.Headers.Add("packageId", package.Id);
request.Headers.Add("managerName", package.Manager.Name);
request.Headers.Add("sourceName", package.Source.Name);
request.Headers.Add("bundleType", type.ToString());

HttpClient _httpClient = new(CoreData.GenericHttpClientParameters);
HttpResponseMessage response = await _httpClient.SendAsync(request);

if (response.IsSuccessStatusCode)
{
Logger.Debug("[Telemetry] Call to /install succeeded");
Logger.Debug($"[Telemetry] Call to /bundles/{endpoint} succeeded");
}
else
{
Logger.Warn($"[Telemetry] Call to /install failed with error code {response.StatusCode}");
Logger.Warn($"[Telemetry] Call to /bundles/{endpoint} failed with error code {response.StatusCode}");
}
}
catch (Exception ex)
{
Logger.Error("[Telemetry] Hard crash when calling /install");
Logger.Error($"[Telemetry] Hard crash when calling /bundles/{endpoint}");
Logger.Error(ex);
}
}

private static string GetRandomizedId()
{
string ID = Settings.GetValue("TelemetryClientToken");
if (ID.Length != 64)
{
ID = CoreTools.RandomString(64);
Settings.SetValue("TelemetryClientToken", ID);
}

return ID;
}
}
3 changes: 2 additions & 1 deletion src/UniGetUI.PackageEngine.Enums/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ public enum DeserializedPackageStatus

public enum BundleFormatType
{
UBUNDLE,
JSON,
YAML,
XML
XML,
}

public enum OperationVeredict
Expand Down
19 changes: 14 additions & 5 deletions src/UniGetUI/AppOperationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static void Remove(AbstractOperation op)
* OPERATION CREATION HELPERS
*
*/
public static async Task<AbstractOperation?> AskLocationAndDownload(IPackage? package)
public static async Task<AbstractOperation?> AskLocationAndDownload(IPackage? package, TEL_InstallReferral referral)
{
if (package is null) return null;
try
Expand Down Expand Up @@ -87,6 +87,8 @@ public static void Remove(AbstractOperation op)
if (file is not null)
{
var op = new DownloadOperation(package, file.Path);
op.OperationSucceeded += (_, _) => TelemetryHandler.DownloadPackage(package, TEL_OP_RESULT.SUCCESS, referral);
op.OperationFailed += (_, _) => TelemetryHandler.DownloadPackage(package, TEL_OP_RESULT.FAILED, referral);
Add(op);
return op;
}
Expand All @@ -104,20 +106,23 @@ public static void Remove(AbstractOperation op)
/*
* PACKAGE INSTALLATION
*/
public static async Task<AbstractOperation?> Install(IPackage? package, bool? elevated = null, bool? interactive = null, bool? no_integrity = null, bool ignoreParallel = false, AbstractOperation? req = null)
public static async Task<AbstractOperation?> Install(IPackage? package, TEL_InstallReferral referral,
bool? elevated = null, bool? interactive = null, bool? no_integrity = null, bool ignoreParallel = false,
AbstractOperation? req = null)
{
if (package is null) return null;

var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity);
var op = new InstallPackageOperation(package, options, ignoreParallel, req);
Add(op);
op.OperationSucceeded += (_, _) => TelemetryHandler.PackageInstalled(package);
op.OperationSucceeded += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.SUCCESS, referral);
op.OperationFailed += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.FAILED, referral);
return op;
}

public static void Install(IReadOnlyList<IPackage> packages, bool? elevated = null, bool? interactive = null, bool? no_integrity = null)
public static void Install(IReadOnlyList<IPackage> packages, TEL_InstallReferral referral, bool? elevated = null, bool? interactive = null, bool? no_integrity = null)
{
foreach (var package in packages) _ = Install(package, elevated, interactive, no_integrity);
foreach (var package in packages) _ = Install(package, referral, elevated, interactive, no_integrity);
}

/*
Expand All @@ -130,6 +135,8 @@ public static void Install(IReadOnlyList<IPackage> packages, bool? elevated = nu
var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, no_integrity);
var op = new UpdatePackageOperation(package, options, ignoreParallel, req);
Add(op);
op.OperationSucceeded += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.SUCCESS);
op.OperationFailed += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.FAILED);
return op;
}

Expand Down Expand Up @@ -165,6 +172,8 @@ public static async void ConfirmAndUninstall(IPackage? package, bool? elevated =
var options = await InstallationOptions.FromPackageAsync(package, elevated, interactive, remove_data: remove_data);
var op = new UninstallPackageOperation(package, options, ignoreParallel, req);
Add(op);
op.OperationSucceeded += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.SUCCESS);
op.OperationFailed += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.FAILED);
return op;
}

Expand Down
3 changes: 2 additions & 1 deletion src/UniGetUI/Controls/OperationWidgets/OperationControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using UniGetUI.PackageEngine.Operations;
using System.Collections.ObjectModel;
using System.Diagnostics;
using UniGetUI.Interface.Telemetry;

namespace UniGetUI.Controls.OperationWidgets;

Expand Down Expand Up @@ -543,7 +544,7 @@ public List<BetterMenuItem> GetOperationOptions()
details.IconName = IconType.Info_Round;
details.Click += (_, _) =>
{
DialogHelper.ShowPackageDetails(packageOp.Package, OperationType.None);
DialogHelper.ShowPackageDetails(packageOp.Package, OperationType.None, TEL_InstallReferral.DIRECT_SEARCH);
};
optionsMenu.Add(details);

Expand Down
4 changes: 3 additions & 1 deletion src/UniGetUI/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Microsoft.Windows.AppNotifications;
using UniGetUI.Core.Classes;
using UniGetUI.Interface.Enums;
using UniGetUI.PackageEngine.Enums;
using UniGetUI.PackageEngine.PackageClasses;
using UniGetUI.Pages.DialogPages;

Expand Down Expand Up @@ -209,7 +210,8 @@ public async void HandleClosingEvent(AppWindow sender, AppWindowClosingEventArgs
}
else
{
if (MainApp.Operations._operationList.Count > 0)
if (MainApp.Operations._operationList.Any()
&& MainApp.Operations._operationList.Where(x => x.Operation.Status is OperationStatus.Running or OperationStatus.InQueue).Any())
{
args.Cancel = true;
ContentDialog d = new()
Expand Down
5 changes: 3 additions & 2 deletions src/UniGetUI/Pages/DialogPages/DialogHelper_Packages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using UniGetUI.Interface;
using UniGetUI.Interface.Dialogs;
using UniGetUI.Interface.Enums;
using UniGetUI.Interface.Telemetry;
using UniGetUI.Interface.Widgets;
using UniGetUI.PackageEngine.Enums;
using UniGetUI.PackageEngine.Interfaces;
Expand Down Expand Up @@ -90,9 +91,9 @@ public static async Task<ContentDialogResult> ShowInstallOptions_ImportedPackage
}


public static async void ShowPackageDetails(IPackage package, OperationType operation)
public static async void ShowPackageDetails(IPackage package, OperationType operation, TEL_InstallReferral referral)
{
PackageDetailsPage DetailsPage = new(package, operation);
PackageDetailsPage DetailsPage = new(package, operation, referral);

ContentDialog DetailsDialog = new()
{
Expand Down
12 changes: 9 additions & 3 deletions src/UniGetUI/Pages/DialogPages/PackageDetailsPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using UniGetUI.PackageEngine.Operations;
using UniGetUI.PackageEngine.PackageClasses;
using UniGetUI.Interface.Enums;
using UniGetUI.Interface.Telemetry;
using UniGetUI.Interface.Widgets;
using UniGetUI.PackageEngine.ManagerClasses.Manager;
using UniGetUI.Pages.DialogPages;
Expand Down Expand Up @@ -54,12 +55,15 @@ private enum LayoutMode
Unset
}

private TEL_InstallReferral InstallReferral;

private LayoutMode __layout_mode = LayoutMode.Unset;
public PackageDetailsPage(IPackage package, OperationType role)
public PackageDetailsPage(IPackage package, OperationType role, TEL_InstallReferral referral)
{
if (role == OperationType.None)
role = OperationType.Install;

InstallReferral = referral;
OperationRole = role;
Package = package;

Expand Down Expand Up @@ -136,6 +140,8 @@ public PackageDetailsPage(IPackage package, OperationType role)
SetUpActionButtonAsUninstall();
}
_ = LoadInformation();

TelemetryHandler.PackageDetails(package, referral.ToString());
}

public void SetUpActionButtonAsInstall()
Expand Down Expand Up @@ -456,7 +462,7 @@ public void DownloadInstallerButton_Click(object sender, RoutedEventArgs e)
{
if (!Package.Manager.Capabilities.CanDownloadInstaller) return;
Close?.Invoke(this, EventArgs.Empty);
_ = MainApp.Operations.AskLocationAndDownload(Package);
_ = MainApp.Operations.AskLocationAndDownload(Package, InstallReferral);
}

public void CloseButton_Click(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -590,7 +596,7 @@ public async void DoAction(

if (action is OperationType.Install)
{
_ = MainApp.Operations.Install(package, AsAdmin, Interactive, SkipHash);
_ = MainApp.Operations.Install(package, InstallReferral, AsAdmin, Interactive, SkipHash);
}
else if (action is OperationType.Uninstall)
{
Expand Down
Loading
Loading