PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/source/ArmarXCore/observers/ProfilerObserver.cpp

https://gitlab.com/mkroehnert/ArmarXCore
C++ | 378 lines | 282 code | 67 blank | 29 comment | 17 complexity | 327e68051b16523bacfe5a764c1469f6 MD5 | raw file
  1. /*
  2. * This file is part of ArmarX.
  3. *
  4. * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
  5. *
  6. * ArmarX is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * ArmarX is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * @package Core::observers::ProfilerObserver
  19. * @author Manfred Kroehnert (manfred dot kroehnert at kit dot edu)
  20. * @date 2015
  21. * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
  22. * GNU General Public License
  23. */
  24. #include "ProfilerObserver.h"
  25. #include "checks/ConditionCheckEquals.h"
  26. #include "checks/ConditionCheckUpdated.h"
  27. #include "checks/ConditionCheckChanged.h"
  28. #include "checks/ConditionCheckValid.h"
  29. #include "../observers/variant/TimestampVariant.h"
  30. #include <set>
  31. #include <algorithm>
  32. #include <ArmarXCore/core/services/profiler/Profiler.h> // for ProfilerPtr
  33. armarx::ProfilerObserver::~ProfilerObserver()
  34. {
  35. }
  36. std::string armarx::ProfilerObserver::getDefaultName() const
  37. {
  38. return "ProfilerObserver";
  39. }
  40. void armarx::ProfilerObserver::onInitObserver()
  41. {
  42. usingTopic(armarx::Profiler::PROFILER_TOPIC_NAME);
  43. }
  44. void armarx::ProfilerObserver::onConnectObserver()
  45. {
  46. offerChannel("activeStateChanged", "Channel reporting the currently active state of statecharts with EnableProfiling property set");
  47. offerDataField("activeStateChanged", "activeState", VariantType::String, "Name of the currently active state");
  48. offerConditionCheck(checks::equals, new ConditionCheckEquals());
  49. offerConditionCheck(checks::updated, new ConditionCheckUpdated());
  50. offerConditionCheck(checks::changed, new ConditionCheckChanged());
  51. offerConditionCheck(checks::valid, new ConditionCheckValid());
  52. setDataField("activeStateChanged", "activeState", "");
  53. }
  54. void armarx::ProfilerObserver::reportNetworkTraffic(const std::string& id, const std::string& protocol, Ice::Int inBytes, Ice::Int outBytes, const Ice::Current&)
  55. {
  56. try
  57. {
  58. if (!existsChannel(id))
  59. {
  60. offerChannel(id, "Network traffic");
  61. }
  62. offerOrUpdateDataField(id, protocol + "_inBytes", Variant(inBytes), "Incoming network traffic");
  63. offerOrUpdateDataField(id, protocol + "_outBytes", Variant(outBytes), "Outgoing network traffic");
  64. updateChannel(id);
  65. }
  66. catch (...)
  67. {
  68. handleExceptions();
  69. }
  70. }
  71. void armarx::ProfilerObserver::reportEvent(const armarx::ProfilerEvent& event, const Ice::Current&)
  72. {
  73. std::string stateIdentifier = event.parentName;
  74. try
  75. {
  76. createStateChannelIfRequired(stateIdentifier);
  77. int microsecondsModifier = 0;
  78. if (event.timestampUnit == "ms")
  79. {
  80. microsecondsModifier = 1000;
  81. }
  82. else if (event.timestampUnit == "us")
  83. {
  84. microsecondsModifier = 1;
  85. }
  86. TimestampVariant timestamp(event.timestamp * microsecondsModifier);
  87. if (event.functionName == Profiler::Profiler::GetEventName(Profiler::Profiler::eFunctionStart))
  88. {
  89. setDataField(stateIdentifier, "lastEnterTimestamp", timestamp);
  90. }
  91. else
  92. {
  93. VariantPtr lastActiveState = VariantPtr::dynamicCast(getDataField(new DataFieldIdentifier(getName(), stateIdentifier, "activeSubstate")));
  94. setDataField(stateIdentifier, "lastExitTimestamp", timestamp);
  95. setDataField(stateIdentifier, "activeSubstate", Variant(""));
  96. if (lastActiveState)
  97. {
  98. setDataFieldFlatCopy(stateIdentifier, "previousSubstate", lastActiveState);
  99. }
  100. }
  101. updateChannel(stateIdentifier);
  102. ARMARX_INFO << "Updating function info channel " << stateIdentifier;
  103. }
  104. catch (...)
  105. {
  106. handleExceptions();
  107. }
  108. }
  109. void armarx::ProfilerObserver::reportProcessCpuUsage(const ProfilerProcessCpuUsage& process, const Ice::Current&)
  110. {
  111. std::string id = process.processName + boost::lexical_cast<std::string>(process.processId);
  112. try
  113. {
  114. createResourceChannelIfRequired(id);
  115. setDataField(id, "cpuUsage", Variant(process.cpuUsage));
  116. updateChannel(id);
  117. }
  118. catch (...)
  119. {
  120. handleExceptions();
  121. }
  122. }
  123. void armarx::ProfilerObserver::reportProcessMemoryUsage(const ProfilerProcessMemoryUsage& memoryUsage, const Ice::Current&)
  124. {
  125. std::string id = memoryUsage.processName + boost::lexical_cast<std::string>(memoryUsage.processId);
  126. try
  127. {
  128. createResourceChannelIfRequired(id);
  129. setDataField(id, "memoryUsage", Variant(memoryUsage.memoryUsage));
  130. updateChannel(id);
  131. }
  132. catch (...)
  133. {
  134. handleExceptions();
  135. }
  136. }
  137. void armarx::ProfilerObserver::reportStatechartTransition(const ProfilerStatechartTransition& transition, const Ice::Current&)
  138. {
  139. try
  140. {
  141. Variant activeSubstate(transition.targetStateIdentifier);
  142. setDataField("activeStateChanged", "activeState", activeSubstate);
  143. updateChannel("activeStateChanged");
  144. std::string stateIdentifier = transition.parentStateIdentifier;
  145. createStateChannelIfRequired(stateIdentifier);
  146. setDataField(stateIdentifier, "activeSubstate", activeSubstate);
  147. setDataField(stateIdentifier, "previousSubstate", Variant(transition.sourceStateIdentifier));
  148. setDataField(stateIdentifier, "lastEventName", Variant(transition.eventName));
  149. updateChannel(stateIdentifier);
  150. ARMARX_INFO << "Updating Transition info channel " << stateIdentifier;
  151. }
  152. catch (...)
  153. {
  154. handleExceptions();
  155. }
  156. }
  157. void armarx::ProfilerObserver::StateParameterToVariantMap(const armarx::StateParameterMap& parameterMap, armarx::StringValueMap& variantMap)
  158. {
  159. for (auto& entry : parameterMap)
  160. {
  161. variantMap.addElement(entry.first, entry.second->value);
  162. }
  163. }
  164. void armarx::ProfilerObserver::reportStatechartInputParameters(const ProfilerStatechartParameters& inputParameters, const Ice::Current&)
  165. {
  166. try
  167. {
  168. createStateChannelIfRequired(inputParameters.stateIdentifier);
  169. StringValueMap parameters(false);
  170. StateParameterToVariantMap(inputParameters.parameterMap, parameters);
  171. setDataField(inputParameters.stateIdentifier, "inputParameters", parameters);
  172. updateChannel(inputParameters.stateIdentifier);
  173. }
  174. catch (...)
  175. {
  176. handleExceptions();
  177. }
  178. }
  179. void armarx::ProfilerObserver::reportStatechartLocalParameters(const ProfilerStatechartParameters& localParameters, const Ice::Current&)
  180. {
  181. try
  182. {
  183. createStateChannelIfRequired(localParameters.stateIdentifier);
  184. StringValueMap parameters(false);
  185. StateParameterToVariantMap(localParameters.parameterMap, parameters);
  186. setDataField(localParameters.stateIdentifier, "localParameters", parameters);
  187. updateChannel(localParameters.stateIdentifier);
  188. }
  189. catch (...)
  190. {
  191. handleExceptions();
  192. }
  193. }
  194. void armarx::ProfilerObserver::reportStatechartOutputParameters(const ProfilerStatechartParameters& outputParameters, const Ice::Current&)
  195. {
  196. try
  197. {
  198. createStateChannelIfRequired(outputParameters.stateIdentifier);
  199. StringValueMap parameters(false);
  200. StateParameterToVariantMap(outputParameters.parameterMap, parameters);
  201. setDataField(outputParameters.stateIdentifier, "outputParameters", parameters);
  202. updateChannel(outputParameters.stateIdentifier);
  203. }
  204. catch (...)
  205. {
  206. handleExceptions();
  207. }
  208. }
  209. void armarx::ProfilerObserver::createStateChannelIfRequired(const std::string& channelName)
  210. {
  211. ScopedLock lock(channelCheckMutex);
  212. if (existsChannel(channelName))
  213. {
  214. return;
  215. }
  216. offerChannel(channelName, "Statechart State Channel");
  217. offerDataField(channelName, "activeSubstate", VariantType::String, "Currently Active Substate");
  218. offerDataField(channelName, "previousSubstate", VariantType::String, "Last Active Substate");
  219. offerDataField(channelName, "lastEventName", VariantType::String, "Last Event/Transition Name");
  220. offerDataField(channelName, "inputParameters", VariantType::VariantContainer, "State Input Parameters");
  221. offerDataField(channelName, "localParameters", VariantType::VariantContainer, "State Local Parameters");
  222. offerDataField(channelName, "outputParameters", VariantType::VariantContainer, "State Output Parameters");
  223. offerDataField(channelName, "lastEnterTimestamp", VariantType::Timestamp, "Timestamp of when onEnter() of the state was last called");
  224. offerDataField(channelName, "lastExitTimestamp", VariantType::Timestamp, "Timestamp of when onExit() or onBreak() of the state was last called");
  225. }
  226. void armarx::ProfilerObserver::createResourceChannelIfRequired(const std::string& channelName)
  227. {
  228. ScopedLock lock(channelCheckMutex);
  229. if (existsChannel(channelName))
  230. {
  231. return;
  232. }
  233. offerChannel(channelName, "Resource Information");
  234. offerDataField(channelName, "cpuUsage", VariantType::Float, "Cpu Usage of process specified by the channelname");
  235. offerDataField(channelName, "memoryUsage", VariantType::Int, "Memory Usage of process specified by the channelname");
  236. }
  237. void armarx::ProfilerObserver::reportEventList(const armarx::ProfilerEventList& events, const Ice::Current&)
  238. {
  239. // ignore these events in the observer
  240. }
  241. void armarx::ProfilerObserver::reportStatechartTransitionList(const armarx::ProfilerStatechartTransitionList& transitions, const Ice::Current&)
  242. {
  243. armarx::ProfilerStatechartTransition lastTransition = transitions.back();
  244. setDataField("activeStateChanged", "activeState", Variant(lastTransition.targetStateIdentifier));
  245. updateChannel("activeStateChanged");
  246. }
  247. void armarx::ProfilerObserver::reportStatechartInputParametersList(const ProfilerStatechartParametersList& inputParametersList, const Ice::Current&)
  248. {
  249. // remove all but the latest occurence of an entry in the list of profiler entries
  250. auto compareFunction = [](const ProfilerStatechartParameters & lhs, const ProfilerStatechartParameters & rhs)
  251. {
  252. return lhs.stateIdentifier < rhs.stateIdentifier;
  253. };
  254. std::set<ProfilerStatechartParameters, decltype(compareFunction)> latestElements(inputParametersList.rbegin(), inputParametersList.rend(), compareFunction);
  255. for (const auto& element : latestElements)
  256. {
  257. reportStatechartInputParameters(element);
  258. }
  259. }
  260. void armarx::ProfilerObserver::reportStatechartLocalParametersList(const ProfilerStatechartParametersList& localParametersList, const Ice::Current&)
  261. {
  262. // remove all but the latest occurence of an entry in the list of profiler entries
  263. auto compareFunction = [](const ProfilerStatechartParameters & lhs, const ProfilerStatechartParameters & rhs)
  264. {
  265. return lhs.stateIdentifier < rhs.stateIdentifier;
  266. };
  267. std::set<ProfilerStatechartParameters, decltype(compareFunction)> latestElements(localParametersList.rbegin(), localParametersList.rend(), compareFunction);
  268. for (const auto& element : latestElements)
  269. {
  270. reportStatechartLocalParameters(element);
  271. }
  272. }
  273. void armarx::ProfilerObserver::reportStatechartOutputParametersList(const ProfilerStatechartParametersList& outputParametersList, const Ice::Current&)
  274. {
  275. // remove all but the latest occurence of an entry in the list of profiler entries
  276. auto compareFunction = [](const ProfilerStatechartParameters & lhs, const ProfilerStatechartParameters & rhs)
  277. {
  278. return lhs.stateIdentifier < rhs.stateIdentifier;
  279. };
  280. std::set<ProfilerStatechartParameters, decltype(compareFunction)> latestElements(outputParametersList.rbegin(), outputParametersList.rend(), compareFunction);
  281. for (const auto& element : latestElements)
  282. {
  283. reportStatechartOutputParameters(element);
  284. }
  285. }
  286. void armarx::ProfilerObserver::reportProcessCpuUsageList(const ProfilerProcessCpuUsageList& processes, const Ice::Current&)
  287. {
  288. // remove all but the latest occurence of an entry in the list of profiler entries
  289. auto compareFunction = [](const ProfilerProcessCpuUsage & lhs, const ProfilerProcessCpuUsage & rhs)
  290. {
  291. return lhs.processId < rhs.processId;
  292. };
  293. std::set<ProfilerProcessCpuUsage, decltype(compareFunction)> latestElements(processes.rbegin(), processes.rend(), compareFunction);
  294. for (const auto& element : latestElements)
  295. {
  296. reportProcessCpuUsage(element);
  297. }
  298. }
  299. void armarx::ProfilerObserver::reportProcessMemoryUsageList(const ProfilerProcessMemoryUsageList& memoryUsages, const Ice::Current&)
  300. {
  301. // remove all but the latest occurence of an entry in the list of profiler entries
  302. auto compareFunction = [](const ProfilerProcessMemoryUsage & lhs, const ProfilerProcessMemoryUsage & rhs)
  303. {
  304. return lhs.processId < rhs.processId;
  305. };
  306. std::set<ProfilerProcessMemoryUsage, decltype(compareFunction)> latestElements(memoryUsages.rbegin(), memoryUsages.rend(), compareFunction);
  307. for (const auto& element : latestElements)
  308. {
  309. reportProcessMemoryUsage(element);
  310. }
  311. }