00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "../global.hpp"
00019
00020 #include "metrics.hpp"
00021
00022 #include <algorithm>
00023 #include <time.h>
00024 #include <iostream>
00025
00026 static bool operator<(const metrics::sample& s, const simple_wml::string_span& name)
00027 {
00028 return s.name < name;
00029 }
00030
00031 static bool operator<(const simple_wml::string_span& name, const metrics::sample& s)
00032 {
00033 return name < s.name;
00034 }
00035
00036 struct compare_samples_by_time {
00037 bool operator()(const metrics::sample& a, const metrics::sample& b) const {
00038 return a.processing_time < b.processing_time;
00039 }
00040 };
00041
00042
00043 metrics::metrics() : most_consecutive_requests_(0),
00044 current_requests_(0), nrequests_(0),
00045 nrequests_waited_(0), started_at_(time(NULL))
00046 {}
00047
00048 metrics::~metrics()
00049 {
00050
00051 for(std::vector<sample>::iterator itor = samples_.begin();
00052 itor != samples_.end(); ++itor)
00053 {
00054 delete[] itor->name.begin();
00055 }
00056 samples_.clear();
00057 }
00058
00059 void metrics::service_request()
00060 {
00061 if(current_requests_ > 0) {
00062 ++nrequests_waited_;
00063 }
00064
00065 ++nrequests_;
00066 ++current_requests_;
00067 if(current_requests_ > most_consecutive_requests_) {
00068 most_consecutive_requests_ = current_requests_;
00069 }
00070 }
00071
00072 void metrics::no_requests()
00073 {
00074 current_requests_ = 0;
00075 }
00076
00077 void metrics::record_sample(const simple_wml::string_span& name,
00078 clock_t parsing_time, clock_t processing_time)
00079 {
00080 std::pair<std::vector<sample>::iterator,std::vector<sample>::iterator>
00081 range = std::equal_range(samples_.begin(), samples_.end(), name);
00082 if(range.first == range.second) {
00083
00084 if(samples_.size() > 30) {
00085 return;
00086 }
00087 int index = range.first - samples_.begin();
00088 simple_wml::string_span dup_name(name.duplicate());
00089 sample new_sample;
00090 new_sample.name = dup_name;
00091 new_sample.nsamples = 0;
00092 new_sample.parsing_time = 0;
00093 new_sample.processing_time = 0;
00094 samples_.insert(range.first, new_sample);
00095
00096 range.first = samples_.begin() + index;
00097 }
00098
00099 range.first->nsamples++;
00100 range.first->parsing_time += parsing_time;
00101 range.first->processing_time += processing_time;
00102 }
00103
00104 void metrics::game_terminated(const std::string& reason)
00105 {
00106 terminations_[reason]++;
00107 }
00108
00109 std::ostream& operator<<(std::ostream& out, metrics& met)
00110 {
00111 const time_t time_up = time(NULL) - met.started_at_;
00112 const int seconds = time_up%60;
00113 const int minutes = (time_up/60)%60;
00114 const int hours = (time_up/(60*60))%24;
00115 const int days = time_up/(60*60*24);
00116 const int requests_immediate = met.nrequests_ - met.nrequests_waited_;
00117 const int percent_immediate = (requests_immediate*100)/(met.nrequests_ > 0 ? met.nrequests_ : 1);
00118 out << "METRICS\nUp " << days << " days, " << hours << " hours, "
00119 << minutes << " minutes, " << seconds << " seconds\n"
00120 << met.nrequests_ << " requests serviced. " << requests_immediate
00121 << " (" << percent_immediate << "%) "
00122 << " requests were serviced immediately\n"
00123 << "longest burst of requests was " << met.most_consecutive_requests_ << "\n";
00124
00125 if(met.terminations_.empty() == false) {
00126 out << "Games have been terminated in the following ways: \n";
00127 for(std::map<std::string,int>::const_iterator i = met.terminations_.begin(); i != met.terminations_.end(); ++i) {
00128 out << i->first << ": " << i->second << "\n";
00129 }
00130 }
00131
00132 std::vector<metrics::sample> ordered_samples = met.samples_;
00133 std::sort(ordered_samples.begin(), ordered_samples.end(), compare_samples_by_time());
00134
00135 out << "\n\nRequest types:\n";
00136
00137 for(std::vector<metrics::sample>::const_iterator s = ordered_samples.begin(); s != ordered_samples.end(); ++s) {
00138 out << "'" << s->name << "' called " << s->nsamples << " times " << s->parsing_time << " parsing time, " << s->processing_time << " processing time\n";
00139 }
00140
00141 return out;
00142 }