blob: be9ea36ec9c9932a2c6f0c68e198411a9fdef0c6 [file] [log] [blame]
Austin Schuhe309d2a2019-11-29 13:25:21 -08001#ifndef AOS_EVENTS_LOGGER_H_
2#define AOS_EVENTS_LOGGER_H_
3
4#include <deque>
5#include <vector>
Austin Schuh05b70472020-01-01 17:11:17 -08006#include <string_view>
Austin Schuhe309d2a2019-11-29 13:25:21 -08007
Austin Schuhe309d2a2019-11-29 13:25:21 -08008#include "absl/types/span.h"
9#include "aos/events/event_loop.h"
Austin Schuha36c8902019-12-30 18:07:15 -080010#include "aos/events/logging/logfile_utils.h"
James Kuszmaul38735e82019-12-07 16:42:06 -080011#include "aos/events/logging/logger_generated.h"
Austin Schuh92547522019-12-28 14:33:43 -080012#include "aos/events/simulated_event_loop.h"
Austin Schuhe309d2a2019-11-29 13:25:21 -080013#include "aos/time/time.h"
14#include "flatbuffers/flatbuffers.h"
15
16namespace aos {
17namespace logger {
18
Austin Schuhe309d2a2019-11-29 13:25:21 -080019// Logs all channels available in the event loop to disk every 100 ms.
20// Start by logging one message per channel to capture any state and
21// configuration that is sent rately on a channel and would affect execution.
22class Logger {
23 public:
24 Logger(DetachedBufferWriter *writer, EventLoop *event_loop,
25 std::chrono::milliseconds polling_period =
26 std::chrono::milliseconds(100));
27
28 private:
29 void DoLogData();
30
31 EventLoop *event_loop_;
32 DetachedBufferWriter *writer_;
33
34 // Structure to track both a fetcher, and if the data fetched has been
35 // written. We may want to delay writing data to disk so that we don't let
36 // data get too far out of order when written to disk so we can avoid making
37 // it too hard to sort when reading.
38 struct FetcherStruct {
39 std::unique_ptr<RawFetcher> fetcher;
40 bool written = false;
Austin Schuh15649d62019-12-28 16:36:38 -080041
42 LogType log_type;
Austin Schuhe309d2a2019-11-29 13:25:21 -080043 };
44
45 std::vector<FetcherStruct> fetchers_;
46 TimerHandler *timer_handler_;
47
48 // Period to poll the channels.
49 const std::chrono::milliseconds polling_period_;
50
51 // Last time that data was written for all channels to disk.
52 monotonic_clock::time_point last_synchronized_time_;
53
54 // Max size that the header has consumed. This much extra data will be
55 // reserved in the builder to avoid reallocating.
56 size_t max_header_size_ = 0;
57};
58
59// Replays all the channels in the logfile to the event loop.
60class LogReader {
61 public:
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080062 // If you want to supply a new configuration that will be used for replay
63 // (e.g., to change message rates, or to populate an updated schema), then
64 // pass it in here. It must provide all the channels that the original logged
65 // config did.
66 LogReader(std::string_view filename,
67 const Configuration *replay_configuration = nullptr);
James Kuszmaul7daef362019-12-31 18:28:17 -080068 ~LogReader();
Austin Schuhe309d2a2019-11-29 13:25:21 -080069
Austin Schuh6331ef92020-01-07 18:28:09 -080070 // Registers all the callbacks to send the log file data out on an event loop
71 // created in event_loop_factory. This also updates time to be at the start
72 // of the log file by running until the log file starts.
73 // Note: the configuration used in the factory should be configuration()
74 // below, but can be anything as long as the locations needed to send
75 // everything are available.
James Kuszmaul84ff3e52020-01-03 19:48:53 -080076 void Register(SimulatedEventLoopFactory *event_loop_factory);
Austin Schuh6331ef92020-01-07 18:28:09 -080077 // Creates an SimulatedEventLoopFactory accessible via event_loop_factory(),
78 // and then calls Register.
79 void Register();
80 // Registers callbacks for all the events after the log file starts. This is
81 // only useful when replaying live.
Austin Schuhe309d2a2019-11-29 13:25:21 -080082 void Register(EventLoop *event_loop);
Austin Schuh6331ef92020-01-07 18:28:09 -080083
James Kuszmaul84ff3e52020-01-03 19:48:53 -080084 // Unregisters the senders. You only need to call this if you separately
85 // supplied an event loop or event loop factory and the lifetimes are such
86 // that they need to be explicitly destroyed before the LogReader destructor
87 // gets called.
Austin Schuhe309d2a2019-11-29 13:25:21 -080088 void Deregister();
89
Austin Schuhe309d2a2019-11-29 13:25:21 -080090 // Returns the configuration from the log file.
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -080091 const Configuration *logged_configuration() const;
92 // Returns the configuration being used for replay.
Austin Schuh15649d62019-12-28 16:36:38 -080093 const Configuration *configuration() const;
94
Austin Schuh6331ef92020-01-07 18:28:09 -080095 const LogFileHeader *log_file_header() const {
96 return sorted_message_reader_.log_file_header();
97 }
98
99 // Returns the node that this log file was created on. This is a pointer to a
100 // node in the nodes() list inside configuration().
Austin Schuh15649d62019-12-28 16:36:38 -0800101 const Node *node() const;
Austin Schuhe309d2a2019-11-29 13:25:21 -0800102
103 // Returns the starting timestamp for the log file.
104 monotonic_clock::time_point monotonic_start_time();
105 realtime_clock::time_point realtime_start_time();
106
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -0800107 // Causes the logger to publish the provided channel on a different name so
108 // that replayed applications can publish on the proper channel name without
109 // interference. This operates on raw channel names, without any node or
110 // application specific mappings.
111 void RemapLoggedChannel(std::string_view name, std::string_view type,
112 std::string_view add_prefix = "/original");
113 template <typename T>
114 void RemapLoggedChannel(std::string_view name,
115 std::string_view add_prefix = "/original") {
116 RemapLoggedChannel(name, T::GetFullyQualifiedName(), add_prefix);
117 }
118
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800119 SimulatedEventLoopFactory *event_loop_factory() {
120 return event_loop_factory_;
121 }
122
Austin Schuhe309d2a2019-11-29 13:25:21 -0800123 // TODO(austin): Add the ability to re-publish the fetched messages. Add 2
124 // options, one which publishes them *now*, and another which publishes them
125 // to the simulated event loop factory back in time where they actually
126 // happened.
127
128 private:
Austin Schuhe309d2a2019-11-29 13:25:21 -0800129 // Queues at least max_out_of_order_duration_ messages into channels_.
130 void QueueMessages();
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -0800131 // Handle constructing a configuration with all the additional remapped
132 // channels from calls to RemapLoggedChannel.
133 void MakeRemappedConfig();
Austin Schuhe309d2a2019-11-29 13:25:21 -0800134
Austin Schuh05b70472020-01-01 17:11:17 -0800135 // Log chunk reader.
136 SortedMessageReader sorted_message_reader_;
Austin Schuhe309d2a2019-11-29 13:25:21 -0800137
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800138 std::unique_ptr<FlatbufferDetachedBuffer<Configuration>>
139 remapped_configuration_buffer_;
140
Austin Schuh05b70472020-01-01 17:11:17 -0800141 std::vector<std::unique_ptr<RawSender>> channels_;
Austin Schuhe309d2a2019-11-29 13:25:21 -0800142
Austin Schuh92547522019-12-28 14:33:43 -0800143 std::unique_ptr<EventLoop> event_loop_unique_ptr_;
144 EventLoop *event_loop_ = nullptr;
Austin Schuhe309d2a2019-11-29 13:25:21 -0800145 TimerHandler *timer_handler_;
James Kuszmaul84ff3e52020-01-03 19:48:53 -0800146
147 std::unique_ptr<SimulatedEventLoopFactory> event_loop_factory_unique_ptr_;
148 SimulatedEventLoopFactory *event_loop_factory_ = nullptr;
James Kuszmaulc7bbb3e2020-01-03 20:01:00 -0800149
150 // Map of channel indices to new name. The channel index will be an index into
151 // logged_configuration(), and the string key will be the name of the channel
152 // to send on instead of the logged channel name.
153 std::map<size_t, std::string> remapped_channels_;
154
155 const Configuration *remapped_configuration_ = nullptr;
156 const Configuration *replay_configuration_ = nullptr;
Austin Schuhe309d2a2019-11-29 13:25:21 -0800157};
158
159} // namespace logger
160} // namespace aos
161
162#endif // AOS_EVENTS_LOGGER_H_