Message statistics
authorEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sun, 13 Mar 2016 20:19:08 +0000 (21:19 +0100)
committerEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sun, 13 Mar 2016 20:19:08 +0000 (21:19 +0100)
Differenciate by command id to store statistics

16 files changed:
include/anna/diameter.comm/LocalServer.hpp
include/anna/diameter.comm/MessageStatistics.hpp [new file with mode: 0644]
include/anna/diameter.comm/Server.hpp
include/anna/diameter/helpers/defines.hpp
include/anna/statistics/Accumulator.hpp
include/anna/statistics/Engine.hpp
include/anna/statistics/Meter.hpp
source/diameter.comm/ClientSession.cpp
source/diameter.comm/Engine.cpp
source/diameter.comm/LocalServer.cpp
source/diameter.comm/MessageStatistics.cpp [new file with mode: 0644]
source/diameter.comm/Server.cpp
source/diameter.comm/ServerSession.cpp
source/statistics/Accumulator.cpp
source/statistics/Engine.cpp
source/statistics/Meter.cpp

index 2416e8c..e0ce97c 100644 (file)
 // STL
 #include <string>
 #include <vector>
+#include <map>
 
+// Project
 #include <anna/config/defines.hpp>
-#include <anna/statistics/Accumulator.hpp>
 #include <anna/diameter.comm/ServerSession.hpp>
