From 28f65b37902786b359d4230cdc1ef2999076c47f Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Fri, 6 Feb 2026 23:12:54 +0800 Subject: [PATCH] =?UTF-8?q?add:Dlass=E9=81=A5=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/TelemetryUploader.cs | 149 ++++++++++++++++++++++++ Ink Canvas/MainWindow.xaml.cs | 3 + 2 files changed, 152 insertions(+) create mode 100644 Ink Canvas/Helpers/TelemetryUploader.cs diff --git a/Ink Canvas/Helpers/TelemetryUploader.cs b/Ink Canvas/Helpers/TelemetryUploader.cs new file mode 100644 index 00000000..2a728e7a --- /dev/null +++ b/Ink Canvas/Helpers/TelemetryUploader.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Threading.Tasks; +using Sentry; + +namespace Ink_Canvas.Helpers +{ + /// + /// 遥测上传辅助类:根据用户设置,通过 Sentry 上传 usage_stats.enc 和 Crashes 目录的摘要信息。 + /// + internal static class TelemetryUploader + { + /// + /// 根据当前设置决定是否上传遥测数据。 + /// 在主窗口加载完成后调用一次即可。 + /// + 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; + } + + // 读取 usage_stats.enc 作为基础数据 + string usageStatsPath = Path.Combine(App.RootPath, "usage_stats.enc"); + string usageStatsContent = null; + if (File.Exists(usageStatsPath)) + { + try + { + usageStatsContent = File.ReadAllText(usageStatsPath); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile( + $"TelemetryUploader | 读取 usage_stats.enc 失败: {ex.Message}", + LogHelper.LogType.Warning); + } + } + + // 可选:读取 Crashes 目录下的崩溃日志(仅在扩展模式时上传) + List crashFiles = null; + if (level == TelemetryUploadLevel.Extended) + { + try + { + string crashDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Crashes"); + if (Directory.Exists(crashDir)) + { + crashFiles = new List(); + var files = Directory.GetFiles(crashDir); + + int count = 0; + foreach (var file in files) + { + if (count >= 10) + { + break; // 简单限制:最多上传最近10个文件 + } + + try + { + var info = new FileInfo(file); + + // 避免一次上传过大,单文件限制为 512KB + if (info.Length > 512 * 1024) + { + continue; + } + + string content = File.ReadAllText(file); + crashFiles.Add(new + { + file_name = info.Name, + content = content + }); + + count++; + } + catch (Exception exFile) + { + LogHelper.WriteLogToFile( + $"TelemetryUploader | 读取崩溃日志失败: {exFile.Message}", + LogHelper.LogType.Warning); + } + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile( + $"TelemetryUploader | 收集崩溃日志失败: {ex.Message}", + LogHelper.LogType.Warning); + } + } + + // 通过 Sentry 上报一个包含遥测信息的事件 + var evt = new SentryEvent + { + Message = "ICC CE Telemetry", + Level = SentryLevel.Info + }; + + evt.SetTag("telemetry_level", level.ToString()); + evt.SetTag("device_id", deviceId); + evt.SetTag("app_version", Assembly.GetExecutingAssembly().GetName().Version.ToString()); + evt.SetTag("os_version", Environment.OSVersion.VersionString); + + evt.SetExtra("usage_stats_raw", usageStatsContent); + 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); + } + }); + } + } +} + + diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index b8fa01cc..1f8a1b2f 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -534,6 +534,9 @@ namespace Ink_Canvas // 初始化Dlass上传队列(恢复上次的上传队列) DlassNoteUploader.InitializeQueue(); + // 根据用户设置上传匿名使用数据(usage_stats.enc / Crashes) + _ = TelemetryUploader.UploadTelemetryIfNeededAsync(); + // 检查保存路径是否可用,不可用则修正 try {