iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EventLog.H
Go to the documentation of this file.
1 /*! @file
2  @author Laurent Itti
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
36 #ifndef INCLUDE_NRT_CORE_DEBUGGING_EVENTLOG_H
37 #define INCLUDE_NRT_CORE_DEBUGGING_EVENTLOG_H
38 
39 #include <mutex>
40 #include <chrono>
41 #include <thread>
42 #include <list>
43 #include <iosfwd>
44 #include <map>
45 #include <vector>
46 #include <mutex>
47 #include <nrt/Core/Typing/Time.H>
48 #include <nrt/External/cereal/types/chrono.hpp>
49 #include <nrt/External/cereal/types/map.hpp>
50 #include <nrt/External/cereal/types/vector.hpp>
51 #include <nrt/External/cereal/types/string.hpp>
52 #include <nrt/External/cereal/types/utility.hpp>
53 
54 namespace nrt
55 {
56  class EventLog;
57 
58  /*! \defgroup eventlog Event logging classes and functions
59 
60  The NRT event loging facility allows one to easily log both point and extended events, either in real-time to a
61  console or to a file that can be later analyzed for profiling purposes.
62 
63  \ingroup debugging */
64 
65  /*! @{ */ // **********************************************************************
66 
67  //! An entry in an nrt::EventLog
68  /*! EventLog entries are very simple, consisting of just start and end time, and a string message. */
70  {
71  std::chrono::time_point<std::chrono::high_resolution_clock> start; //!< Event start time
72  std::chrono::time_point<std::chrono::high_resolution_clock> stop; //!< Event stop time
73  std::string msg; //!< Text message describing the event
74  };
75 
76  //! Event is a simple proxy class for an event, similar to lock classes for mutex
77  /*! Just like providing lock() and unlock() functions for mutex objects poses problems, for example with exceptions
78  which may leave a mutex locked, providing event start and stop functions poses similar problems. Hence, similar to
79  the concept of lock objects, the nrt::EventLog facility uses Event objects.
80 
81  Basically, an Event starts when it is constructed and ends when it is destructed. Event is intended to be used
82  with nrt::EventLog. Indeed, only nrt::EventLog can construct new events. This is because an Event must be attached
83  to ean EventLog so that the Event can report to the EventLog upon destruction. Thus, EventLog can create Event
84  objects, these can then be kept alive or passed along (using move semantics), and when Event objects get
85  destructed they update their end time in the EventLog.
86 
87  \see nrt::EventLog::event(), nrt::EventLog, nrt::EventLogEntry */
88  class Event
89  {
90  public:
91  //! Move constructor
92  Event(Event && e);
93 
94  //! Forbid default construction
95  Event() = delete;
96 
97  //! Forbid copy-construction
98  Event(Event const & e) = delete;
99 
100  //! Move assignment
101  Event & operator=(Event && e);
102 
103  //! Forbid copy
104  Event & operator=(Event const & e) = delete;
105 
106  //! The event will be marked as finished in the EventLog when the Event destructor is called
107  ~Event();
108 
109  private:
110  friend class EventLog;
111 
112  //! Create a new event
113  /*! If os and mtx are not null, then the event will be immediately output to os upon completion (destruction), in
114  addition to being stored in the event log, locking mtx while the ostream is being written to (to avoid
115  conflicts between different threads). */
116  Event(EventLogEntry * e, std::ostream * os = nullptr, std::mutex * mtx = nullptr);
117 
118  EventLogEntry * itsLogEntry;
119  std::ostream * itsOstream;
120  std::mutex * itsOstreamMtx;
121  };
122 
123  //! Parsed summary from an EventLog
124  /*! nrt::EventLogSummary transforms the unsorted list of mixed point and extended events of an nrt::EventLog into two
125  maps, under the assumption that the events will periodically repeat. For instance, one may issue several events
126  from several parallel threads for each video frame in a complex video processing system. Assuming that the
127  messages of the events are the same for every frame, an nrt::EventLogSummary will concatenate all the event times
128  that have the same message, thus allowing one to plot all the occurrences of that event together over the video
129  frames.
130 
131  Several nrt::EventLogSummary can be merged which is useful to merge summaries that have been recorded by different
132  Blackboards in a distributed Blackboard federation. */
134  {
135  std::map<std::chrono::time_point<std::chrono::high_resolution_clock>,
136  std::vector<std::string> > checkpoints;
137 
138  std::map<std::string,
139  std::vector<std::pair<std::chrono::time_point<std::chrono::high_resolution_clock>,
140  std::chrono::time_point<std::chrono::high_resolution_clock> > > > events;
141 
142  //! Merge another summary into us
143  void mergeWith(EventLogSummary const & other);
144 
145  //! Serialize the summary
146  template <class Archive> void serialize(Archive & ar)
147  { ar( checkpoints, events ); }
148  };
149 
150  //! A simple event logger
151  /*! Use to log point as well as extended events, recording event times and also a simple string message for each
152  event. The log of events can be either streamed online to an std::ostream or saved to a text file for later ofline
153  analysis.
154 
155  Point events (which have no duration) are logged by calling nrt::EventLog::checkpoint(). These are typically used
156  to log the time at which critical steps, branching points, decision points, or checkpoints in a program are
157  reached.
158 
159  Extended events (which have a duration) are logged by creating an nrt::Event object by calling
160  nrt::EventLog::event(); the time at which the Event object is constructed represents the start time of the
161  extended event, while the destruction time of the Event object will mark the end time of the extended event.
162 
163  EventLog can always operate in offline mode, in which case a call to nrt::EventLog::save() is necessary to save
164  the log to an std::ostream for later offline analysis. Or it can additionally operate in online mode if
165  nrt::EventLog::setOnlineStream() is called with a valid std::ostream. \see nrt::Event */
166  class EventLog
167  {
168  public:
169  //! Log a point event (no duration)
170  void checkpoint(std::string const & msg);
171 
172  //! Log a point event (no duration), faster version for literal strings
173  void checkpoint(char const * msg);
174 
175  //! Start logging an extended event
176  /*! The start time point is now(), and the end time point will be filled when the Event object is
177  destroyed. Example usage is as follows:
178 
179  @code
180  EventLog evl;
181 
182  while(true) {
183  Event e = evl.event("Body of while loop"); // start time is now
184 
185  // ... do things during the event. If we throw here, e will be destroyed and the event properly stopped
186 
187  } // event destroyed, stop time is set now
188  @endcode */
189  Event event(std::string const & msg);
190 
191  //! Start logging an extended event, faster version for literal strings
192  Event event(char const * msg);
193 
194  //! Save entire log to a stream
195  void save(std::ostream & os) const;
196 
197  //! Save a summary of the entire log
198  void summary(EventLogSummary & s) const;
199 
200  //! Set the ostream to use when logging online (i.e. writing each log entry as it is created)
201  /*! Setting to nullptr will disable online logging, requiring you to explicitly call save() to write out logs. */
202  void setOnlineOstream(std::ostream * os = nullptr);
203 
204  private:
205  mutable std::mutex itsMtx;
206  std::list<EventLogEntry> itsEntries;
207  std::ostream * itsOnlineOstream;
208  };
209 
210  /*! @} */ // **********************************************************************
211 }
212 
213 
214 #endif // INCLUDE_NRT_CORE_DEBUGGING_EVENTLOG_H