]> Git Repo - VerusCoin.git/blame - src/metrics.cpp
Auto merge of #1870 - str4d:1749-benchmark-rescanning, r=str4d
[VerusCoin.git] / src / metrics.cpp
CommitLineData
a6df7ab5
JG
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
5#include "metrics.h"
6
7#include "chainparams.h"
d793f94b 8#include "main.h"
4ace963c 9#include "ui_interface.h"
a6df7ab5
JG
10#include "util.h"
11#include "utiltime.h"
d793f94b 12#include "utilmoneystr.h"
a6df7ab5
JG
13
14#include <boost/thread.hpp>
4ace963c
JG
15#include <boost/thread/synchronized_value.hpp>
16#include <string>
db853f8a 17#include <sys/ioctl.h>
1da44b34 18#include <unistd.h>
a6df7ab5 19
cb709831
JG
20CCriticalSection cs_metrics;
21
000499ae 22boost::synchronized_value<int64_t> nNodeStartTime;
a6df7ab5
JG
23AtomicCounter transactionsValidated;
24AtomicCounter ehSolverRuns;
e7d59bbc 25AtomicCounter solutionTargetChecks;
a6df7ab5
JG
26AtomicCounter minedBlocks;
27
d793f94b
JG
28boost::synchronized_value<std::list<uint256>> trackedBlocks;
29
4ace963c
JG
30boost::synchronized_value<std::list<std::string>> messageBox;
31boost::synchronized_value<std::string> initMessage;
32bool loaded = false;
33
eb5b582e
JG
34extern int64_t GetNetworkHashPS(int lookup, int height);
35
d793f94b
JG
36void TrackMinedBlock(uint256 hash)
37{
cb709831 38 LOCK(cs_metrics);
d793f94b
JG
39 minedBlocks.increment();
40 trackedBlocks->push_back(hash);
41}
42
000499ae
JG
43void MarkStartTime()
44{
45 *nNodeStartTime = GetTime();
46}
47
48int64_t GetUptime()
49{
50 return GetTime() - *nNodeStartTime;
51}
52
53double GetLocalSolPS_INTERNAL(int64_t uptime)
54{
55 return uptime > 0 ? (double)solutionTargetChecks.get() / uptime : 0;
56}
57
58double GetLocalSolPS()
59{
60 return GetLocalSolPS_INTERNAL(GetUptime());
61}
62
4ace963c
JG
63static bool metrics_ThreadSafeMessageBox(const std::string& message,
64 const std::string& caption,
65 unsigned int style)
66{
67 std::string strCaption;
68 // Check for usage of predefined caption
69 switch (style) {
70 case CClientUIInterface::MSG_ERROR:
71 strCaption += _("Error");
72 break;
73 case CClientUIInterface::MSG_WARNING:
74 strCaption += _("Warning");
75 break;
76 case CClientUIInterface::MSG_INFORMATION:
77 strCaption += _("Information");
78 break;
79 default:
80 strCaption += caption; // Use supplied caption (can be empty)
81 }
82
83 boost::strict_lock_ptr<std::list<std::string>> u = messageBox.synchronize();
84 u->push_back(strCaption + ": " + message);
85 if (u->size() > 5) {
86 u->pop_back();
87 }
88}
89
90static void metrics_InitMessage(const std::string& message)
91{
92 *initMessage = message;
93}
94
95void ConnectMetricsScreen()
96{
97 uiInterface.ThreadSafeMessageBox.disconnect_all_slots();
98 uiInterface.ThreadSafeMessageBox.connect(metrics_ThreadSafeMessageBox);
99 uiInterface.InitMessage.disconnect_all_slots();
100 uiInterface.InitMessage.connect(metrics_InitMessage);
101}
102
eb5b582e
JG
103int printNetworkStats()
104{
105 LOCK2(cs_main, cs_vNodes);
106
107 std::cout << " " << _("Block height") << " | " << chainActive.Height() << std::endl;
108 std::cout << " " << _("Network solution rate") << " | " << GetNetworkHashPS(120, -1) << " Sol/s" << std::endl;
109 std::cout << " " << _("Connections") << " | " << vNodes.size() << std::endl;
110 std::cout << std::endl;
111
112 return 4;
113}
114
848c89cd 115int printMiningStatus(bool mining)
d30273f9 116{
848c89cd
JG
117 // Number of lines that are always displayed
118 int lines = 1;
119
d30273f9
JG
120 if (mining) {
121 int nThreads = GetArg("-genproclimit", 1);
122 if (nThreads < 0) {
123 // In regtest threads defaults to 1
124 if (Params().DefaultMinerThreads())
125 nThreads = Params().DefaultMinerThreads();
126 else
127 nThreads = boost::thread::hardware_concurrency();
128 }
eb5b582e
JG
129 std::cout << strprintf(_("You are mining with the %s solver on %d threads."),
130 GetArg("-equihashsolver", "default"), nThreads) << std::endl;
848c89cd 131 lines++;
d30273f9 132 } else {
0ddd6d1c
JG
133 std::cout << _("You are currently not mining.") << std::endl;
134 std::cout << _("To enable mining, add 'gen=1' to your zcash.conf and restart.") << std::endl;
848c89cd 135 lines += 2;
d30273f9
JG
136 }
137 std::cout << std::endl;
848c89cd
JG
138
139 return lines;
d30273f9
JG
140}
141
000499ae 142int printMetrics(size_t cols, bool mining)
d30273f9
JG
143{
144 // Number of lines that are always displayed
145 int lines = 3;
146
147 // Calculate uptime
000499ae 148 int64_t uptime = GetUptime();
d30273f9
JG
149 int days = uptime / (24 * 60 * 60);
150 int hours = (uptime - (days * 24 * 60 * 60)) / (60 * 60);
151 int minutes = (uptime - (((days * 24) + hours) * 60 * 60)) / 60;
152 int seconds = uptime - (((((days * 24) + hours) * 60) + minutes) * 60);
153
154 // Display uptime
0ddd6d1c 155 std::string duration;
d30273f9 156 if (days > 0) {
0ddd6d1c
JG
157 duration = strprintf(_("%d days, %d hours, %d minutes, %d seconds"), days, hours, minutes, seconds);
158 } else if (hours > 0) {
159 duration = strprintf(_("%d hours, %d minutes, %d seconds"), hours, minutes, seconds);
160 } else if (minutes > 0) {
161 duration = strprintf(_("%d minutes, %d seconds"), minutes, seconds);
162 } else {
163 duration = strprintf(_("%d seconds"), seconds);
d30273f9 164 }
db853f8a
JG
165 std::string strDuration = strprintf(_("Since starting this node %s ago:"), duration);
166 std::cout << strDuration << std::endl;
167 lines += (strDuration.size() / cols);
d30273f9 168
1c8d5c40 169 int validatedCount = transactionsValidated.get();
ba6fc72b
S
170 if (validatedCount > 1) {
171 std::cout << "- " << strprintf(_("You have validated %d transactions!"), validatedCount) << std::endl;
172 } else if (validatedCount == 1) {
1c8d5c40 173 std::cout << "- " << _("You have validated a transaction!") << std::endl;
ba6fc72b 174 } else {
1c8d5c40 175 std::cout << "- " << _("You have validated no transactions.") << std::endl;
ba6fc72b 176 }
d30273f9 177
24f10266 178 if (mining && loaded) {
000499ae 179 double solps = GetLocalSolPS_INTERNAL(uptime);
199b3aaf
JG
180 std::string strSolps = strprintf("%.4f Sol/s", solps);
181 std::cout << "- " << strprintf(_("You have contributed %s on average to the network solution rate."), strSolps) << std::endl;
0ddd6d1c 182 std::cout << "- " << strprintf(_("You have completed %d Equihash solver runs."), ehSolverRuns.get()) << std::endl;
e7d59bbc 183 lines += 2;
d30273f9 184
cb709831
JG
185 int mined = 0;
186 int orphaned = 0;
22ee0efe
JG
187 CAmount immature {0};
188 CAmount mature {0};
cb709831
JG
189 {
190 LOCK2(cs_main, cs_metrics);
d793f94b
JG
191 boost::strict_lock_ptr<std::list<uint256>> u = trackedBlocks.synchronize();
192 auto consensusParams = Params().GetConsensus();
193 auto tipHeight = chainActive.Height();
d793f94b
JG
194
195 // Update orphans and calculate subsidies
73a43918
JG
196 std::list<uint256>::iterator it = u->begin();
197 while (it != u->end()) {
d793f94b
JG
198 auto hash = *it;
199 if (mapBlockIndex.count(hash) > 0 &&
200 chainActive.Contains(mapBlockIndex[hash])) {
201 int height = mapBlockIndex[hash]->nHeight;
202 CAmount subsidy = GetBlockSubsidy(height, consensusParams);
203 if ((height > 0) && (height <= consensusParams.GetLastFoundersRewardBlockHeight())) {
204 subsidy -= subsidy/5;
205 }
206 if (std::max(0, COINBASE_MATURITY - (tipHeight - height)) > 0) {
207 immature += subsidy;
208 } else {
209 mature += subsidy;
210 }
73a43918 211 it++;
d793f94b
JG
212 } else {
213 it = u->erase(it);
214 }
215 }
d793f94b 216
cb709831
JG
217 mined = minedBlocks.get();
218 orphaned = mined - u->size();
219 }
220
221 if (mined > 0) {
22ee0efe 222 std::string units = Params().CurrencyUnits();
0ddd6d1c 223 std::cout << "- " << strprintf(_("You have mined %d blocks!"), mined) << std::endl;
d793f94b
JG
224 std::cout << " "
225 << strprintf(_("Orphaned: %d blocks, Immature: %u %s, Mature: %u %s"),
226 orphaned,
227 FormatMoney(immature), units,
228 FormatMoney(mature), units)
229 << std::endl;
230 lines += 2;
d30273f9
JG
231 }
232 }
233 std::cout << std::endl;
234
235 return lines;
236}
237
db853f8a 238int printMessageBox(size_t cols)
4ace963c
JG
239{
240 boost::strict_lock_ptr<std::list<std::string>> u = messageBox.synchronize();
241
242 if (u->size() == 0) {
243 return 0;
244 }
245
db853f8a 246 int lines = 2 + u->size();
0ddd6d1c 247 std::cout << _("Messages:") << std::endl;
4ace963c
JG
248 for (auto it = u->cbegin(); it != u->cend(); ++it) {
249 std::cout << *it << std::endl;
db853f8a
JG
250 // Handle wrapped lines
251 lines += (it->size() / cols);
4ace963c 252 }
d30273f9 253 std::cout << std::endl;
db853f8a 254 return lines;
4ace963c
JG
255}
256
257int printInitMessage()
258{
259 if (loaded) {
260 return 0;
261 }
262
263 std::string msg = *initMessage;
0ddd6d1c 264 std::cout << _("Init message:") << " " << msg << std::endl;
d30273f9 265 std::cout << std::endl;
4ace963c 266
0ddd6d1c 267 if (msg == _("Done loading")) {
4ace963c
JG
268 loaded = true;
269 }
270
271 return 2;
272}
273
a6df7ab5
JG
274void ThreadShowMetricsScreen()
275{
276 // Make this thread recognisable as the metrics screen thread
277 RenameThread("zcash-metrics-screen");
278
3c024773 279 // Determine whether we should render a persistent UI or rolling metrics
83ccbf6b
JG
280 bool isTTY = isatty(STDOUT_FILENO);
281 bool isScreen = GetBoolArg("-metricsui", isTTY);
282 int64_t nRefresh = GetArg("-metricsrefreshtime", isTTY ? 1 : 600);
a6df7ab5 283
3c024773
JG
284 if (isScreen) {
285 // Clear screen
286 std::cout << "\e[2J";
a6df7ab5 287
3c024773
JG
288 // Print art
289 std::cout << METRICS_ART << std::endl;
290 std::cout << std::endl;
291
292 // Thank you text
293 std::cout << _("Thank you for running a Zcash node!") << std::endl;
294 std::cout << _("You're helping to strengthen the network and contributing to a social good :)") << std::endl;
295 std::cout << std::endl;
296 }
a6df7ab5 297
a6df7ab5 298 while (true) {
4ace963c 299 // Number of lines that are always displayed
d30273f9 300 int lines = 1;
c0876672 301 int cols = 80;
a6df7ab5 302
db853f8a 303 // Get current window size
83ccbf6b 304 if (isTTY) {
1da44b34
JT
305 struct winsize w;
306 w.ws_col = 0;
307 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1 && w.ws_col != 0) {
308 cols = w.ws_col;
309 }
c0876672 310 }
db853f8a 311
3c024773
JG
312 if (isScreen) {
313 // Erase below current position
314 std::cout << "\e[J";
315 }
a6df7ab5 316
848c89cd
JG
317 // Miner status
318 bool mining = GetBoolArg("-gen", false);
319
eb5b582e
JG
320 if (loaded) {
321 lines += printNetworkStats();
322 }
848c89cd 323 lines += printMiningStatus(mining);
000499ae 324 lines += printMetrics(cols, mining);
c0876672 325 lines += printMessageBox(cols);
4ace963c
JG
326 lines += printInitMessage();
327
3c024773
JG
328 if (isScreen) {
329 // Explain how to exit
330 std::cout << "[" << _("Press Ctrl+C to exit") << "] [" << _("Set 'showmetrics=0' to hide") << "]" << std::endl;
331 } else {
332 // Print delineator
e2752e1e 333 std::cout << "----------------------------------------" << std::endl;
3c024773 334 }
a6df7ab5 335
83ccbf6b
JG
336 int64_t nWaitEnd = GetTime() + nRefresh;
337 while (GetTime() < nWaitEnd) {
338 boost::this_thread::interruption_point();
339 MilliSleep(200);
340 }
a6df7ab5 341
3c024773
JG
342 if (isScreen) {
343 // Return to the top of the updating section
344 std::cout << "\e[" << lines << "A";
345 }
a6df7ab5
JG
346 }
347}
This page took 0.074143 seconds and 4 git commands to generate.