+#include <anna/diameter/defines.hpp>
+#include <anna/diameter.comm/MessageStatistics.hpp>
 
 
 namespace anna {
@@ -65,9 +68,7 @@ class LocalServer {
   Engine *a_engine;
 
   // Statistics
-  int a_processing_time__StatisticConceptId; // request from local server (dpr's, etc.)
-  int a_received_message_size__StatisticConceptId;
-  anna::statistics::Accumulator *a_statisticsAccumulator;
+  MessageStatistics a_messageStatistics;
   void initializeStatisticResources() throw();
   void resetStatistics() throw();
 
@@ -351,10 +352,10 @@ public:
   anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
 
   // Statistics
-  void updateProcessingTimeStatisticConcept(const double &value) throw();
-  void updateReceivedMessageSizeStatisticConcept(const double &value) throw();
-  int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
-  int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
+  void updateProcessingTimeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw();
+  void updateReceivedMessageSizeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw();
+//  int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
+//  int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
 
 protected:
 
diff --git a/include/anna/diameter.comm/MessageStatistics.hpp b/include/anna/diameter.comm/MessageStatistics.hpp
new file mode 100644 (file)
index 0000000..9c502e2
--- /dev/null
@@ -0,0 +1,57 @@
+// ANNA - Anna is Not Nothingness Anymore                                                         //
+//                                                                                                //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
+//                                                                                                //
+// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+
+#ifndef anna_diameter_comm_MessageStatistics_hpp
+#define anna_diameter_comm_MessageStatistics_hpp
+
+// Standard
+#include <algorithm>
+#include <string>
+#include <map>
+
+// Project
+#include <anna/diameter/defines.hpp>
+#include <anna/statistics/Accumulator.hpp>
+
+namespace anna {
+
+namespace xml {
+  class Node;
+}
+
+namespace diameter {
+
+namespace comm {
+
+
+
+class MessageStatistics {
+
+  public:
+    MessageStatistics() {;}
+    ~MessageStatistics() {;}
+
+    struct ConceptType { enum _v { SentRequestProcessingTime, ReceivedMessageSize }; };
+
+    void initialize(const std::string &name) throw(anna::RuntimeException);
+    void process(const ConceptType::_v &conceptType, const anna::diameter::CommandId &cid, const double & value) throw(anna::RuntimeException);
+    anna::statistics::Accumulator *getAccumulator() const throw() { return a_accumulator; }
+  private:
+    anna::statistics::Accumulator *a_accumulator;
+    typedef std::pair<anna::diameter::CommandId, ConceptType::_v> ConceptId;
+    typedef std::map<ConceptId, int /* engine concept id */> concepts_map_t;
+    typedef std::map<ConceptId, int /* engine concept id */>::const_iterator concepts_map_it;
+    concepts_map_t a_concepts;
+};
+
+}
+}
+}
+
+#endif
index 69f5e80..6735e5f 100644 (file)
 // STL
 #include <string>
 #include <vector>
+#include <map>
 
+// Project
 #include <anna/core/util/Millisecond.hpp>
 #include <anna/core/RuntimeException.hpp>
-
 #include <anna/diameter/defines.hpp>
 #include <anna/config/defines.hpp>
 #include <anna/diameter.comm/ClassCode.hpp>
-#include <anna/statistics/Accumulator.hpp>
+#include <anna/diameter.comm/MessageStatistics.hpp>
+
+
 
 
 namespace anna {
@@ -71,9 +74,7 @@ class Server {
   Engine *a_engine;
 
   // Statistics
-  int a_processing_time__StatisticConceptId;
-  int a_received_message_size__StatisticConceptId;
-  anna::statistics::Accumulator *a_statisticsAccumulator;
+  MessageStatistics a_messageStatistics;
   void initializeStatisticResources() throw();
   void resetStatistics() throw();
 
@@ -267,10 +268,10 @@ public:
 
 
   // Statistics
-  void updateProcessingTimeStatisticConcept(const double &value) throw();
-  void updateReceivedMessageSizeStatisticConcept(const double &value) throw();
-  int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
-  int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
+  void updateProcessingTimeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw();
+  void updateReceivedMessageSizeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw();
+//  int getProcessingTimeStatisticConcept() const throw() { return a_processing_time__StatisticConceptId; }
+//  int getReceivedMessageSizeStatisticConcept() const throw() { return a_received_message_size__StatisticConceptId; }
 
 protected:
 
index 2c8cbfd..9f4e1f7 100644 (file)
@@ -63,6 +63,9 @@ namespace helpers {
 /** Generic AVP */
 static const AvpId AVPID__AVP(0, 0);
 
+/** Reserved Generic COMMAND */
+//static const AvpId COMMANDID__COMMAND(0, 0);
+
 /**
 * Vendors
 * http://www.iana.org/assignments/enterprise-numbers
index c13bbf1..d86c65f 100644 (file)
@@ -85,6 +85,23 @@ typedef std::map <int, _concept_data_t>::const_iterator _concept_data_map_iter;
  * @short Contains statistical sample information
  */
 class Accumulator {
+
+  std::string a_name;
+
+  void initialize(const int & conceptId) throw();
+  _concept_data_t * getConcept(const int & conceptId) const throw(anna::RuntimeException);
+  // Gets the data structure for a existing concept Id.
+  // Initializes and returns the new data structure for a new stored concept Id which is valid (exists for the engine).
+  // Launch exception if concept id is not a valid concept registered at Engine.
+
+  /*mutable */_concept_data_map_t a_concept_data_map;
+
+  std::string floatFormat(const int & numberOfDecimals) const throw();
+
+  double getStandardDeviation(const _concept_data_t * conceptData) const throw(anna::RuntimeException);
+  double getBesselStandardDeviation(const _concept_data_t * conceptData) const throw(anna::RuntimeException);
+
+
 public:
 
   /**
@@ -97,7 +114,15 @@ public:
   /**
   * Destructor.
   */
-  ~Accumulator();
+  ~Accumulator() {;}
+
+
+  /**
+   * Sets the accumulator name
+   *
+   * @param name Name provided
+   */
+  void setName(const std::string &name) throw() { a_name = name; }
 
   /**
   * Adds a new statistic concept through the accumulator, to ease the concept name creation,
@@ -109,14 +134,15 @@ public:
   *                            (is more intuitive 850 msecs than 0,850 secs). Then, it is @em true by default.
   *                            This is useful to advice better representation for some indicators like minimum/maximum
   *                             within integer samples.
+  * @param conceptNameFormat Format to register the complete concept name. Will be parsed using (in order) the provided
+  *                          description, and the accumulator name: '<concept description> [<accumulator name>]' by default.
   *
   * @return Assigned concept identification number (sequence)
   */
-  int addConcept(const std::string & description, const std::string & unit, const bool & integerNatureSample = true) throw();
-
+  int addConcept(const std::string & description, const std::string & unit, const bool & integerNatureSample = true, const char *conceptNameFormat = "%s [%s]") throw();
 
   /**
-  * Process new value for the sample.
+  * Process new value for the sample regarding a concept identifier previously registered through the engine.
   *
   * @param conceptId statistical concept processed
   * @param value Value for processed item
@@ -157,6 +183,13 @@ public:
 
   // Gets
 
+  /**
+   * Gets the accumulator name
+   *
+   * @result Accumulator name
+   */
+  const std::string &getName() const throw() { return a_name; }
+
   /**
   * Gets current sample size for any concept id
   *
@@ -202,23 +235,6 @@ public:
   * @return XML with class content
   */
   anna::xml::Node* asXML(anna::xml::Node* parent, const int & numberOfDecimals = 2) const throw();
-
-
-private:
-
-  std::string a_name;
-
-  void initialize(const int & conceptId) throw();
-  _concept_data_t * getConcept(const int & conceptId) const throw(anna::RuntimeException);
-  // Return NULL if no data is found for the concept Id
-  // Launch exception if concept id is not a valid concept registered at Engine
-
-  /*mutable */_concept_data_map_t a_concept_data_map;
-
-  std::string floatFormat(const int & numberOfDecimals) const throw();
-
-  double getStandardDeviation(const _concept_data_t * conceptData) const throw(anna::RuntimeException);
-  double getBesselStandardDeviation(const _concept_data_t * conceptData) const throw(anna::RuntimeException);
 };
 
 }
index 61a9fe6..5300cfa 100644 (file)
 
 #include <anna/core/Singleton.hpp>
 #include <anna/core/util/Millisecond.hpp>
+#include <anna/core/RuntimeException.hpp>
 #include <anna/core/mt/Mutex.hpp>
 
 // Standard
 #include <string>
-#include <vector>
 #include <map>
 
 // Local
@@ -34,6 +34,9 @@ namespace anna {
 namespace statistics {
 
 
+class Accumulator;
+
+
 typedef struct {
 
   std::string SampleFile; // Sample file to optional writtings
@@ -47,8 +50,9 @@ typedef std::map <int, _concept_identification_t> _concept_identification_map_t;
 typedef std::map <int, _concept_identification_t>::const_iterator _concept_identification_map_iter;
 typedef std::map <int, _concept_identification_t>::iterator _concept_identification_map_nc_iter;
 
-typedef std::vector <Accumulator*> _accumulator_vector_t;
-typedef std::vector <Accumulator*>::const_iterator _accumulator_vector_it;
+typedef std::map <std::string, Accumulator*> _accumulator_map_t;
+typedef std::map <std::string, Accumulator*>::const_iterator _accumulator_map_it;
+typedef std::map <std::string, Accumulator*>::iterator _accumulator_map_nc_it;
 
 
 /**
@@ -137,16 +141,26 @@ public:
   */
   bool enabled(void) const throw() { return (a_enabled); }
 
+
   /**
-  * There is an advantage creating Accumulators over the engine: the #asXML method will show all the controlled information
-  * easily. Anyway, you could allocate this class objects without using this. Then, this is a helper to create accumulators
-  * and centralize their reports.
-  *
-  * @param name Accumulator name
-  *
-  * @return New allocated accumulator, to be used by the client
-  */
-  Accumulator *createAccumulator(const std::string &name) throw();
+   * Creates a statistic accumulator
+   *
+   * @param name Accumulator name
+   *
+   * \return The accumulator created or exception when already exists for the provided name.
+   */
+  Accumulator *createAccumulator(const std::string &name) throw(anna::RuntimeException);
+
+  /**
+   * Returns accumulator instance identified by name.
+   *
+   * \param name Accumulator name
+   *
+   * \return The accumulator instance identified by name provided, NULL if not found
+   */
+  Accumulator* getAccumulator(const std::string &name) throw();
+
+
 
   /**
   * Class string representation
@@ -171,7 +185,7 @@ private:
   Engine(); // private constructor
 
   _concept_identification_map_t a_concept_identification_map;
-  _accumulator_vector_t a_accumulators; // you could create accumulators regardless the engine, but this is easier and asXML will show all the information easily
+  _accumulator_map_t a_accumulators; // you could create accumulators regardless the engine, but this is easier and asXML will show all the information easily
   bool a_enabled;
   int a_sequence_concept_id;
   anna::Mutex a_mutex; // for logSample
index ada8afb..82f3ee3 100644 (file)
@@ -48,7 +48,7 @@ public:
   /**
   * Constructor.
   */
-  Meter(const std::string & description);
+  Meter(const std::string & name);
 
   /**
   * Destructor.
index 83c286c..87c9cc1 100644 (file)
@@ -510,12 +510,13 @@ throw(anna::RuntimeException) {
       }
     }
 );
+
   // Main counters:
   OamModule &oamModule = OamModule::instantiate();
   oamModule.count(isRequest ? OamModule::Counter::RequestReceived : OamModule::Counter::AnswerReceived);
   oamModule.count(isRequest ? OamModule::Counter::RequestReceivedOnClientSession : OamModule::Counter::AnswerReceivedOnClientSession);
   // Statistic (size)
-  a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize()); // only on reception (application could manage sent sizes)
+  a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize(), cid); // only on reception (application could manage sent sizes)
 
   if(isRequest) {
     /////////////////////////////
@@ -678,14 +679,14 @@ throw(anna::RuntimeException) {
   anna::Millisecond current = (anna::Millisecond)anna::functions::millisecond();
   anna::Millisecond request = response->getRequest()->getRequestTimestampMs();
   anna::Millisecond timeToAnswerMs = current - request;
-  a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs);
-  LOGDEBUG
-  (
-    std::string msg = "This diameter request context lasted ";
-    msg += anna::functions::asString(timeToAnswerMs);
-    msg += " milliseconds at diameter server (included network time)";
-    anna::Logger::debug(msg, ANNA_FILE_LOCATION);
-  );
+  a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs, cid);
+  //LOGDEBUG
+  //(
+  //  std::string msg = "This diameter request context lasted ";
+  //  msg += anna::functions::asString(timeToAnswerMs);
+  //  msg += " milliseconds at diameter server (included network time)";
+  //  anna::Logger::debug(msg, ANNA_FILE_LOCATION);
+  //);
   // Progress origin for tracking purposes on asyncronous boxes with both diameter interfaces (entities and clients)
   Message * requestMessage = const_cast<Message*>(response->getRequest());
   requestMessage->setRequestServerSessionKey(response->getRequest()->getRequestServerSessionKey()); // -1 means unkown/unset
index 584ccfa..d43da75 100644 (file)
@@ -16,7 +16,6 @@
 #include <anna/comm/Network.hpp>
 #include <anna/comm/Host.hpp>
 #include <anna/comm/ClientSocket.hpp>
-
 #include <anna/diameter.comm/Transport.hpp>
 #include <anna/diameter.comm/Engine.hpp>
 #include <anna/diameter.comm/Entity.hpp>
index 6374182..0e2bc2e 100644 (file)
@@ -43,8 +43,7 @@ LocalServer::LocalServer() :
   a_category(0),
   a_lock(false),
   a_available(false),
-  a_lastUsedResource(NULL),
-  a_statisticsAccumulator(NULL) {}
+  a_lastUsedResource(NULL) {}
 
 
 void LocalServer::initializeStatisticResources() throw() {
@@ -55,26 +54,23 @@ void LocalServer::initializeStatisticResources() throw() {
   accName += "' and origin-host '";
   accName += a_engine ? a_engine->getOriginHost() : "unknown"; // it should be known (createServer)
   accName += "'";
-  a_statisticsAccumulator = anna::statistics::Engine::instantiate().createAccumulator(accName);
-  a_processing_time__StatisticConceptId = a_statisticsAccumulator->addConcept("Diameter requests processing time at clients connected to", "ms", true/* integer values */);
-  a_received_message_size__StatisticConceptId = a_statisticsAccumulator->addConcept("Diameter message sizes received from clients connected to", "bytes", true/* integer values */);
+  a_messageStatistics.initialize(accName);
 }
 
 void LocalServer::resetStatistics() throw() {
-  a_statisticsAccumulator->reset();
+  a_messageStatistics.getAccumulator()->reset();
 }
 
-void LocalServer::updateProcessingTimeStatisticConcept(const double &value) throw() {
-  a_statisticsAccumulator->process(a_processing_time__StatisticConceptId, value);
-  LOGDEBUG(anna::Logger::debug(a_statisticsAccumulator->asString(), ANNA_FILE_LOCATION));
+void LocalServer::updateProcessingTimeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw() {
+  a_messageStatistics.process(MessageStatistics::ConceptType::SentRequestProcessingTime, cid, value);
+  LOGDEBUG(anna::Logger::debug(a_messageStatistics.getAccumulator()->asString(), ANNA_FILE_LOCATION));
 }
 
-void LocalServer::updateReceivedMessageSizeStatisticConcept(const double &value) throw() {
-  a_statisticsAccumulator->process(a_received_message_size__StatisticConceptId, value);
-  //LOGDEBUG(anna::Logger::debug(a_statisticsAccumulator->asString(), ANNA_FILE_LOCATION));
+void LocalServer::updateReceivedMessageSizeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw() {
+  a_messageStatistics.process(MessageStatistics::ConceptType::ReceivedMessageSize, cid, value);
+  LOGDEBUG(anna::Logger::debug(a_messageStatistics.getAccumulator()->asString(), ANNA_FILE_LOCATION));
 }
 
-
 ServerSession* LocalServer::allocateServerSession() throw() { return a_serverSessionsRecycler.create(); }
 void LocalServer::releaseServerSession(ServerSession *serverSession) throw() { a_serverSessionsRecycler.release(serverSession); }
 
@@ -400,7 +396,7 @@ void LocalServer::setClassCodeTimeout(const ClassCode::_v v, const anna::Millise
 }
 
 void LocalServer::setMaxConnections(int maxConnections) throw(anna::RuntimeException) {
-  LOGMETHOD(anna::TraceMethod tttm("diameter::comm::LocalServer", "setMaxConnections", ANNA_FILE_LOCATION));
+  LOGMETHOD(anna::TraceMethod tttm("anna::diameter::comm::LocalServer", "setMaxConnections", ANNA_FILE_LOCATION));
 
   // Negative & initial
   if(maxConnections < 0) {
@@ -576,7 +572,7 @@ std::string LocalServer::asString() const throw() {
   result += " | Last Outgoing Activity Time: ";
   result += a_lastOutgoingActivityTime.asString();
 //   result += "\n";
-//   result += a_statisticsAccumulator->asString();
+//   result += a_messageStatistics.getAccumulator()->asString();
   // ServerSessions only in xml
   return result += " }";
 }
@@ -600,8 +596,8 @@ anna::xml::Node* LocalServer::asXML(anna::xml::Node* parent) const throw() {
   result->createAttribute("LastIncomingActivityTime", a_lastIncomingActivityTime.asString());
   result->createAttribute("LastOutgoingActivityTime", a_lastOutgoingActivityTime.asString());
   // Statistics
-  anna::xml::Node* stats = result->createChild("Statistics");
-  a_statisticsAccumulator->asXML(stats);
+  anna::xml::Node* stats = result->createChild("MessageStatistics");
+  a_messageStatistics.getAccumulator()->asXML(stats);
   anna::xml::Node* serverSessions = result->createChild("ServerSessions"); // LocalServer.ServerSessions
 
   for(const_serverSession_iterator it = serverSession_begin(); it != serverSession_end(); it++)
diff --git a/source/diameter.comm/MessageStatistics.cpp b/source/diameter.comm/MessageStatistics.cpp
new file mode 100644 (file)
index 0000000..00ba91a
--- /dev/null
@@ -0,0 +1,57 @@
+// ANNA - Anna is Not Nothingness Anymore                                                         //
+//                                                                                                //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
+//                                                                                                //
+// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+// Standard
+#include <string>
+
+// Project
+#include <anna/diameter.comm/MessageStatistics.hpp>
+#include <anna/statistics/Engine.hpp>
+#include <anna/diameter/functions.hpp>
+#include <anna/diameter/helpers/defines.hpp>
+#include <anna/diameter/codec/Message.hpp>
+#include <anna/diameter/codec/Engine.hpp>
+#include <anna/diameter/codec/EngineManager.hpp>
+
+
+void anna::diameter::comm::MessageStatistics::initialize(const std::string &name) throw(anna::RuntimeException) {
+  a_accumulator = anna::statistics::Engine::instantiate().createAccumulator(name);
+}
+
+
+void anna::diameter::comm::MessageStatistics::process(const ConceptType::_v &conceptType, const anna::diameter::CommandId &cid, const double & value) throw(anna::RuntimeException) {
+
+  // Development issue:
+//  if (!a_accumulator) {
+//    LOGWARNING(anna::Logger::warning("Cannot process uninitialized 'MessageStatistics' instance", ANNA_FILE_LOCATION));
+//    return;
+//  }
+
+  // retrieve the concept id for the pair:
+  ConceptId conceptId(cid, conceptType);
+  int engine_concept_id = 0;
+  concepts_map_it it = a_concepts.find(conceptId);
+  if (it != a_concepts.end()) { // found
+    engine_concept_id = it->second;
+  }
+  else { // register a new concept id
+    std::string description;
+    if(conceptType == ConceptType::SentRequestProcessingTime) {
+      description = anna::functions::asString("Processing time for outgoing requests (code = %d)", cid.first);
+    }
+    else if (conceptType == ConceptType::ReceivedMessageSize) {
+      description = "Message size for received messages ";
+      description += anna::diameter::functions::commandIdAsPairString(cid);
+    }
+
+    engine_concept_id = a_accumulator->addConcept(description, "ms", true/* integer values */);
+    a_concepts[conceptId] = engine_concept_id;
+  }
+
+  a_accumulator->process(engine_concept_id, value);
+}
+
index cfefec1..1ba8356 100644 (file)
@@ -36,7 +36,6 @@ void Server::initialize() throw() {
   a_maxClientSessions = 1; // mono client connection
   a_lastIncomingActivityTime = (anna::Millisecond)0;
   a_lastOutgoingActivityTime = (anna::Millisecond)0;
-  a_statisticsAccumulator = NULL;
   a_lastUsedResource = NULL;
 }
 
@@ -48,23 +47,21 @@ void Server::initializeStatisticResources() throw() {
   accName += "' and origin-host '";
   accName += a_engine ? a_engine->getOriginHost() : "unknown"; // it should be known (createServer)
   accName += "'";
-  a_statisticsAccumulator = anna::statistics::Engine::instantiate().createAccumulator(accName);
-  a_processing_time__StatisticConceptId = a_statisticsAccumulator->addConcept("Diameter requests processing time at", "ms", true/* integer values */);
-  a_received_message_size__StatisticConceptId = a_statisticsAccumulator->addConcept("Diameter message sizes received from", "bytes", true/* integer values */);
+  a_messageStatistics.initialize(accName);
 }
 
 void Server::resetStatistics() throw() {
-  a_statisticsAccumulator->reset();
+  a_messageStatistics.getAccumulator()->reset();
 }
 
-void Server::updateProcessingTimeStatisticConcept(const double &value) throw() {
-  a_statisticsAccumulator->process(a_processing_time__StatisticConceptId, value);
-  LOGDEBUG(anna::Logger::debug(a_statisticsAccumulator->asString(), ANNA_FILE_LOCATION));
+void Server::updateProcessingTimeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw() {
+  a_messageStatistics.process(MessageStatistics::ConceptType::SentRequestProcessingTime, cid, value);
+  LOGDEBUG(anna::Logger::debug(a_messageStatistics.getAccumulator()->asString(), ANNA_FILE_LOCATION));
 }
 
-void Server::updateReceivedMessageSizeStatisticConcept(const double &value) throw() {
-  a_statisticsAccumulator->process(a_received_message_size__StatisticConceptId, value);
-  //LOGDEBUG(anna::Logger::debug(a_statisticsAccumulator->asString(), ANNA_FILE_LOCATION));
+void Server::updateReceivedMessageSizeStatisticConcept(const double &value, const anna::diameter::CommandId &cid) throw() {
+  a_messageStatistics.process(MessageStatistics::ConceptType::ReceivedMessageSize, cid, value);
+  LOGDEBUG(anna::Logger::debug(a_messageStatistics.getAccumulator()->asString(), ANNA_FILE_LOCATION));
 }
 
 
@@ -281,7 +278,7 @@ std::string Server::asString() const throw() {
   result += " | Hidden: ";
   result += (hidden() ? "yes" : "no");
   result += "\n";
-  result += a_statisticsAccumulator->asString();
+  result += a_messageStatistics.getAccumulator()->asString();
 
   for(std::vector<ClientSession*>::const_iterator it = begin(); it != end(); it++) {
     result += "\n";
@@ -305,7 +302,7 @@ anna::xml::Node* Server::asXML(anna::xml::Node* parent) const throw() {
   result->createAttribute("Hidden", hidden() ? "yes" : "no");
   // Statistics
   anna::xml::Node* stats = result->createChild("Statistics");
-  a_statisticsAccumulator->asXML(stats);
+  a_messageStatistics.getAccumulator()->asXML(stats);
   anna::xml::Node* clientSessions = result->createChild("Server.ClientSessions");
 
   for(std::vector<ClientSession*>::const_iterator it = begin(); it != end(); it++)
index ad0b15a..ef58f68 100644 (file)
@@ -378,7 +378,7 @@ throw(anna::RuntimeException) {
   oamModule.count(isRequest ? OamModule::Counter::RequestReceived : OamModule::Counter::AnswerReceived);
   oamModule.count(isRequest ? OamModule::Counter::RequestReceivedOnServerSession : OamModule::Counter::AnswerReceivedOnServerSession);
   // Statistic (size)
-  a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize()); // only on reception (application could manage sent sizes)
+  a_parent->updateReceivedMessageSizeStatisticConcept(message.getSize(), cid); // only on reception (application could manage sent sizes)
 
   if(isRequest) {
     // Si recibo un request, el message solo tiene fiable el DataBlock. Como por defecto se construye como ApplicationMessage,
@@ -503,14 +503,14 @@ throw(anna::RuntimeException) {
   anna::Millisecond current = (anna::Millisecond)anna::functions::millisecond();
   anna::Millisecond request = response->getRequest()->getRequestTimestampMs();
   anna::Millisecond timeToAnswerMs = current - request;
-  a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs);
-  LOGDEBUG
-  (
-    std::string msg = "This diameter request context lasted ";
-    msg += anna::functions::asString(timeToAnswerMs);
-    msg += " milliseconds at diameter client (included network time)";
-    anna::Logger::debug(msg, ANNA_FILE_LOCATION);
-  );
+  a_parent->updateProcessingTimeStatisticConcept(timeToAnswerMs, cid);
+  //LOGDEBUG
+  //(
+  //  std::string msg = "This diameter request context lasted ";
+  //  msg += anna::functions::asString(timeToAnswerMs);
+  //  msg += " milliseconds at diameter client (included network time)";
+  //  anna::Logger::debug(msg, ANNA_FILE_LOCATION);
+  //);
   // Progress origin for tracking purposes on asyncronous boxes with both diameter interfaces (entities and clients)
   Message * requestMessage = const_cast<Message*>(response->getRequest());
   requestMessage->setRequestClientSessionKey(response->getRequest()->getRequestClientSessionKey()); // "" means unkown/unset
index 358c87c..c3e3b2c 100644 (file)
@@ -32,15 +32,6 @@ using namespace anna::statistics;
 using namespace anna::time;
 
 
-//******************************************************************************
-//------------------------------------------------------------------------------
-//-------------------------------------------------- Accumulator::~Accumulator()
-//------------------------------------------------------------------------------
-Accumulator::~Accumulator() {
-// LOGMETHOD (TraceMethod tttm ("anna::statistics::Accumulator", "Destructor", ANNA_FILE_LOCATION));
-  // TODO: anna::statistics::Engine::instantiate().releaseAccumulator(a_name);
-}
-
 // Private functions:
 
 
@@ -57,10 +48,8 @@ void Accumulator::initialize(const int & conceptId) throw() {
 //------------------------------------------------------------------------------
 //---------------------------------------------------- Accumulator::addConcept()
 //------------------------------------------------------------------------------
-int Accumulator::addConcept(const std::string & description, const std::string & unit, const bool & integerNatureSample) throw() {
-  std::string conceptName = description;
-  conceptName += ": ";
-  conceptName += a_name;
+int Accumulator::addConcept(const std::string & description, const std::string & unit, const bool & integerNatureSample, const char *conceptNameFormat) throw() {
+  std::string conceptName = anna::functions::asString(conceptNameFormat, description.c_str(), a_name.c_str());
   return anna::statistics::Engine::instantiate().addConcept(conceptName, unit, integerNatureSample);
 }
 
@@ -68,7 +57,7 @@ int Accumulator::addConcept(const std::string & description, const std::string &
 //------------------------------------------------------------------------------
 //---------------------------------------------------- Accumulator::getConcept()
 //------------------------------------------------------------------------------
-_concept_data_t * Accumulator::getConcept(const int & conceptId) const throw(anna::RuntimeException) {
+_concept_data_t *Accumulator::getConcept(const int & conceptId) const throw(anna::RuntimeException) {
   _concept_data_map_iter it = a_concept_data_map.find(conceptId);
 
   if(it == a_concept_data_map.end()) {  // not found
@@ -85,7 +74,6 @@ _concept_data_t * Accumulator::getConcept(const int & conceptId) const throw(ann
 
     Accumulator * nc_this = const_cast<Accumulator *>(this);
     nc_this->initialize(conceptId);
-    // (la otra posibilidad era hacer mutable el mapa e inicializar poniendo el contenido de 'initialize()')
     it = a_concept_data_map.find(conceptId);
   }
 
@@ -104,9 +92,6 @@ std::string Accumulator::floatFormat(const int & numberOfDecimals) const throw()
 }
 
 
-
-
-
 //------------------------------------------------------------------------------
 //------------------------------------------ Accumulator::getStandardDeviation()
 //------------------------------------------------------------------------------
@@ -229,8 +214,10 @@ void Accumulator::reset(void) throw() {
 //------------------------------------------------------------------------------
 void Accumulator::reset(const int & conceptId) throw(anna::RuntimeException) {
 // LOGMETHOD (TraceMethod tttm ("anna::statistics::Accumulator", "reset", ANNA_FILE_LOCATION));
-  _concept_data_t *ptr_auxConceptData = getConcept(conceptId);
-  //if (ptr_auxConceptData == NULL) return; // Not possible: getConcept initializes it if not found.
+  _concept_data_t *ptr_auxConceptData = getConcept(conceptId); // will initialize if didn't associated to this accumulator,
+                                                               // exception if engine knows nothing about such concept id.
+  //if (ptr_auxConceptData == NULL) return; // Not possible: getConcept initializes it if not found or exception was launched
+                                            //               previously if the engine don't know the concept id.
   ptr_auxConceptData->reset();
 }
 
index ebde06c..e804599 100644 (file)
@@ -39,8 +39,8 @@ Engine::Engine() {
 //------------------------------------------------------------ Engine::~Engine()
 //------------------------------------------------------------------------------
 Engine::~Engine() {
-  for (_accumulator_vector_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
-    delete (*it);
+  for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
+    delete (it->second);
 }
 
 
@@ -156,13 +156,26 @@ bool Engine::logSample(const int & conceptId, const anna::Millisecond & unixTime
 
 
 //------------------------------------------------------------------------------
-//----------------------------------------------------------- Engine::asString()
+//-------------------------------------------------- Engine::createAccumulator()
 //------------------------------------------------------------------------------
-Accumulator *Engine::createAccumulator(const std::string &name) throw() {
-  Accumulator *result;
+Accumulator *Engine::createAccumulator(const std::string &name) throw(anna::RuntimeException) {
+  Accumulator *result = getAccumulator(name);
+
+  if (result)
+    throw anna::RuntimeException(anna::functions::asString("Cannot register another accumulator with the same name: %s", name.c_str()), ANNA_FILE_LOCATION);
 
   result = new Accumulator(name);
-  a_accumulators.push_back(result);
+  a_accumulators[name] = result;
+  return result;
+}
+
+Accumulator* Engine::getAccumulator(const std::string &name) throw() {
+  Accumulator *result = NULL;
+
+  _accumulator_map_nc_it it = a_accumulators.find(name);
+  if (it != a_accumulators.end())
+    result = it->second;
+
   return result;
 }
 
@@ -204,9 +217,9 @@ std::string Engine::asString(void) const throw() {
 
   // Accumulators:
   trace += "\nNumber of accumulators= "; trace += anna::functions::asString(a_accumulators.size());
-  for (_accumulator_vector_it it = a_accumulators.begin(); it != a_accumulators.end(); it++) {
+  for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++) {
     trace += "\n";
-    trace += (*it)->asString();
+    trace += it->second->asString();
   }
 
   return (trace);
@@ -240,8 +253,8 @@ anna::xml::Node* Engine::asXML(anna::xml::Node* parent, const int & numberOfDeci
   // Accumulators:
   anna::xml::Node* accumulators = result->createChild("anna.statistics.Accumulators");
   accumulators->createAttribute("RegisteredAccumulators", a_accumulators.size());
-  for (_accumulator_vector_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
-    (*it)->asXML(accumulators);
+  for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
+    it->second->asXML(accumulators);
 
   return result;
 }
index 9c9de5f..bf4c3f8 100644 (file)
@@ -26,9 +26,9 @@ using namespace anna::statistics;
 //------------------------------------------------------------------------------
 
 // Default Constructor
-Meter::Meter(const std::string & description) : a_accumulator(description) {
+Meter::Meter(const std::string & name) : a_accumulator(name) {
   Engine& statsEngine = Engine::instantiate();
-  a_single_accumulator_concept_id = statsEngine.addConcept(description, "ms", true);
+  a_single_accumulator_concept_id = statsEngine.addConcept(name, "ms", true);
 }