The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
metrics.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2003 - 2025
3 by David White <dave@whitevine.net>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16/**
17 * @file
18 * Various server-statistics.
19 */
20
22
24
25#include <algorithm>
26#include <ostream>
27
30 {
31 return a < b;
32 }
33};
34
36 bool operator()(const metrics::sample& a, const metrics::sample& b) const {
37 return a.processing_time < b.processing_time;
38 }
39};
40
42 : samples_()
43 , most_consecutive_requests_(0)
44 , current_requests_(0)
45 , nrequests_(0)
46 , nrequests_waited_(0)
47 , started_at_(std::chrono::steady_clock::now())
48 , terminations_()
49{
50}
51
53{
54 for(auto& s : samples_) {
55 delete[] s.name.begin();
56 }
57
58 samples_.clear();
59}
60
73
78
80 const std::chrono::steady_clock::duration& parsing_time,
81 const std::chrono::steady_clock::duration& processing_time)
82{
83 auto isample = std::lower_bound(samples_.begin(), samples_.end(), name,compare_samples_to_stringspan());
84 if(isample == samples_.end() || isample->name != name) {
85 //protect against DoS with memory exhaustion
86 if(samples_.size() > 30) {
87 return;
88 }
89 int index = std::distance(samples_.begin(), isample);
90 simple_wml::string_span dup_name(name.duplicate());
91 sample new_sample;
92 new_sample.name = dup_name;
93 samples_.insert(isample, new_sample);
94
95 isample = samples_.begin() + index;
96 }
97
98 isample->nsamples++;
99 isample->parsing_time += parsing_time;
100 isample->processing_time += processing_time;
101 isample->max_parsing_time = std::max(parsing_time,isample->max_parsing_time);
102 isample->max_processing_time = std::max(processing_time,isample->max_processing_time);
103}
104
105void metrics::game_terminated(const std::string& reason)
106{
107 terminations_[reason]++;
108}
109
110std::ostream& metrics::games(std::ostream& out) const
111{
112 if (terminations_.empty()) return out << "No game ended so far.";
113
114 std::size_t n = 0;
115 out << "Games have been terminated in the following ways:\n";
116 for(const auto& t : terminations_) {
117 out << t.first << ": " << t.second << "\n";
118 n += t.second;
119 }
120 out << "Total number of games = " << n;
121
122 return out;
123}
124
125std::ostream& metrics::requests(std::ostream& out) const
126{
127 if (samples_.empty()) return out;
128
129 std::vector<metrics::sample> ordered_samples = samples_;
130 std::sort(ordered_samples.begin(), ordered_samples.end(), compare_samples_by_time());
131
132 out << "\nSampled request types:\n";
133
134 std::size_t n = 0;
135 std::chrono::steady_clock::duration pa{0};
136 std::chrono::steady_clock::duration pr{0};
137 for(const auto& s : ordered_samples) {
138 out << "'" << s.name << "' called " << s.nsamples << " times "
139 << s.parsing_time.count() << "(" << s.max_parsing_time.count() << ") parsing time, "
140 << s.processing_time.count() << "(" << s.max_processing_time.count() << ") processing time\n";
141 n += s.nsamples;
142 pa += s.parsing_time;
143 pr += s.processing_time;
144 }
145 out << "Total number of request samples = " << n << "\n"
146 << "Total parsing time = " << pa.count() << "\n"
147 << "Total processing time = " << pr.count();
148
149 return out;
150}
151
152std::ostream& operator<<(std::ostream& out, metrics& met)
153{
154 const auto time_up = std::chrono::steady_clock::now() - met.started_at_;
155 auto [days, hours, minutes, seconds] = chrono::deconstruct_duration<chrono::days, std::chrono::hours, std::chrono::minutes, std::chrono::seconds>(time_up);
156
157 const int requests_immediate = met.nrequests_ - met.nrequests_waited_;
158 const int percent_immediate = (requests_immediate*100)/(met.nrequests_ > 0 ? met.nrequests_ : 1);
159 out << "METRICS\nUp " << days.count() << " days, " << hours.count() << " hours, "
160 << minutes.count() << " minutes, " << seconds.count() << " seconds\n"
161 << met.nrequests_ << " requests serviced. " << requests_immediate
162 << " (" << percent_immediate << "%) "
163 << "requests were serviced immediately.\n"
164 << "longest burst of requests was: " << met.most_consecutive_requests_;
165
166 return out;
167}
double t
std::map< std::string, int > terminations_
Definition metrics.hpp:68
void service_request()
Definition metrics.cpp:61
std::ostream & requests(std::ostream &out) const
Definition metrics.cpp:125
void no_requests()
Definition metrics.cpp:74
int nrequests_waited_
Definition metrics.hpp:66
std::ostream & games(std::ostream &out) const
Definition metrics.cpp:110
std::vector< sample > samples_
Definition metrics.hpp:61
int current_requests_
Definition metrics.hpp:64
int most_consecutive_requests_
Definition metrics.hpp:63
metrics()
Definition metrics.cpp:41
const std::chrono::steady_clock::time_point started_at_
Definition metrics.hpp:67
~metrics()
Definition metrics.cpp:52
void game_terminated(const std::string &reason)
Definition metrics.cpp:105
void record_sample(const simple_wml::string_span &name, const std::chrono::steady_clock::duration &parsing_time, const std::chrono::steady_clock::duration &processing_time)
Definition metrics.cpp:79
int nrequests_
Definition metrics.hpp:65
char * duplicate() const
const char * begin() const
std::ostream & operator<<(std::ostream &out, metrics &met)
Definition metrics.cpp:152
STL namespace.
bool operator()(const metrics::sample &a, const metrics::sample &b) const
Definition metrics.cpp:36
bool operator()(const simple_wml::string_span &a, const simple_wml::string_span &b) const
Definition metrics.cpp:29
std::chrono::steady_clock::duration processing_time
Definition metrics.hpp:50
simple_wml::string_span name
Definition metrics.hpp:47
static map_location::direction n
static map_location::direction s
#define b