telemetry_session.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright 2017 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/assert.h"
  5. #include "common/common_types.h"
  6. #include "common/file_util.h"
  7. #include "core/core.h"
  8. #include "core/file_sys/control_metadata.h"
  9. #include "core/file_sys/patch_manager.h"
  10. #include "core/loader/loader.h"
  11. #include "core/settings.h"
  12. #include "core/telemetry_session.h"
  13. namespace Core {
  14. static u64 GenerateTelemetryId() {
  15. u64 telemetry_id{};
  16. return telemetry_id;
  17. }
  18. u64 GetTelemetryId() {
  19. u64 telemetry_id{};
  20. const std::string filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) +
  21. "telemetry_id"};
  22. if (FileUtil::Exists(filename)) {
  23. FileUtil::IOFile file(filename, "rb");
  24. if (!file.IsOpen()) {
  25. LOG_ERROR(Core, "failed to open telemetry_id: {}", filename);
  26. return {};
  27. }
  28. file.ReadBytes(&telemetry_id, sizeof(u64));
  29. } else {
  30. FileUtil::IOFile file(filename, "wb");
  31. if (!file.IsOpen()) {
  32. LOG_ERROR(Core, "failed to open telemetry_id: {}", filename);
  33. return {};
  34. }
  35. telemetry_id = GenerateTelemetryId();
  36. file.WriteBytes(&telemetry_id, sizeof(u64));
  37. }
  38. return telemetry_id;
  39. }
  40. u64 RegenerateTelemetryId() {
  41. const u64 new_telemetry_id{GenerateTelemetryId()};
  42. const std::string filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) +
  43. "telemetry_id"};
  44. FileUtil::IOFile file(filename, "wb");
  45. if (!file.IsOpen()) {
  46. LOG_ERROR(Core, "failed to open telemetry_id: {}", filename);
  47. return {};
  48. }
  49. file.WriteBytes(&new_telemetry_id, sizeof(u64));
  50. return new_telemetry_id;
  51. }
  52. std::future<bool> VerifyLogin(std::string username, std::string token, std::function<void()> func) {
  53. #ifdef ENABLE_WEB_SERVICE
  54. return WebService::VerifyLogin(username, token, Settings::values.verify_endpoint_url, func);
  55. #else
  56. return std::async(std::launch::async, [func{std::move(func)}]() {
  57. func();
  58. return false;
  59. });
  60. #endif
  61. }
  62. TelemetrySession::TelemetrySession() {
  63. #ifdef ENABLE_WEB_SERVICE
  64. if (Settings::values.enable_telemetry) {
  65. backend = std::make_unique<WebService::TelemetryJson>(
  66. Settings::values.telemetry_endpoint_url, Settings::values.yuzu_username,
  67. Settings::values.yuzu_token);
  68. } else {
  69. backend = std::make_unique<Telemetry::NullVisitor>();
  70. }
  71. #else
  72. backend = std::make_unique<Telemetry::NullVisitor>();
  73. #endif
  74. // Log one-time top-level information
  75. AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId());
  76. // Log one-time session start information
  77. const s64 init_time{std::chrono::duration_cast<std::chrono::milliseconds>(
  78. std::chrono::system_clock::now().time_since_epoch())
  79. .count()};
  80. AddField(Telemetry::FieldType::Session, "Init_Time", init_time);
  81. u64 program_id{};
  82. const Loader::ResultStatus res{System::GetInstance().GetAppLoader().ReadProgramId(program_id)};
  83. if (res == Loader::ResultStatus::Success) {
  84. AddField(Telemetry::FieldType::Session, "ProgramId", program_id);
  85. std::string name;
  86. System::GetInstance().GetAppLoader().ReadTitle(name);
  87. if (name.empty()) {
  88. auto [nacp, icon_file] = FileSys::PatchManager(program_id).GetControlMetadata();
  89. if (nacp != nullptr)
  90. name = nacp->GetApplicationName();
  91. }
  92. if (!name.empty())
  93. AddField(Telemetry::FieldType::Session, "ProgramName", name);
  94. }
  95. AddField(Telemetry::FieldType::Session, "ProgramFormat",
  96. static_cast<u8>(System::GetInstance().GetAppLoader().GetFileType()));
  97. // Log application information
  98. Telemetry::AppendBuildInfo(field_collection);
  99. // Log user system information
  100. Telemetry::AppendCPUInfo(field_collection);
  101. Telemetry::AppendOSInfo(field_collection);
  102. // Log user configuration information
  103. AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", Settings::values.use_cpu_jit);
  104. AddField(Telemetry::FieldType::UserConfig, "Core_UseMultiCore",
  105. Settings::values.use_multi_core);
  106. AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor",
  107. Settings::values.resolution_factor);
  108. AddField(Telemetry::FieldType::UserConfig, "Renderer_UseFrameLimit",
  109. Settings::values.use_frame_limit);
  110. AddField(Telemetry::FieldType::UserConfig, "Renderer_FrameLimit", Settings::values.frame_limit);
  111. AddField(Telemetry::FieldType::UserConfig, "Renderer_UseAccurateFramebuffers",
  112. Settings::values.use_accurate_framebuffers);
  113. AddField(Telemetry::FieldType::UserConfig, "System_UseDockedMode",
  114. Settings::values.use_docked_mode);
  115. }
  116. TelemetrySession::~TelemetrySession() {
  117. // Log one-time session end information
  118. const s64 shutdown_time{std::chrono::duration_cast<std::chrono::milliseconds>(
  119. std::chrono::system_clock::now().time_since_epoch())
  120. .count()};
  121. AddField(Telemetry::FieldType::Session, "Shutdown_Time", shutdown_time);
  122. // Complete the session, submitting to web service if necessary
  123. // This is just a placeholder to wrap up the session once the core completes and this is
  124. // destroyed. This will be moved elsewhere once we are actually doing real I/O with the service.
  125. field_collection.Accept(*backend);
  126. backend->Complete();
  127. backend = nullptr;
  128. }
  129. } // namespace Core