00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef ANA_STATS_HPP
00034 #define ANA_STATS_HPP
00035
00036 #include "timers.hpp"
00037
00038 namespace ana
00039 {
00040
00041 enum stat_type
00042 {
00043
00044 ACCUMULATED,
00045
00046
00047 SECONDS,
00048
00049
00050 MINUTES,
00051
00052
00053 HOURS,
00054
00055
00056 DAYS
00057 };
00058
00059
00060
00061
00062 struct stats
00063 {
00064 virtual ~stats() {}
00065
00066
00067 virtual size_t uptime() const = 0;
00068
00069
00070 virtual size_t packets_in() const = 0;
00071
00072
00073 virtual size_t packets_out() const = 0;
00074
00075
00076 virtual size_t bytes_in() const = 0;
00077
00078
00079 virtual size_t bytes_out() const = 0;
00080 };
00081
00082
00083 namespace detail
00084 {
00085 class stats_logger : public stats
00086 {
00087 public:
00088 stats_logger(size_t ms_to_reset, boost::asio::io_service& io_service) :
00089 started_at_( std::time(0) ),
00090 secs_to_reset_(ms_to_reset / 1000.0),
00091 timer_(io_service),
00092 start_time_( 0 ),
00093 packets_in_( 0 ),
00094 packets_out_( 0 ),
00095 bytes_in_( 0 ),
00096 bytes_out_( 0 )
00097 {
00098 if (secs_to_reset_ > 0 )
00099 {
00100 timer_.expires_from_now( secs_to_reset_ );
00101 timer_.async_wait(boost::bind( &stats_logger::reset, this,
00102 boost::asio::placeholders::error ) );
00103 }
00104 }
00105
00106 virtual ~stats_logger() {}
00107
00108 void log_send( detail::shared_buffer buffer )
00109 {
00110 ++packets_out_;
00111 bytes_out_ += buffer->size() + HEADER_LENGTH;
00112 }
00113
00114 void log_send( size_t size, bool finished_packet = false )
00115 {
00116 bytes_out_ += size;
00117 if (finished_packet)
00118 ++packets_out_;
00119 }
00120
00121 void log_receive( read_buffer buffer )
00122 {
00123 ++packets_in_;
00124 bytes_in_ += buffer->size();
00125 }
00126
00127 void log_receive( size_t size, bool finished_packet = false )
00128 {
00129 bytes_in_ += size;
00130 if (finished_packet)
00131 ++packets_in_;
00132 }
00133
00134 private:
00135 void reset(const boost::system::error_code& )
00136 {
00137 packets_in_ = 0;
00138 packets_out_ = 0;
00139 bytes_in_ = 0;
00140 bytes_out_ = 0;
00141
00142 if (secs_to_reset_ > 0 )
00143 {
00144 timer_.expires_from_now( secs_to_reset_ );
00145 timer_.async_wait(boost::bind( &stats_logger::reset, this,
00146 boost::asio::placeholders::error ) );
00147 }
00148 }
00149
00150 virtual size_t uptime() const
00151 {
00152 return std::time(0) - started_at_;
00153 }
00154
00155 virtual size_t packets_in() const
00156 {
00157 return packets_in_;
00158 }
00159
00160 virtual size_t packets_out() const
00161 {
00162 return packets_out_;
00163 }
00164
00165 virtual size_t bytes_in() const
00166 {
00167 return bytes_in_;
00168 }
00169
00170 virtual size_t bytes_out() const
00171 {
00172 return bytes_out_;
00173 }
00174
00175
00176 std::time_t started_at_;
00177
00178 double secs_to_reset_;
00179 boost_timer timer_;
00180
00181 std::time_t start_time_;
00182
00183 size_t packets_in_;
00184 size_t packets_out_;
00185
00186 size_t bytes_in_;
00187 size_t bytes_out_;
00188 };
00189 }
00190
00191 class stats_collector
00192 {
00193 public:
00194 stats_collector() :
00195 io_service_(),
00196 collector_thread_( NULL ),
00197 accumulator_( 0, io_service_),
00198 seconds_stats_( time::seconds(1), io_service_ ),
00199 minutes_stats_( time::minutes(1), io_service_ ),
00200 hours_stats_( time::hours(1), io_service_ ),
00201 days_stats_( time::days(1), io_service_ ),
00202 current_packet_in_size_(0),
00203 current_packet_out_size_(0),
00204 current_packet_in_(0),
00205 current_packet_out_(0),
00206 current_packet_in_max_(0),
00207 current_packet_out_max_(0),
00208 current_packet_in_total_(0),
00209 current_packet_out_total_(0)
00210 {
00211 collector_thread_ = new boost::thread( boost::bind(&boost::asio::io_service::run,
00212 &io_service_) );
00213 }
00214
00215 const stats* get_stats( stat_type type ) const
00216 {
00217 switch (type)
00218 {
00219 case ACCUMULATED : return &accumulator_;
00220 case SECONDS : return &seconds_stats_;
00221 case MINUTES : return &minutes_stats_;
00222 case HOURS : return &hours_stats_;
00223 case DAYS : return &days_stats_;
00224 }
00225 throw std::runtime_error("Wrong stat stype requested.");
00226 }
00227
00228 size_t current_packet_in_size() const { return current_packet_in_size_; }
00229 size_t current_packet_out_size() const { return current_packet_out_size_; }
00230
00231 size_t current_packet_in_last() const { return current_packet_in_; }
00232 size_t current_packet_in_max() const { return current_packet_in_max_; }
00233 size_t current_packet_in_total() const { return current_packet_in_total_; }
00234
00235 size_t current_packet_out_last() const { return current_packet_out_; }
00236 size_t current_packet_out_max() const { return current_packet_out_max_; }
00237 size_t current_packet_out_total() const { return current_packet_out_total_; }
00238
00239 void log_send( detail::shared_buffer buffer )
00240 {
00241 accumulator_.log_send ( buffer );
00242 seconds_stats_.log_send( buffer );
00243 minutes_stats_.log_send( buffer );
00244 hours_stats_.log_send ( buffer );
00245 days_stats_.log_send ( buffer );
00246
00247 log_current_packet_out(buffer->size(), true);
00248 }
00249
00250 void log_send( size_t size, bool finished_packet = false )
00251 {
00252 accumulator_.log_send ( size, finished_packet );
00253 seconds_stats_.log_send( size, finished_packet );
00254 minutes_stats_.log_send( size, finished_packet );
00255 hours_stats_.log_send ( size, finished_packet );
00256 days_stats_.log_send ( size, finished_packet );
00257
00258 log_current_packet_out(size, finished_packet);
00259 }
00260
00261
00262 void log_receive( read_buffer buffer )
00263 {
00264 accumulator_.log_receive ( buffer );
00265 seconds_stats_.log_receive( buffer );
00266 minutes_stats_.log_receive( buffer );
00267 hours_stats_.log_receive ( buffer );
00268 days_stats_.log_receive ( buffer );
00269
00270 log_current_packet_in(buffer->size(), true);
00271 }
00272
00273 void log_receive( size_t size, bool finished_packet = false )
00274 {
00275 accumulator_.log_receive ( size, finished_packet );
00276 seconds_stats_.log_receive( size, finished_packet );
00277 minutes_stats_.log_receive( size, finished_packet );
00278 hours_stats_.log_receive ( size, finished_packet );
00279 days_stats_.log_receive ( size, finished_packet );
00280
00281 log_current_packet_in(size, finished_packet);
00282 }
00283
00284 void start_send_packet( size_t size ) { current_packet_out_size_ = size; }
00285 void start_receive_packet( size_t size ) { current_packet_in_size_ = size; }
00286
00287 ~stats_collector()
00288 {
00289 io_service_.stop();
00290 collector_thread_->join();
00291 delete collector_thread_;
00292 }
00293
00294 private:
00295 void log_current_packet_in(size_t size,bool finished_packet)
00296 {
00297 if (finished_packet)
00298 {
00299 current_packet_in_ = 0;
00300 current_packet_in_max_ = 0;
00301 current_packet_in_total_ = 0;
00302 }
00303 else
00304 {
00305 current_packet_in_ = size;
00306 current_packet_in_max_ = (std::max)(size, current_packet_in_max_);
00307 current_packet_in_total_ += size;
00308 }
00309 }
00310 void log_current_packet_out(size_t size, bool finished_packet)
00311 {
00312 if (finished_packet)
00313 {
00314 current_packet_out_ = 0;
00315 current_packet_out_max_ = 0;
00316 current_packet_out_total_ = 0;
00317 }
00318 else
00319 {
00320 current_packet_out_ = size;
00321 current_packet_out_max_ = (std::max)(size, current_packet_out_max_);
00322 current_packet_out_total_ += size;
00323 }
00324 }
00325
00326
00327 boost::asio::io_service io_service_;
00328
00329 boost::thread* collector_thread_;
00330
00331 detail::stats_logger accumulator_;
00332 detail::stats_logger seconds_stats_;
00333 detail::stats_logger minutes_stats_;
00334 detail::stats_logger hours_stats_;
00335 detail::stats_logger days_stats_;
00336
00337 size_t current_packet_in_size_;
00338 size_t current_packet_out_size_;
00339
00340 size_t current_packet_in_;
00341 size_t current_packet_out_;
00342 size_t current_packet_in_max_;
00343 size_t current_packet_out_max_;
00344 size_t current_packet_in_total_;
00345 size_t current_packet_out_total_;
00346 };
00347
00348 }
00349
00350 #endif