The Battle for Wesnoth  1.19.7+dev
metrics.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2024
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 
23 #include "serialization/chrono.hpp"
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 
62 {
63  if(current_requests_ > 0) {
65  }
66 
67  ++nrequests_;
71  }
72 }
73 
75 {
77 }
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 
105 void metrics::game_terminated(const std::string& reason)
106 {
107  terminations_[reason]++;
108 }
109 
110 std::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 
125 std::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 
152 std::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::format::days_hours_mins_secs, 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
Definition: astarsearch.cpp:63
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
Definition: simple_wml.cpp:188
std::ostream & operator<<(std::ostream &out, metrics &met)
Definition: metrics.cpp:152
constexpr auto days_hours_mins_secs
Definition: chrono.hpp:89
constexpr auto deconstruct_duration(const std::tuple< Ts... > &, const std::chrono::duration< Rep, Period > &span)
Definition: chrono.hpp:76
std::chrono::duration< int, std::ratio< 86400 > > days
Definition: chrono.hpp:39
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
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