server/metrics.cpp

Go to the documentation of this file.
00001 /* $Id: metrics.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  * @file
00018  * Various server-statistics.
00019  */
00020 
00021 #include "../global.hpp"
00022 
00023 #include "metrics.hpp"
00024 
00025 #include <algorithm>
00026 #include <iostream>
00027 
00028 struct compare_samples_to_stringspan {
00029     bool operator()(const simple_wml::string_span& a, const simple_wml::string_span& b)
00030     {
00031         return a < b;
00032     }
00033 };
00034 
00035 struct compare_samples_by_time {
00036     bool operator()(const metrics::sample& a, const metrics::sample& b) const {
00037         return a.processing_time < b.processing_time;
00038     }
00039 };
00040 
00041 
00042 metrics::metrics() :
00043     samples_(),
00044     most_consecutive_requests_(0),
00045     current_requests_(0),
00046     nrequests_(0),
00047     nrequests_waited_(0),
00048     started_at_(time(NULL)),
00049     terminations_()
00050 {}
00051 
00052 metrics::~metrics()
00053 {
00054 
00055     for(std::vector<sample>::iterator itor = samples_.begin();
00056             itor != samples_.end(); ++itor)
00057     {
00058         delete[] itor->name.begin();
00059     }
00060     samples_.clear();
00061 }
00062 
00063 void metrics::service_request()
00064 {
00065     if(current_requests_ > 0) {
00066         ++nrequests_waited_;
00067     }
00068 
00069     ++nrequests_;
00070     ++current_requests_;
00071     if(current_requests_ > most_consecutive_requests_) {
00072         most_consecutive_requests_ = current_requests_;
00073     }
00074 }
00075 
00076 void metrics::no_requests()
00077 {
00078     current_requests_ = 0;
00079 }
00080 
00081 void metrics::record_sample(const simple_wml::string_span& name,
00082                             clock_t parsing_time, clock_t processing_time)
00083 {
00084     std::vector<sample>::iterator isample = std::lower_bound(samples_.begin(), samples_.end(), name,compare_samples_to_stringspan());
00085     if(isample == samples_.end()
00086         || isample->name != name) {
00087         //protect against DoS with memory exhaustion
00088         if(samples_.size() > 30) {
00089             return;
00090         }
00091         int index = isample - samples_.begin();
00092         simple_wml::string_span dup_name(name.duplicate());
00093         sample new_sample;
00094         new_sample.name = dup_name;
00095         samples_.insert(isample, new_sample);
00096 
00097         isample = samples_.begin() + index;
00098     }
00099 
00100     isample->nsamples++;
00101     isample->parsing_time += parsing_time;
00102     isample->processing_time += processing_time;
00103     isample->max_parsing_time = std::max(parsing_time,isample->max_parsing_time);
00104     isample->max_processing_time = std::max(processing_time,isample->max_processing_time);
00105 }
00106 
00107 void metrics::game_terminated(const std::string& reason)
00108 {
00109     terminations_[reason]++;
00110 }
00111 
00112 std::ostream& metrics::games(std::ostream& out) const
00113 {
00114     if (terminations_.empty()) return out << "No game ended so far.";
00115 
00116     size_t n = 0;
00117     out << "Games have been terminated in the following ways:\n";
00118     for(std::map<std::string,int>::const_iterator i = terminations_.begin(); i != terminations_.end(); ++i) {
00119         out << i->first << ": " << i->second << "\n";
00120         n += i->second;
00121     }
00122     out << "Total number of games = " << n;
00123 
00124     return out;
00125 }
00126 
00127 std::ostream& metrics::requests(std::ostream& out) const
00128 {
00129     if (samples_.empty()) return out;
00130 
00131     std::vector<metrics::sample> ordered_samples = samples_;
00132     std::sort(ordered_samples.begin(), ordered_samples.end(), compare_samples_by_time());
00133 
00134     out << "\nSampled request types:\n";
00135 
00136     size_t n = 0;
00137     size_t pa = 0;
00138     size_t pr = 0;
00139     for(std::vector<metrics::sample>::const_iterator s = ordered_samples.begin(); s != ordered_samples.end(); ++s) {
00140         out << "'" << s->name << "' called " << s->nsamples << " times "
00141             << s->parsing_time << "("<< s->max_parsing_time <<") parsing time, "
00142             << s->processing_time << "("<<s->max_processing_time<<") processing time\n";
00143         n += s->nsamples;
00144         pa += s->parsing_time;
00145         pr += s->processing_time;
00146     }
00147     out << "Total number of request samples = " << n << "\n"
00148         << "Total parsing time = " << pa << "\n"
00149         << "Total processing time = " << pr;
00150 
00151     return out;
00152 }
00153 
00154 std::ostream& operator<<(std::ostream& out, metrics& met)
00155 {
00156     const time_t time_up = time(NULL) - met.started_at_;
00157     const int seconds = time_up%60;
00158     const int minutes = (time_up/60)%60;
00159     const int hours = (time_up/(60*60))%24;
00160     const int days = time_up/(60*60*24);
00161     const int requests_immediate = met.nrequests_ - met.nrequests_waited_;
00162     const int percent_immediate = (requests_immediate*100)/(met.nrequests_ > 0 ? met.nrequests_ : 1);
00163     out << "METRICS\nUp " << days << " days, " << hours << " hours, "
00164         << minutes << " minutes, " << seconds << " seconds\n"
00165         << met.nrequests_ << " requests serviced. " << requests_immediate
00166         << " (" << percent_immediate << "%) "
00167         << "requests were serviced immediately.\n"
00168         << "longest burst of requests was: " << met.most_consecutive_requests_;
00169 
00170     return out;
00171 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:09 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs