Create TelemetryIdentity.cs and more fixes

Create TelemetryIdentity.cs and more fixes
This commit is contained in:
Namhyeon Go 2025-12-03 16:34:41 +09:00
parent 78bcae182e
commit 2db2e7b91a
4 changed files with 162 additions and 16 deletions

View File

@ -47,19 +47,15 @@ namespace WelsonJS.Launcher
);
// telemetry
bool telemetryEnabled = string.Equals(GetAppConfig("TelemetryEnabled"), "true", StringComparison.OrdinalIgnoreCase);
if (!telemetryEnabled)
string telemetryProvider = GetAppConfig("TelemetryProvider");
var telemetryOptions = new TelemetryOptions
{
string telemetryProvider = GetAppConfig("TelemetryProvider");
var telemetryOptions = new TelemetryOptions
{
ApiKey = GetAppConfig("TelemetryApiKey"),
BaseUrl = GetAppConfig("TelemetryBaseUrl"),
DistinctId = Environment.MachineName,
Disabled = !telemetryEnabled
};
_telemetryClient = new TelemetryClient(telemetryProvider, telemetryOptions, _logger);
}
ApiKey = GetAppConfig("TelemetryApiKey"),
BaseUrl = GetAppConfig("TelemetryBaseUrl"),
DistinctId = TelemetryIdentity.GetDistinctId(),
Disabled = !string.Equals(GetAppConfig("TelemetryEnabled"), "true", StringComparison.OrdinalIgnoreCase)
};
_telemetryClient = new TelemetryClient(telemetryProvider, telemetryOptions, _logger);
}
[STAThread]

View File

@ -22,11 +22,14 @@ namespace WelsonJS.Launcher.Telemetry
{
_options = options ?? throw new ArgumentNullException(nameof(options));
if (string.IsNullOrWhiteSpace(_options.ApiKey))
throw new ArgumentException("PostHog API key is missing.");
if (!_options.Disabled)
{
if (string.IsNullOrWhiteSpace(_options.ApiKey))
throw new ArgumentException("PostHog API key is missing.");
if (string.IsNullOrWhiteSpace(_options.BaseUrl))
throw new ArgumentException("PostHog BaseUrl is missing.");
if (string.IsNullOrWhiteSpace(_options.BaseUrl))
throw new ArgumentException("PostHog BaseUrl is missing.");
}
if (string.IsNullOrWhiteSpace(_options.DistinctId))
_options.DistinctId = $"anon-{Guid.NewGuid():N}";

View File

@ -0,0 +1,145 @@
// TelemetryIdentity.cs
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2025 Catswords OSS and WelsonJS Contributors
// https://github.com/gnh1201/welsonjs
//
using System;
using System.Collections.Generic;
using System.Management;
using System.Security.Cryptography;
using System.Text;
namespace WelsonJS.Launcher.Telemetry
{
public static class TelemetryIdentity
{
/// <summary>
/// Collects multiple hardware/OS identity sources (BIOS UUID, OS SerialNumber, MachineName),
/// joins them with ',' and computes SHA-256 hash, then returns the first 16 hex characters
/// as a compact Distinct ID.
/// </summary>
public static string GetDistinctId()
{
var sources = new List<string>();
string biosUuid = GetBiosUuid();
if (!string.IsNullOrEmpty(biosUuid))
sources.Add(biosUuid);
string osUuid = GetOsUuid();
if (!string.IsNullOrEmpty(osUuid))
sources.Add(osUuid);
string machineName = GetMachineName();
if (!string.IsNullOrEmpty(machineName))
sources.Add(machineName);
string raw = string.Join(",", sources);
string hash = ComputeSha256(raw);
if (!string.IsNullOrEmpty(hash) && hash.Length >= 16)
return hash.Substring(0, 16);
return hash;
}
private static string GetMachineName()
{
try { return Environment.MachineName ?? ""; }
catch { return ""; }
}
/// <summary>
/// Retrieves BIOS UUID from Win32_ComputerSystemProduct.
/// Filters out invalid values (all zeros or all 'F').
/// </summary>
private static string GetBiosUuid()
{
try
{
using (var searcher =
new ManagementObjectSearcher("SELECT UUID FROM Win32_ComputerSystemProduct"))
{
foreach (ManagementObject obj in searcher.Get())
{
string uuid = obj["UUID"] as string;
if (string.IsNullOrEmpty(uuid))
return null;
uuid = uuid.Trim();
string compact = uuid.Replace("-", "").ToUpperInvariant();
// Exclude invalid dummy UUIDs such as all 0s or all Fs
if (IsAllChar(compact, '0') || IsAllChar(compact, 'F'))
return null;
return uuid;
}
}
}
catch { }
return null;
}
/// <summary>
/// Retrieves OS-level UUID equivalent using Win32_OperatingSystem.SerialNumber.
/// This value is unique per Windows installation.
/// </summary>
private static string GetOsUuid()
{
try
{
using (var searcher =
new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_OperatingSystem"))
{
foreach (ManagementObject obj in searcher.Get())
{
string serial = obj["SerialNumber"] as string;
if (!string.IsNullOrEmpty(serial))
return serial.Trim();
}
}
}
catch { }
return null;
}
private static bool IsAllChar(string s, char c)
{
if (string.IsNullOrEmpty(s)) return false;
for (int i = 0; i < s.Length; i++)
if (s[i] != c) return false;
return true;
}
/// <summary>
/// Computes SHA-256 hex string for the given input text.
/// Returns null if hashing fails.
/// </summary>
private static string ComputeSha256(string input)
{
if (input == null) input = "";
try
{
using (var sha = SHA256.Create())
{
var data = Encoding.UTF8.GetBytes(input);
var digest = sha.ComputeHash(data);
var sb = new StringBuilder(digest.Length * 2);
for (int i = 0; i < digest.Length; i++)
sb.Append(digest[i].ToString("x2"));
return sb.ToString();
}
}
catch
{
return null;
}
}
}
}

View File

@ -80,6 +80,7 @@
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Management" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
@ -131,6 +132,7 @@
<Compile Include="Telemetry\ITelemetryProvider.cs" />
<Compile Include="Telemetry\PosthogTelemetryProvider.cs" />
<Compile Include="Telemetry\TelemetryClient.cs" />
<Compile Include="Telemetry\TelemetryIdentity.cs" />
<Compile Include="Telemetry\TelemetryOptions.cs" />
<Compile Include="Telemetry\TelemetryProviderFactory.cs" />
<Compile Include="TraceLogger.cs" />