2026-03-03 16:04:20 +08:00
|
|
|
using Sentry;
|
2026-02-06 23:12:54 +08:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace Ink_Canvas.Helpers
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
2026-02-06 23:36:57 +08:00
|
|
|
/// 遥测上传:根据用户设置,通过 Sentry 上传 usage_stats 和 Crashes 目录的摘要信息。
|
2026-02-06 23:12:54 +08:00
|
|
|
/// </summary>
|
|
|
|
|
internal static class TelemetryUploader
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 根据当前设置决定是否上传遥测数据。
|
|
|
|
|
/// 在主窗口加载完成后调用一次即可。
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static Task UploadTelemetryIfNeededAsync()
|
|
|
|
|
{
|
|
|
|
|
return Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var settings = MainWindow.Settings;
|
|
|
|
|
if (settings == null || settings.Startup == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var level = settings.Startup.TelemetryUploadLevel;
|
|
|
|
|
if (level == TelemetryUploadLevel.None)
|
|
|
|
|
{
|
|
|
|
|
return; // 用户未开启
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取并校验设备ID
|
|
|
|
|
string deviceId = DeviceIdentifier.GetDeviceId();
|
|
|
|
|
if (string.IsNullOrWhiteSpace(deviceId) || deviceId.Length < 5)
|
|
|
|
|
{
|
|
|
|
|
LogHelper.WriteLogToFile("TelemetryUploader | 设备ID无效,取消遥测上传", LogHelper.LogType.Warning);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 23:36:57 +08:00
|
|
|
// 可选:Crashes 目录下的崩溃日志
|
2026-02-06 23:12:54 +08:00
|
|
|
List<object> crashFiles = null;
|
|
|
|
|
if (level == TelemetryUploadLevel.Extended)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
string crashDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Crashes");
|
|
|
|
|
if (Directory.Exists(crashDir))
|
|
|
|
|
{
|
|
|
|
|
crashFiles = new List<object>();
|
|
|
|
|
var files = Directory.GetFiles(crashDir);
|
|
|
|
|
|
2026-02-06 23:36:57 +08:00
|
|
|
FileInfo latestInfo = null;
|
|
|
|
|
string latestContent = null;
|
|
|
|
|
|
2026-02-06 23:12:54 +08:00
|
|
|
foreach (var file in files)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var info = new FileInfo(file);
|
|
|
|
|
|
2026-02-06 23:36:57 +08:00
|
|
|
// 避免一次上传过大,单文件限制为 8192KB
|
|
|
|
|
if (info.Length > 8192 * 1024)
|
2026-02-06 23:12:54 +08:00
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string content = File.ReadAllText(file);
|
|
|
|
|
|
2026-02-06 23:36:57 +08:00
|
|
|
if (latestInfo == null || info.LastWriteTime > latestInfo.LastWriteTime)
|
|
|
|
|
{
|
|
|
|
|
latestInfo = info;
|
|
|
|
|
latestContent = content;
|
|
|
|
|
}
|
2026-02-06 23:12:54 +08:00
|
|
|
}
|
|
|
|
|
catch (Exception exFile)
|
|
|
|
|
{
|
|
|
|
|
LogHelper.WriteLogToFile(
|
|
|
|
|
$"TelemetryUploader | 读取崩溃日志失败: {exFile.Message}",
|
|
|
|
|
LogHelper.LogType.Warning);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-06 23:36:57 +08:00
|
|
|
|
|
|
|
|
if (latestInfo != null && latestContent != null)
|
|
|
|
|
{
|
|
|
|
|
crashFiles.Add(new
|
|
|
|
|
{
|
|
|
|
|
file_name = latestInfo.Name,
|
|
|
|
|
content = latestContent
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-02-06 23:12:54 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LogHelper.WriteLogToFile(
|
|
|
|
|
$"TelemetryUploader | 收集崩溃日志失败: {ex.Message}",
|
|
|
|
|
LogHelper.LogType.Warning);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-07 12:43:03 +08:00
|
|
|
var telemetryData = new
|
|
|
|
|
{
|
|
|
|
|
telemetry_level = level.ToString(),
|
|
|
|
|
device_id = deviceId,
|
|
|
|
|
update_channel = settings.Startup.UpdateChannel.ToString(),
|
|
|
|
|
app_version = Assembly.GetExecutingAssembly().GetName().Version.ToString(),
|
|
|
|
|
os_version = Environment.OSVersion.VersionString,
|
|
|
|
|
crash_files = crashFiles
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-06 23:12:54 +08:00
|
|
|
// 通过 Sentry 上报一个包含遥测信息的事件
|
2026-02-07 12:43:03 +08:00
|
|
|
string userName = Environment.UserName;
|
|
|
|
|
SentrySdk.ConfigureScope(scope =>
|
|
|
|
|
{
|
|
|
|
|
scope.User = new SentryUser
|
|
|
|
|
{
|
|
|
|
|
Id = deviceId,
|
|
|
|
|
Username = userName,
|
2026-03-03 16:04:20 +08:00
|
|
|
Email = $"{userName}",
|
2026-02-07 12:43:03 +08:00
|
|
|
IpAddress = "{{auto}}"
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
2026-02-06 23:12:54 +08:00
|
|
|
var evt = new SentryEvent
|
|
|
|
|
{
|
|
|
|
|
Message = "ICC CE Telemetry",
|
|
|
|
|
Level = SentryLevel.Info
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-07 12:43:03 +08:00
|
|
|
evt.User = new SentryUser
|
|
|
|
|
{
|
|
|
|
|
Id = deviceId,
|
|
|
|
|
Username = userName,
|
2026-03-03 16:04:20 +08:00
|
|
|
Email = $"{userName}",
|
2026-02-07 12:43:03 +08:00
|
|
|
IpAddress = "{{auto}}"
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-06 23:12:54 +08:00
|
|
|
evt.SetTag("telemetry_level", level.ToString());
|
|
|
|
|
evt.SetTag("device_id", deviceId);
|
2026-02-06 23:36:57 +08:00
|
|
|
evt.SetTag("update_channel", settings.Startup.UpdateChannel.ToString());
|
2026-02-06 23:12:54 +08:00
|
|
|
evt.SetTag("app_version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
|
|
|
|
evt.SetTag("os_version", Environment.OSVersion.VersionString);
|
2026-03-03 16:04:20 +08:00
|
|
|
evt.SetExtra("telemetry_data", telemetryData);
|
2026-02-06 23:12:54 +08:00
|
|
|
|
|
|
|
|
if (crashFiles != null)
|
|
|
|
|
{
|
|
|
|
|
evt.SetExtra("crash_files", crashFiles);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SentrySdk.CaptureEvent(evt);
|
|
|
|
|
LogHelper.WriteLogToFile("TelemetryUploader | 遥测数据已通过 Sentry 上报", LogHelper.LogType.Event);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LogHelper.WriteLogToFile($"TelemetryUploader | 遥测上传失败: {ex.Message}", LogHelper.LogType.Warning);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|