package_build_report.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include <array>
  2. #include <atomic>
  3. #include <cstdio>
  4. #include "../../../../core/logging/log.h"
  5. #include "../../../../middleware/content/packages/tables/definition_index_table.h"
  6. #include "internal.h"
  7. namespace sunrise::client::content::items::packages {
  8. namespace {
  9. std::atomic<bool> g_reported{};
  10. std::atomic<bool> g_bucketFailureReported{};
  11. std::atomic<std::size_t> g_abilityFailureReports{};
  12. } // namespace
  13. /** @param slot Requested-set position. @param definitionIndex Native item index that failed. */
  14. void report_detail_failure(std::size_t slot, std::uint16_t definitionIndex) noexcept {
  15. std::array<char, 96> line{};
  16. const int written = std::snprintf(line.data(),
  17. line.size(),
  18. "ev=pkg stage=details result=fail slot=%zu index=%u",
  19. slot,
  20. static_cast<unsigned>(definitionIndex));
  21. if (written > 0) {
  22. core::log::write(core::log::Channel::client,
  23. core::log::Level::warn,
  24. {line.data(), static_cast<std::size_t>(written)});
  25. }
  26. }
  27. /** @param count Ability bucket rows the pass built, one per subclass and ability selection. */
  28. void report_ability_count(std::size_t count) noexcept {
  29. std::array<char, 96> line{};
  30. const int written =
  31. std::snprintf(line.data(), line.size(), "ev=pkg stage=abilities result=ok rows=%zu", count);
  32. if (written > 0) {
  33. core::log::write(core::log::Channel::client,
  34. core::log::Level::info,
  35. {line.data(), static_cast<std::size_t>(written)});
  36. }
  37. }
  38. /** Reports the precise ability boundary without flooding the periodic extraction retry. */
  39. void report_ability_failure(const char* stage,
  40. std::size_t character,
  41. std::size_t first,
  42. std::size_t second) noexcept {
  43. constexpr std::size_t kReportLimit = 12;
  44. if (g_abilityFailureReports.fetch_add(1, std::memory_order_relaxed) >= kReportLimit) {
  45. return;
  46. }
  47. std::array<char, 176> line{};
  48. const int written = std::snprintf(line.data(),
  49. line.size(),
  50. "ev=pkg stage=ability_failure reason=%s character=%zu "
  51. "first=%zu second=%zu",
  52. stage,
  53. character,
  54. first,
  55. second);
  56. if (written > 0) {
  57. core::log::write(core::log::Channel::client,
  58. core::log::Level::warn,
  59. {line.data(), static_cast<std::size_t>(written)});
  60. }
  61. }
  62. /** Reports requested, retained, and skipped rows for the equippable-item detail closure. */
  63. void report_detail_count(std::size_t requested, std::size_t built) noexcept {
  64. std::array<char, 128> line{};
  65. const int written = std::snprintf(line.data(),
  66. line.size(),
  67. "ev=pkg stage=details result=ok requested=%zu rows=%zu "
  68. "skipped=%zu",
  69. requested,
  70. built,
  71. requested - built);
  72. if (written > 0) {
  73. core::log::write(core::log::Channel::client,
  74. core::log::Level::info,
  75. {line.data(), static_cast<std::size_t>(written)});
  76. }
  77. }
  78. /** Reports the item index-table walk and every entry it could not read. */
  79. void report_row_count(std::size_t walked,
  80. std::size_t rows,
  81. std::size_t skipped,
  82. bool truncated) noexcept {
  83. std::array<char, 128> line{};
  84. const int written = std::snprintf(line.data(),
  85. line.size(),
  86. "ev=pkg stage=rows result=ok walked=%zu rows=%zu "
  87. "skipped=%zu truncated=%u",
  88. walked,
  89. rows,
  90. skipped,
  91. static_cast<unsigned>(truncated));
  92. if (written > 0) {
  93. core::log::write(core::log::Channel::client,
  94. skipped == 0 && !truncated ? core::log::Level::info
  95. : core::log::Level::warn,
  96. {line.data(), static_cast<std::size_t>(written)});
  97. }
  98. }
  99. /** Reports the bounded exact ordinary-socket relation extracted from the installed packages. */
  100. void report_socket_plug_count(std::size_t rules,
  101. std::size_t pools,
  102. std::size_t members,
  103. std::size_t skipped) noexcept {
  104. std::array<char, 160> line{};
  105. const int written = std::snprintf(line.data(),
  106. line.size(),
  107. "ev=pkg stage=socket_plugs result=ok rules=%zu pools=%zu "
  108. "members=%zu skipped=%zu",
  109. rules,
  110. pools,
  111. members,
  112. skipped);
  113. if (written > 0) {
  114. core::log::write(core::log::Channel::client,
  115. skipped == 0 ? core::log::Level::info : core::log::Level::warn,
  116. {line.data(), static_cast<std::size_t>(written)});
  117. }
  118. }
  119. /** Reports the installed bucket definition relation used by loadout resolution. */
  120. void report_bucket_equipment_mapping(std::size_t mappedSlots) noexcept {
  121. std::array<char, 128> line{};
  122. const int written = std::snprintf(line.data(),
  123. line.size(),
  124. "ev=pkg stage=bucket_equipment result=ok rows=%zu mapped=%zu",
  125. tables::kBucketDefinitionCount,
  126. mappedSlots);
  127. if (written > 0) {
  128. core::log::write(core::log::Channel::client,
  129. core::log::Level::info,
  130. {line.data(), static_cast<std::size_t>(written)});
  131. }
  132. }
  133. /** Reports one fail-closed bucket-definition rejection without flooding extraction retries. */
  134. void report_bucket_equipment_failure(const char* stage,
  135. std::size_t first,
  136. std::size_t second) noexcept {
  137. if (g_bucketFailureReported.exchange(true, std::memory_order_relaxed)) {
  138. return;
  139. }
  140. std::array<char, 160> line{};
  141. const int written = std::snprintf(line.data(),
  142. line.size(),
  143. "ev=pkg stage=bucket_equipment result=fail reason=%s "
  144. "first=%zu second=%zu",
  145. stage,
  146. first,
  147. second);
  148. if (written > 0) {
  149. core::log::write(core::log::Channel::client,
  150. core::log::Level::warn,
  151. {line.data(), static_cast<std::size_t>(written)});
  152. }
  153. }
  154. /** Reports the pass outcome once. @param published Rows published, or zero on failure. */
  155. void report(std::size_t published, const char* reason) noexcept {
  156. if (g_reported.exchange(true, std::memory_order_relaxed)) {
  157. return;
  158. }
  159. std::array<char, 96> line{};
  160. const int written = published != 0
  161. ? std::snprintf(line.data(),
  162. line.size(),
  163. "ev=build_data stage=items result=ok rows=%zu",
  164. published)
  165. : std::snprintf(line.data(),
  166. line.size(),
  167. "ev=build_data stage=items result=fail reason=%s",
  168. reason);
  169. if (written > 0) {
  170. core::log::write(core::log::Channel::client,
  171. published != 0 ? core::log::Level::info : core::log::Level::warn,
  172. {line.data(), static_cast<std::size_t>(written)});
  173. }
  174. }
  175. } // namespace sunrise::client::content::items::packages