metrics.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright (c) 2016 The Zcash developers
  2. // Distributed under the MIT software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #include "metrics.h"
  5. #include "chainparams.h"
  6. #include "ui_interface.h"
  7. #include "util.h"
  8. #include "utiltime.h"
  9. #include <boost/thread.hpp>
  10. #include <boost/thread/synchronized_value.hpp>
  11. #include <string>
  12. #include <sys/ioctl.h>
  13. #include <unistd.h>
  14. AtomicCounter transactionsValidated;
  15. AtomicCounter ehSolverRuns;
  16. AtomicCounter solutionTargetChecks;
  17. AtomicCounter minedBlocks;
  18. boost::synchronized_value<std::list<std::string>> messageBox;
  19. boost::synchronized_value<std::string> initMessage;
  20. bool loaded = false;
  21. static bool metrics_ThreadSafeMessageBox(const std::string& message,
  22. const std::string& caption,
  23. unsigned int style)
  24. {
  25. std::string strCaption;
  26. // Check for usage of predefined caption
  27. switch (style) {
  28. case CClientUIInterface::MSG_ERROR:
  29. strCaption += _("Error");
  30. break;
  31. case CClientUIInterface::MSG_WARNING:
  32. strCaption += _("Warning");
  33. break;
  34. case CClientUIInterface::MSG_INFORMATION:
  35. strCaption += _("Information");
  36. break;
  37. default:
  38. strCaption += caption; // Use supplied caption (can be empty)
  39. }
  40. boost::strict_lock_ptr<std::list<std::string>> u = messageBox.synchronize();
  41. u->push_back(strCaption + ": " + message);
  42. if (u->size() > 5) {
  43. u->pop_back();
  44. }
  45. }
  46. static void metrics_InitMessage(const std::string& message)
  47. {
  48. *initMessage = message;
  49. }
  50. void ConnectMetricsScreen()
  51. {
  52. uiInterface.ThreadSafeMessageBox.disconnect_all_slots();
  53. uiInterface.ThreadSafeMessageBox.connect(metrics_ThreadSafeMessageBox);
  54. uiInterface.InitMessage.disconnect_all_slots();
  55. uiInterface.InitMessage.connect(metrics_InitMessage);
  56. }
  57. void printMiningStatus(bool mining)
  58. {
  59. if (mining) {
  60. int nThreads = GetArg("-genproclimit", 1);
  61. if (nThreads < 0) {
  62. // In regtest threads defaults to 1
  63. if (Params().DefaultMinerThreads())
  64. nThreads = Params().DefaultMinerThreads();
  65. else
  66. nThreads = boost::thread::hardware_concurrency();
  67. }
  68. std::cout << strprintf(_("You are running %d mining threads."), nThreads) << std::endl;
  69. } else {
  70. std::cout << _("You are currently not mining.") << std::endl;
  71. std::cout << _("To enable mining, add 'gen=1' to your zcash.conf and restart.") << std::endl;
  72. }
  73. std::cout << std::endl;
  74. }
  75. int printMetrics(size_t cols, int64_t nStart, bool mining)
  76. {
  77. // Number of lines that are always displayed
  78. int lines = 3;
  79. // Calculate uptime
  80. int64_t uptime = GetTime() - nStart;
  81. int days = uptime / (24 * 60 * 60);
  82. int hours = (uptime - (days * 24 * 60 * 60)) / (60 * 60);
  83. int minutes = (uptime - (((days * 24) + hours) * 60 * 60)) / 60;
  84. int seconds = uptime - (((((days * 24) + hours) * 60) + minutes) * 60);
  85. // Display uptime
  86. std::string duration;
  87. if (days > 0) {
  88. duration = strprintf(_("%d days, %d hours, %d minutes, %d seconds"), days, hours, minutes, seconds);
  89. } else if (hours > 0) {
  90. duration = strprintf(_("%d hours, %d minutes, %d seconds"), hours, minutes, seconds);
  91. } else if (minutes > 0) {
  92. duration = strprintf(_("%d minutes, %d seconds"), minutes, seconds);
  93. } else {
  94. duration = strprintf(_("%d seconds"), seconds);
  95. }
  96. std::string strDuration = strprintf(_("Since starting this node %s ago:"), duration);
  97. std::cout << strDuration << std::endl;
  98. lines += (strDuration.size() / cols);
  99. std::cout << "- " << strprintf(_("You have validated %d transactions!"), transactionsValidated.get()) << std::endl;
  100. if (mining) {
  101. double solps = uptime > 0 ? (double)solutionTargetChecks.get() / uptime : 0;
  102. std::string strSolps = strprintf("%.4f Sol/s", solps);
  103. std::cout << "- " << strprintf(_("You have contributed %s on average to the network solution rate."), strSolps) << std::endl;
  104. std::cout << "- " << strprintf(_("You have completed %d Equihash solver runs."), ehSolverRuns.get()) << std::endl;
  105. lines += 2;
  106. int mined = minedBlocks.get();
  107. if (mined > 0) {
  108. std::cout << "- " << strprintf(_("You have mined %d blocks!"), mined) << std::endl;
  109. lines++;
  110. }
  111. }
  112. std::cout << std::endl;
  113. return lines;
  114. }
  115. int printMessageBox(size_t cols)
  116. {
  117. boost::strict_lock_ptr<std::list<std::string>> u = messageBox.synchronize();
  118. if (u->size() == 0) {
  119. return 0;
  120. }
  121. int lines = 2 + u->size();
  122. std::cout << _("Messages:") << std::endl;
  123. for (auto it = u->cbegin(); it != u->cend(); ++it) {
  124. std::cout << *it << std::endl;
  125. // Handle wrapped lines
  126. lines += (it->size() / cols);
  127. }
  128. std::cout << std::endl;
  129. return lines;
  130. }
  131. int printInitMessage()
  132. {
  133. if (loaded) {
  134. return 0;
  135. }
  136. std::string msg = *initMessage;
  137. std::cout << _("Init message:") << " " << msg << std::endl;
  138. std::cout << std::endl;
  139. if (msg == _("Done loading")) {
  140. loaded = true;
  141. }
  142. return 2;
  143. }
  144. void ThreadShowMetricsScreen()
  145. {
  146. // Make this thread recognisable as the metrics screen thread
  147. RenameThread("zcash-metrics-screen");
  148. // Clear screen
  149. std::cout << "\e[2J";
  150. // Print art
  151. std::cout << METRICS_ART << std::endl;
  152. std::cout << std::endl;
  153. // Thank you text
  154. std::cout << _("Thank you for running a Zcash node!") << std::endl;
  155. std::cout << _("You're helping to strengthen the network and contributing to a social good :)") << std::endl;
  156. std::cout << std::endl;
  157. // Miner status
  158. bool mining = GetBoolArg("-gen", false);
  159. printMiningStatus(mining);
  160. // Count uptime
  161. int64_t nStart = GetTime();
  162. while (true) {
  163. // Number of lines that are always displayed
  164. int lines = 1;
  165. int cols = 80;
  166. // Get current window size
  167. if (isatty(STDOUT_FILENO)) {
  168. struct winsize w;
  169. w.ws_col = 0;
  170. if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1 && w.ws_col != 0) {
  171. cols = w.ws_col;
  172. }
  173. }
  174. // Erase below current position
  175. std::cout << "\e[J";
  176. lines += printMetrics(cols, nStart, mining);
  177. lines += printMessageBox(cols);
  178. lines += printInitMessage();
  179. // Explain how to exit
  180. std::cout << "[" << _("Press Ctrl+C to exit") << "] [" << _("Set 'showmetrics=0' to hide") << "]" << std::endl;;
  181. boost::this_thread::interruption_point();
  182. MilliSleep(1000);
  183. // Return to the top of the updating section
  184. std::cout << "\e[" << lines << "A";
  185. }
  186. }