CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_7_hltpatch2/src/EventFilter/SMProxyServer/src/SMPSWebPageHelper.cc

Go to the documentation of this file.
00001 // $Id: SMPSWebPageHelper.cc,v 1.3 2011/05/09 11:03:34 mommsen Exp $
00003 
00004 #include "EventFilter/SMProxyServer/interface/SMPSWebPageHelper.h"
00005 #include "EventFilter/StorageManager/interface/RegistrationCollection.h"
00006 #include "EventFilter/StorageManager/interface/Utils.h"
00007 #include "EventFilter/StorageManager/interface/XHTMLMonitor.h"
00008 #include "EventFilter/StorageManager/src/ConsumerWebPageHelper.icc"
00009 
00010 #include <boost/pointer_cast.hpp>
00011 
00012 
00013 namespace smproxy
00014 {
00015   SMPSWebPageHelper::SMPSWebPageHelper
00016   (
00017     xdaq::ApplicationDescriptor* appDesc,
00018     StateMachinePtr stateMachine
00019   ) :
00020   stor::WebPageHelper<SMPSWebPageHelper>(appDesc, "$Name: V03-03-00 $", this, &smproxy::SMPSWebPageHelper::addDOMforHyperLinks),
00021   stateMachine_(stateMachine),
00022   consumerWebPageHelper_(appDesc, "$Name: V03-03-00 $", this, &smproxy::SMPSWebPageHelper::addDOMforHyperLinks)
00023   { }
00024   
00025   
00026   void SMPSWebPageHelper::defaultWebPage(xgi::Output* out) const
00027   {
00028     stor::XHTMLMonitor theMonitor;
00029     stor::XHTMLMaker maker;
00030 
00031     stor::XHTMLMaker::Node* body = createWebPageBody(maker,
00032       "Main",
00033       stateMachine_->getExternallyVisibleStateName(),
00034       stateMachine_->getStateName(),
00035       stateMachine_->getReasonForFailed()
00036     );
00037 
00038     DataRetrieverMonitorCollection::SummaryStats summaryStats;
00039     stateMachine_->getStatisticsReporter()->
00040       getDataRetrieverMonitorCollection().getSummaryStats(summaryStats);
00041 
00042     addDOMforConnectionInfo(maker, body, summaryStats);
00043 
00044     maker.addNode("br", body);
00045 
00046     addDOMforThroughputPerEventType(maker, body, summaryStats);
00047     
00048     addDOMforHyperLinks(maker, body);
00049     
00050     // Dump the webpage to the output stream
00051     maker.out(*out);
00052   }
00053   
00054   
00055   void SMPSWebPageHelper::dataRetrieverWebPage(xgi::Output* out) const
00056   {
00057     stor::XHTMLMonitor theMonitor;
00058     stor::XHTMLMaker maker;
00059 
00060     stor::XHTMLMaker::Node* body = createWebPageBody(maker,
00061       "Data Retrieval",
00062       stateMachine_->getExternallyVisibleStateName(),
00063       stateMachine_->getStateName(),
00064       stateMachine_->getReasonForFailed()
00065     );
00066 
00067     addDOMforEventServers(maker, body);
00068     
00069     maker.addNode("hr", body);
00070     
00071     addDOMforDQMEventServers(maker, body);
00072     
00073     addDOMforHyperLinks(maker, body);
00074     
00075     // Dump the webpage to the output stream
00076     maker.out(*out);    
00077   } 
00078   
00079   
00080   void SMPSWebPageHelper::consumerStatisticsWebPage(xgi::Output* out) const
00081   {
00082     consumerWebPageHelper_.consumerStatistics(out,
00083       stateMachine_->getExternallyVisibleStateName(),
00084       stateMachine_->getStateName(),
00085       stateMachine_->getReasonForFailed(),
00086       stateMachine_->getStatisticsReporter(),
00087       stateMachine_->getRegistrationCollection(),
00088       stateMachine_->getEventQueueCollection(),
00089       stateMachine_->getDQMEventQueueCollection()
00090     );
00091   }
00092   
00093   
00094   void SMPSWebPageHelper::dqmEventStatisticsWebPage(xgi::Output* out) const
00095   {
00096     stor::XHTMLMonitor theMonitor;
00097     stor::XHTMLMaker maker;
00098 
00099     stor::XHTMLMaker::Node* body = createWebPageBody(maker,
00100       "DQM Event Processor",
00101       stateMachine_->getExternallyVisibleStateName(),
00102       stateMachine_->getStateName(),
00103       stateMachine_->getReasonForFailed()
00104     );
00105     
00106     const stor::DQMEventMonitorCollection& demc =
00107       stateMachine_->getStatisticsReporter()->getDQMEventMonitorCollection();
00108     addDOMforProcessedDQMEvents(maker, body, demc);
00109     addDOMforDQMEventStatistics(maker, body, demc);
00110 
00111     addDOMforHyperLinks(maker, body);
00112     
00113     // Dump the webpage to the output stream
00114     maker.out(*out);    
00115   } 
00116   
00117   
00118   void SMPSWebPageHelper::addDOMforHyperLinks
00119   (
00120     stor::XHTMLMaker& maker,
00121     stor::XHTMLMaker::Node *parent
00122   ) const
00123   {
00124     std::string url = appDescriptor_->getContextDescriptor()->getURL()
00125       + "/" + appDescriptor_->getURN();
00126     
00127     stor::XHTMLMaker::AttrMap linkAttr;
00128     stor::XHTMLMaker::Node *link;
00129     
00130     maker.addNode("hr", parent);
00131     
00132     linkAttr[ "href" ] = url;
00133     link = maker.addNode("a", parent, linkAttr);
00134     maker.addText(link, "Main web page");
00135     
00136     maker.addNode("hr", parent);
00137     
00138     linkAttr[ "href" ] = url + "/dataRetriever";
00139     link = maker.addNode("a", parent, linkAttr);
00140     maker.addText(link, "Data retriever web page");
00141     
00142     maker.addNode("hr", parent);
00143     
00144     linkAttr[ "href" ] = url + "/dqmEventStatistics";
00145     link = maker.addNode("a", parent, linkAttr);
00146     maker.addText(link, "DQM event processor statistics");
00147     
00148     maker.addNode("hr", parent);
00149     
00150     linkAttr[ "href" ] = url + "/consumerStatistics";
00151     link = maker.addNode("a", parent, linkAttr);
00152     maker.addText(link, "Consumer Statistics");
00153     
00154     maker.addNode("hr", parent);
00155   }
00156   
00157   
00158   void SMPSWebPageHelper::addDOMforConnectionInfo
00159   (
00160     stor::XHTMLMaker& maker,
00161     stor::XHTMLMaker::Node* parent,
00162     const DataRetrieverMonitorCollection::SummaryStats& summaryStats
00163   ) const
00164   {
00165     stor::XHTMLMaker::AttrMap colspanAttr;
00166     colspanAttr[ "colspan" ] = "2";
00167 
00168     stor::XHTMLMaker::AttrMap tableAttr = tableAttr_;
00169     tableAttr[ "width" ] = "50%";
00170 
00171     stor::XHTMLMaker::AttrMap widthAttr;
00172     widthAttr[ "width" ] = "70%";
00173  
00174     stor::XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr);
00175     
00176     stor::XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00177     stor::XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
00178     maker.addText(tableDiv, "Connection Information");
00179 
00180     // # of configured SMs
00181     tableRow = maker.addNode("tr", table, rowAttr_);
00182     tableDiv = maker.addNode("td", tableRow, widthAttr);
00183     maker.addText(tableDiv, "# of configured StorageManagers");
00184     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00185     const size_t configuredSMs = stateMachine_->getConfiguration()->
00186       getDataRetrieverParams().smRegistrationList_.size();
00187     maker.addInt(tableDiv, configuredSMs);
00188 
00189     // # of requested SMs connections
00190     tableRow = maker.addNode("tr", table, rowAttr_);
00191     tableDiv = maker.addNode("td", tableRow, widthAttr);
00192     maker.addText(tableDiv, "# of requested SM connections");
00193     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00194     maker.addInt(tableDiv, summaryStats.registeredSMs);
00195 
00196     // # of active SMs connections
00197     tableRow = maker.addNode("tr", table, rowAttr_);
00198     tableDiv = maker.addNode("td", tableRow, widthAttr);
00199     maker.addText(tableDiv, "# of active SM connections");
00200     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00201     maker.addInt(tableDiv, summaryStats.activeSMs);
00202 
00203     // # of connected event consumers
00204     tableRow = maker.addNode("tr", table, rowAttr_);
00205     tableDiv = maker.addNode("td", tableRow, widthAttr);
00206     maker.addText(tableDiv, "# of connected event consumers");
00207     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00208     stor::RegistrationCollection::ConsumerRegistrations consumers;
00209     stateMachine_->getRegistrationCollection()->
00210       getEventConsumers(consumers);
00211     maker.addInt(tableDiv, consumers.size());
00212 
00213     // # of connected DQM event (histogram) consumers
00214     tableRow = maker.addNode("tr", table, rowAttr_);
00215     tableDiv = maker.addNode("td", tableRow, widthAttr);
00216     maker.addText(tableDiv, "# of connected histogram consumers");
00217     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00218     stor::RegistrationCollection::DQMConsumerRegistrations dqmConsumers;
00219     stateMachine_->getRegistrationCollection()->
00220       getDQMEventConsumers(dqmConsumers);
00221     maker.addInt(tableDiv, dqmConsumers.size());
00222   }
00223   
00224   
00225   void SMPSWebPageHelper::addDOMforThroughputPerEventType
00226   (
00227     stor::XHTMLMaker& maker,
00228     stor::XHTMLMaker::Node* parent,
00229     const DataRetrieverMonitorCollection::SummaryStats& summaryStats
00230   ) const
00231   {
00232     stor::XHTMLMaker::AttrMap colspanAttr;
00233     colspanAttr[ "colspan" ] = "13";
00234     
00235     stor::XHTMLMaker::AttrMap subColspanAttr;
00236     
00237     stor::XHTMLMaker::AttrMap rowspanAttr;
00238     rowspanAttr[ "rowspan" ] = "3";
00239     rowspanAttr[ "width" ] = "30%";
00240 
00241     stor::XHTMLMaker::AttrMap noWrapAttr; 
00242     noWrapAttr[ "style" ] = "white-space: nowrap;";
00243 
00244     stor::XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
00245     stor::XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00246     stor::XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
00247     maker.addText(tableDiv, "Throughput");
00248     
00249     tableRow = maker.addNode("tr", table, rowAttr_);
00250     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
00251     maker.addText(tableDiv, "Requested Event Type");
00252     subColspanAttr[ "colspan" ] = "2";
00253     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00254     maker.addText(tableDiv, "");
00255     subColspanAttr[ "colspan" ] = "6";
00256     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00257     maker.addText(tableDiv, "Input");
00258     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00259     maker.addText(tableDiv, "Output");
00260 
00261     subColspanAttr[ "colspan" ] = "2";
00262     tableRow = maker.addNode("tr", table, rowAttr_);
00263     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00264     maker.addText(tableDiv, "Average Event Size (kB)");
00265     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00266     maker.addText(tableDiv, "Event Rate (Hz)");
00267     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00268     maker.addText(tableDiv, "Bandwidth (kB/s)");
00269     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00270     maker.addText(tableDiv, "Corrupted Event Rate (Hz)");
00271     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00272     maker.addText(tableDiv, "Event Rate (Hz)");
00273     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00274     maker.addText(tableDiv, "Bandwidth (kB/s)");
00275 
00276     tableRow = maker.addNode("tr", table, rowAttr_);
00277     tableDiv = maker.addNode("th", tableRow);
00278     maker.addText(tableDiv, "overall");
00279     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00280     maker.addText(tableDiv, "last 60 s");
00281     tableDiv = maker.addNode("th", tableRow);
00282     maker.addText(tableDiv, "overall");
00283     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00284     maker.addText(tableDiv, "last 60 s");
00285     tableDiv = maker.addNode("th", tableRow);
00286     maker.addText(tableDiv, "overall");
00287     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00288     maker.addText(tableDiv, "last 60 s");
00289     tableDiv = maker.addNode("th", tableRow);
00290     maker.addText(tableDiv, "overall");
00291     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00292     maker.addText(tableDiv, "last 60 s");
00293     tableDiv = maker.addNode("th", tableRow);
00294     maker.addText(tableDiv, "overall");
00295     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00296     maker.addText(tableDiv, "last 60 s");
00297     tableDiv = maker.addNode("th", tableRow);
00298     maker.addText(tableDiv, "overall");
00299     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00300     maker.addText(tableDiv, "last 60 s");
00301 
00302     if ( summaryStats.eventTypeStats.empty() )
00303     {
00304       stor::XHTMLMaker::AttrMap messageAttr = colspanAttr;
00305       messageAttr[ "align" ] = "center";
00306       
00307       stor::XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00308       stor::XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow, messageAttr);
00309       maker.addText(tableDiv, "No data flowing, yet.");
00310       return;
00311     }
00312     
00313     bool evenRow = false;
00314     
00315     for (DataRetrieverMonitorCollection::SummaryStats::EventTypeStatList::const_iterator
00316            it = summaryStats.eventTypeStats.begin(), itEnd = summaryStats.eventTypeStats.end();
00317          it != itEnd; ++it)
00318     {
00319       stor::XHTMLMaker::AttrMap rowAttr = rowAttr_;
00320       if( evenRow )
00321       {
00322         rowAttr[ "style" ] = "background-color:#e0e0e0;";
00323         evenRow = false;
00324       }
00325        else
00326       {
00327         evenRow = true;
00328       }
00329       stor::XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr);
00330       addRowForEventType(maker, tableRow, *it);
00331     }
00332 
00333     addSummaryRowForThroughput(maker, table, summaryStats);
00334   }
00335   
00336   
00337   void SMPSWebPageHelper::addRowForEventType
00338   (
00339     stor::XHTMLMaker& maker,
00340     stor::XHTMLMaker::Node* tableRow,
00341     DataRetrieverMonitorCollection::SummaryStats::EventTypeStats const& stats
00342   ) const
00343   {
00344     // Event type
00345     stor::XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00346     stor::XHTMLMaker::Node* pre = maker.addNode("pre", tableDiv);
00347     std::ostringstream eventType;
00348     stats.first->eventType(eventType);
00349     maker.addText(pre, eventType.str());
00350     
00351     // Average event size
00352     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00353     maker.addDouble(tableDiv, stats.second.sizeStats.getValueAverage(stor::MonitoredQuantity::FULL));
00354     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00355     maker.addDouble(tableDiv, stats.second.sizeStats.getValueAverage(stor::MonitoredQuantity::RECENT));
00356 
00357     // Input event rate
00358     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00359     maker.addDouble(tableDiv, stats.second.sizeStats.getSampleRate(stor::MonitoredQuantity::FULL));
00360     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00361     maker.addDouble(tableDiv, stats.second.sizeStats.getSampleRate(stor::MonitoredQuantity::RECENT));
00362 
00363     // Input bandwidth
00364     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00365     maker.addDouble(tableDiv, stats.second.sizeStats.getValueRate(stor::MonitoredQuantity::FULL));
00366     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00367     maker.addDouble(tableDiv, stats.second.sizeStats.getValueRate(stor::MonitoredQuantity::RECENT));
00368 
00369     // Input corrupted events rate
00370     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00371     maker.addDouble(tableDiv,
00372       stats.second.corruptedEventsStats.getSampleRate(stor::MonitoredQuantity::FULL));
00373     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00374     maker.addDouble(tableDiv,
00375       stats.second.corruptedEventsStats.getSampleRate(stor::MonitoredQuantity::RECENT));
00376 
00377     // Get statistics for consumers requesting this event type
00378     stor::QueueIDs queueIDs;
00379     bool isEventConsumer =
00380       stateMachine_->getDataManager()->getQueueIDsFromDataEventRetrievers(
00381         boost::dynamic_pointer_cast<stor::EventConsumerRegistrationInfo>(stats.first),
00382         queueIDs
00383       );
00384     if ( ! isEventConsumer)
00385     {
00386       stateMachine_->getDataManager()->getQueueIDsFromDQMEventRetrievers(
00387         boost::dynamic_pointer_cast<stor::DQMEventConsumerRegistrationInfo>(stats.first),
00388         queueIDs
00389       );
00390     }
00391 
00392     if ( queueIDs.empty() )
00393     {
00394       stor::XHTMLMaker::AttrMap noConsumersAttr = tableLabelAttr_;
00395       noConsumersAttr[ "colspan" ] = "4";
00396       tableDiv = maker.addNode("td", tableRow, noConsumersAttr);
00397       maker.addText(tableDiv, "no consumers connected");
00398       return;
00399     }
00400     
00401     const stor::EventConsumerMonitorCollection& ecmc =
00402       stateMachine_->getStatisticsReporter()->getEventConsumerMonitorCollection();
00403     const stor::DQMConsumerMonitorCollection& dcmc =
00404       stateMachine_->getStatisticsReporter()->getDQMConsumerMonitorCollection();
00405     const stor::ConsumerMonitorCollection& cmc =
00406       isEventConsumer ?
00407       static_cast<const stor::ConsumerMonitorCollection&>(ecmc) :
00408       static_cast<const stor::ConsumerMonitorCollection&>(dcmc);
00409     
00410     double rateOverall = 0;
00411     double rateRecent = 0;
00412     double bandwidthOverall = 0;
00413     double bandwidthRecent = 0;
00414 
00415     for ( stor::QueueIDs::const_iterator it = queueIDs.begin(),
00416             itEnd = queueIDs.end(); it != itEnd; ++it)
00417     {
00418       stor::MonitoredQuantity::Stats result;
00419       if ( cmc.getServed(*it, result) )
00420       {
00421         rateOverall += result.getSampleRate(stor::MonitoredQuantity::FULL);
00422         rateRecent += result.getSampleRate(stor::MonitoredQuantity::RECENT);
00423         bandwidthOverall += result.getValueRate(stor::MonitoredQuantity::FULL) / 1024;
00424         bandwidthRecent += result.getValueRate(stor::MonitoredQuantity::RECENT) / 1024;
00425       }
00426     }
00427 
00428     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00429     maker.addDouble(tableDiv, rateOverall);
00430     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00431     maker.addDouble(tableDiv, rateRecent);
00432     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00433     maker.addDouble(tableDiv, bandwidthOverall);
00434     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00435     maker.addDouble(tableDiv, bandwidthRecent);
00436   }
00437   
00438   
00439   void SMPSWebPageHelper::addSummaryRowForThroughput
00440   (
00441     stor::XHTMLMaker& maker,
00442     stor::XHTMLMaker::Node* table,
00443     const DataRetrieverMonitorCollection::SummaryStats& summaryStats
00444   ) const
00445   {
00446     stor::XHTMLMaker::Node* tableRow = maker.addNode("tr", table, specialRowAttr_);
00447     stor::XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00448     maker.addText(tableDiv, "Total");
00449 
00450     // Average event size
00451     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00452     maker.addDouble(tableDiv, summaryStats.totals.sizeStats.getValueAverage(stor::MonitoredQuantity::FULL));
00453     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00454     maker.addDouble(tableDiv, summaryStats.totals.sizeStats.getValueAverage(stor::MonitoredQuantity::RECENT));
00455 
00456     // Input event rate
00457     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00458     maker.addDouble(tableDiv, summaryStats.totals.sizeStats.getSampleRate(stor::MonitoredQuantity::FULL));
00459     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00460     maker.addDouble(tableDiv, summaryStats.totals.sizeStats.getSampleRate(stor::MonitoredQuantity::RECENT));
00461 
00462     // Input bandwidth
00463     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00464     maker.addDouble(tableDiv, summaryStats.totals.sizeStats.getValueRate(stor::MonitoredQuantity::FULL));
00465     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00466     maker.addDouble(tableDiv, summaryStats.totals.sizeStats.getValueRate(stor::MonitoredQuantity::RECENT));
00467 
00468     // Input corrupted events rate
00469     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00470     maker.addDouble(tableDiv, summaryStats.totals.corruptedEventsStats.getValueRate(stor::MonitoredQuantity::FULL));
00471     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00472     maker.addDouble(tableDiv, summaryStats.totals.corruptedEventsStats.getValueRate(stor::MonitoredQuantity::RECENT));
00473     
00474     const stor::EventConsumerMonitorCollection& ecmc =
00475       stateMachine_->getStatisticsReporter()->getEventConsumerMonitorCollection();
00476     const stor::DQMConsumerMonitorCollection& dcmc =
00477       stateMachine_->getStatisticsReporter()->getDQMConsumerMonitorCollection();
00478     stor::ConsumerMonitorCollection::TotalStats ecmcStats, dcmcStats;
00479     ecmc.getTotalStats(ecmcStats);
00480     dcmc.getTotalStats(dcmcStats);
00481 
00482     // Output event rate
00483     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00484     maker.addDouble(tableDiv,
00485       ecmcStats.servedStats.getSampleRate(stor::MonitoredQuantity::FULL) +
00486       dcmcStats.servedStats.getSampleRate(stor::MonitoredQuantity::FULL)
00487     );
00488     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00489     maker.addDouble(tableDiv,
00490       ecmcStats.servedStats.getSampleRate(stor::MonitoredQuantity::RECENT) +
00491       dcmcStats.servedStats.getSampleRate(stor::MonitoredQuantity::RECENT)
00492     );
00493     
00494     // Output bandwidth
00495     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00496     maker.addDouble(tableDiv,
00497       (ecmcStats.servedStats.getValueRate(stor::MonitoredQuantity::FULL) +
00498         dcmcStats.servedStats.getValueRate(stor::MonitoredQuantity::FULL)) / 1024
00499     );
00500     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00501     maker.addDouble(tableDiv,
00502       (ecmcStats.servedStats.getValueRate(stor::MonitoredQuantity::RECENT) +
00503         dcmcStats.servedStats.getValueRate(stor::MonitoredQuantity::RECENT)) / 1024
00504     );
00505   }
00506   
00507   
00508   void SMPSWebPageHelper::addDOMforEventServers
00509   (
00510     stor::XHTMLMaker& maker,
00511     stor::XHTMLMaker::Node* parent
00512   ) const
00513   {
00514     stor::XHTMLMaker::AttrMap colspanAttr;
00515     colspanAttr[ "colspan" ] = "14";
00516     
00517     stor::XHTMLMaker::Node* table = maker.addNode("table", parent, tableAttr_);
00518     
00519     stor::XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr_);
00520     stor::XHTMLMaker::Node* tableDiv = maker.addNode("th", tableRow, colspanAttr);
00521     maker.addText(tableDiv, "Event Servers");
00522     
00523     stor::XHTMLMaker::AttrMap rowspanAttr;
00524     rowspanAttr[ "rowspan" ] = "2";
00525     
00526     stor::XHTMLMaker::AttrMap subColspanAttr;
00527     subColspanAttr[ "colspan" ] = "2";
00528 
00529     stor::XHTMLMaker::AttrMap noWrapAttr; 
00530     noWrapAttr[ "style" ] = "white-space: nowrap;";
00531    
00532     // Header
00533     tableRow = maker.addNode("tr", table, specialRowAttr_);
00534     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
00535     maker.addText(tableDiv, "Hostname");
00536     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
00537     maker.addText(tableDiv, "Status");
00538     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
00539     maker.addText(tableDiv, "Requested Event Type");
00540     tableDiv = maker.addNode("th", tableRow, rowspanAttr);
00541     maker.addText(tableDiv, "Max Request Rate (Hz)");
00542     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00543     maker.addText(tableDiv, "Event Rate (Hz)");
00544     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00545     maker.addText(tableDiv, "Average Event Size (kB)");
00546     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00547     maker.addText(tableDiv, "Bandwidth (kB/s)");
00548     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00549     maker.addText(tableDiv, "Corrupted Events");
00550     tableDiv = maker.addNode("th", tableRow, subColspanAttr);
00551     maker.addText(tableDiv, "Corrupted Event Rate (Hz)");
00552 
00553     tableRow = maker.addNode("tr", table, specialRowAttr_);
00554     tableDiv = maker.addNode("th", tableRow);
00555     maker.addText(tableDiv, "overall");
00556     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00557     maker.addText(tableDiv, "last 60 s");
00558     tableDiv = maker.addNode("th", tableRow);
00559     maker.addText(tableDiv, "overall");
00560     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00561     maker.addText(tableDiv, "last 60 s");
00562     tableDiv = maker.addNode("th", tableRow);
00563     maker.addText(tableDiv, "overall");
00564     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00565     maker.addText(tableDiv, "last 60 s");
00566     tableDiv = maker.addNode("th", tableRow);
00567     maker.addText(tableDiv, "overall");
00568     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00569     maker.addText(tableDiv, "last 60 s");
00570     tableDiv = maker.addNode("th", tableRow);
00571     maker.addText(tableDiv, "overall");
00572     tableDiv = maker.addNode("th", tableRow, noWrapAttr);
00573     maker.addText(tableDiv, "last 60 s");
00574 
00575     DataRetrieverMonitorCollection::EventTypePerConnectionStatList eventTypePerConnectionStats;
00576     stateMachine_->getStatisticsReporter()->getDataRetrieverMonitorCollection()
00577       .getStatsByEventTypesPerConnection(eventTypePerConnectionStats);
00578 
00579     DataRetrieverMonitorCollection::ConnectionStats connectionStats;
00580     stateMachine_->getStatisticsReporter()->getDataRetrieverMonitorCollection()
00581       .getStatsByConnection(connectionStats);
00582 
00583     if ( eventTypePerConnectionStats.empty() )
00584     {
00585       stor::XHTMLMaker::AttrMap messageAttr = colspanAttr;
00586       messageAttr[ "align" ] = "center";
00587 
00588       tableRow = maker.addNode("tr", table, rowAttr_);
00589       tableDiv = maker.addNode("td", tableRow, messageAttr);
00590       maker.addText(tableDiv, "Not registered to any event servers yet");
00591       return;
00592     }
00593 
00594     bool evenRow = false;
00595 
00596     for (DataRetrieverMonitorCollection::EventTypePerConnectionStatList::const_iterator
00597            it = eventTypePerConnectionStats.begin(), itEnd = eventTypePerConnectionStats.end();
00598          it != itEnd; ++it)
00599     {
00600       stor::XHTMLMaker::AttrMap rowAttr = rowAttr_;
00601       if( evenRow )
00602       {
00603         rowAttr[ "style" ] = "background-color:#e0e0e0;";
00604         evenRow = false;
00605       }
00606       else
00607       {
00608         evenRow = true;
00609       }
00610       stor::XHTMLMaker::Node* tableRow = maker.addNode("tr", table, rowAttr);
00611       addRowForEventServer(maker, tableRow, *it);
00612       
00613       const std::string currentSourceURL = it->regPtr->sourceURL();
00614 
00615       if ( (it+1) == eventTypePerConnectionStats.end() ||
00616         (it+1)->regPtr->sourceURL() != currentSourceURL )
00617       {
00618         addSummaryRowForEventServer(maker, table,
00619           connectionStats.find(currentSourceURL));
00620       }
00621     }
00622   }
00623   
00624   
00625   void SMPSWebPageHelper::addRowForEventServer
00626   (
00627     stor::XHTMLMaker& maker,
00628     stor::XHTMLMaker::Node* tableRow,
00629     DataRetrieverMonitorCollection::EventTypePerConnectionStats const& stats
00630   ) const
00631   {
00632     stor::XHTMLMaker::Node* tableDiv;
00633 
00634     // Hostname
00635     addDOMforSMhost(maker, tableRow, stats.regPtr->sourceURL());
00636 
00637     // Status
00638     if ( stats.connectionStatus == DataRetrieverMonitorCollection::CONNECTED )
00639     {
00640       tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
00641       maker.addText(tableDiv, "Connected");
00642     }
00643     else
00644     {
00645       stor::XHTMLMaker::AttrMap statusAttr = tableLabelAttr_;
00646       statusAttr[ "style" ] = "color:brown;";
00647       tableDiv = maker.addNode("td", tableRow, statusAttr);
00648       std::ostringstream status;
00649       status << stats.connectionStatus;
00650       maker.addText(tableDiv, status.str());
00651     }
00652 
00653     // Requested event type
00654     tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
00655     stor::XHTMLMaker::Node* pre = maker.addNode("pre", tableDiv);
00656     std::ostringstream eventType;
00657     stats.regPtr->eventType(eventType);
00658     maker.addText(pre, eventType.str());
00659 
00660     // Max request rate
00661     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00662     const stor::utils::Duration_t interval =
00663       stats.regPtr->minEventRequestInterval();
00664     if ( interval.is_not_a_date_time() )
00665       maker.addText(tableDiv, "unlimited");
00666     else
00667       maker.addDouble(tableDiv, 1 / stor::utils::durationToSeconds(interval), 1);
00668 
00669     // Event rate
00670     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00671     maker.addDouble(tableDiv, stats.eventStats.sizeStats.getSampleRate(stor::MonitoredQuantity::FULL));
00672     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00673     maker.addDouble(tableDiv, stats.eventStats.sizeStats.getSampleRate(stor::MonitoredQuantity::RECENT));
00674 
00675     // Average event size
00676     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00677     maker.addDouble(tableDiv, stats.eventStats.sizeStats.getValueAverage(stor::MonitoredQuantity::FULL));
00678     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00679     maker.addDouble(tableDiv, stats.eventStats.sizeStats.getValueAverage(stor::MonitoredQuantity::RECENT));
00680     
00681     // Bandwidth
00682     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00683     maker.addDouble(tableDiv, stats.eventStats.sizeStats.getValueRate(stor::MonitoredQuantity::FULL));
00684     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00685     maker.addDouble(tableDiv, stats.eventStats.sizeStats.getValueRate(stor::MonitoredQuantity::RECENT));
00686     
00687     // Corrupted events counts
00688     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00689     maker.addDouble(tableDiv,
00690       stats.eventStats.corruptedEventsStats.getValueSum(stor::MonitoredQuantity::FULL), 0);
00691     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00692     maker.addDouble(tableDiv,
00693       stats.eventStats.corruptedEventsStats.getValueSum(stor::MonitoredQuantity::RECENT), 0);
00694     
00695     // Corrupted event rate
00696     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00697     maker.addDouble(tableDiv,
00698       stats.eventStats.corruptedEventsStats.getValueRate(stor::MonitoredQuantity::FULL));
00699     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00700     maker.addDouble(tableDiv,
00701       stats.eventStats.corruptedEventsStats.getValueRate(stor::MonitoredQuantity::RECENT));
00702   }
00703   
00704   
00705   void SMPSWebPageHelper::addSummaryRowForEventServer
00706   (
00707     stor::XHTMLMaker& maker,
00708     stor::XHTMLMaker::Node* table,
00709     DataRetrieverMonitorCollection::ConnectionStats::const_iterator pos
00710   ) const
00711   {
00712     stor::XHTMLMaker::Node* tableRow = maker.addNode("tr", table, specialRowAttr_);
00713     
00714     // Hostname
00715     addDOMforSMhost(maker, tableRow, pos->first);
00716 
00717     // Status, requst type, and max request rate not filled
00718     stor::XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow);
00719     tableDiv = maker.addNode("td", tableRow);
00720     tableDiv = maker.addNode("td", tableRow);
00721     
00722     // Event rate
00723     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00724     maker.addDouble(tableDiv, pos->second.sizeStats.getSampleRate(stor::MonitoredQuantity::FULL));
00725     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00726     maker.addDouble(tableDiv, pos->second.sizeStats.getSampleRate(stor::MonitoredQuantity::RECENT));
00727 
00728     // Average event size
00729     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00730     maker.addDouble(tableDiv, pos->second.sizeStats.getValueAverage(stor::MonitoredQuantity::FULL));
00731     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00732     maker.addDouble(tableDiv, pos->second.sizeStats.getValueAverage(stor::MonitoredQuantity::RECENT));
00733     
00734     // Bandwidth
00735     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00736     maker.addDouble(tableDiv, pos->second.sizeStats.getValueRate(stor::MonitoredQuantity::FULL));
00737     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00738     maker.addDouble(tableDiv, pos->second.sizeStats.getValueRate(stor::MonitoredQuantity::RECENT));
00739     
00740     // Corrupted events counts
00741     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00742     maker.addDouble(tableDiv,
00743       pos->second.corruptedEventsStats.getValueSum(stor::MonitoredQuantity::FULL), 0);
00744     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00745     maker.addDouble(tableDiv,
00746       pos->second.corruptedEventsStats.getValueSum(stor::MonitoredQuantity::RECENT), 0);
00747     
00748     // Corrupted event rate
00749     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00750     maker.addDouble(tableDiv,
00751       pos->second.corruptedEventsStats.getValueRate(stor::MonitoredQuantity::FULL));
00752     tableDiv = maker.addNode("td", tableRow, tableValueAttr_);
00753     maker.addDouble(tableDiv,
00754       pos->second.corruptedEventsStats.getValueRate(stor::MonitoredQuantity::RECENT));
00755   }
00756   
00757   
00758   void SMPSWebPageHelper::addDOMforSMhost
00759   (
00760     stor::XHTMLMaker& maker,
00761     stor::XHTMLMaker::Node* tableRow,
00762     const std::string& sourceURL
00763   ) const
00764   {
00765     stor::XHTMLMaker::Node* tableDiv = maker.addNode("td", tableRow, tableLabelAttr_);
00766     std::string::size_type startPos = sourceURL.find("//");
00767     if ( startPos == std::string::npos )
00768       startPos = 0; 
00769     else
00770       startPos += 2;
00771     const std::string::size_type endPos = sourceURL.find('.');
00772     const std::string hostname = sourceURL.substr(startPos,(endPos-startPos));
00773     stor::XHTMLMaker::AttrMap linkAttr;
00774     linkAttr[ "href" ] = sourceURL + "/consumerStatistics";
00775     stor::XHTMLMaker::Node* link = maker.addNode("a", tableDiv, linkAttr);
00776     maker.addText(link, hostname);
00777   }
00778   
00779   
00780   void SMPSWebPageHelper::addDOMforDQMEventServers
00781   (
00782     stor::XHTMLMaker& maker,
00783     stor::XHTMLMaker::Node* parent
00784   ) const
00785   {
00786   }
00787   
00788 } // namespace smproxy
00789 
00790