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