blob: 84745b6ddca9941edb67e26b41c4882d2936b846 [file] [log] [blame]
Austin Schuhcb5601b2020-09-10 15:29:59 -07001#ifndef AOS_EVENTS_LOGGING_LOG_NAMER_H_
2#define AOS_EVENTS_LOGGING_LOG_NAMER_H_
3
4#include <functional>
5#include <map>
6#include <memory>
7#include <string_view>
8#include <vector>
9
Austin Schuh58646e22021-08-23 23:51:46 -070010#include "absl/container/btree_map.h"
Austin Schuhcb5601b2020-09-10 15:29:59 -070011#include "aos/events/logging/logfile_utils.h"
12#include "aos/events/logging/logger_generated.h"
Austin Schuh4385b142021-03-14 21:31:13 -070013#include "aos/uuid.h"
Austin Schuhcb5601b2020-09-10 15:29:59 -070014#include "flatbuffers/flatbuffers.h"
15
16namespace aos {
17namespace logger {
18
Austin Schuh572924a2021-07-30 22:32:12 -070019class LogNamer;
20
Austin Schuhb8bca732021-07-30 22:32:00 -070021// TODO(austin): Rename this back to DataWriter once all other callers are of
22// the old DataWriter.
Austin Schuh572924a2021-07-30 22:32:12 -070023//
24// Class to manage writing data to log files. This lets us track which boot the
25// written header has in it, and if the header has been written or not.
Austin Schuh58646e22021-08-23 23:51:46 -070026//
27// The design of this class is that instead of being notified when any of the
28// header data changes, it polls and owns that decision. This makes it much
29// harder to write corrupted data. If that becomes a performance problem, we
30// can DCHECK and take it out of production binaries.
Austin Schuhb8bca732021-07-30 22:32:00 -070031class NewDataWriter {
32 public:
33 // Constructs a NewDataWriter.
Austin Schuh572924a2021-07-30 22:32:12 -070034 // log_namer is the log namer which holds the config and any other data we
35 // need for our header.
36 // node is the node whom's prespective we are logging from.
Austin Schuhb8bca732021-07-30 22:32:00 -070037 // reopen is called whenever a file needs to be reopened.
38 // close is called to close that file and extract any statistics.
Austin Schuhf5f99f32022-02-07 20:05:37 -080039 NewDataWriter(LogNamer *log_namer, const Node *node, const Node *logger_node,
Austin Schuh572924a2021-07-30 22:32:12 -070040 std::function<void(NewDataWriter *)> reopen,
Austin Schuh48d10d62022-10-16 22:19:23 -070041 std::function<void(NewDataWriter *)> close,
42 size_t max_message_size);
43
44 void UpdateMaxMessageSize(size_t new_size) {
45 if (new_size > max_message_size_) {
46 CHECK(!header_written_);
47 max_message_size_ = new_size;
48 }
49 }
50 size_t max_message_size() const { return max_message_size_; }
Austin Schuhb8bca732021-07-30 22:32:00 -070051
52 NewDataWriter(NewDataWriter &&other) = default;
53 aos::logger::NewDataWriter &operator=(NewDataWriter &&other) = default;
54 NewDataWriter(const NewDataWriter &) = delete;
55 void operator=(const NewDataWriter &) = delete;
56
Austin Schuh572924a2021-07-30 22:32:12 -070057 ~NewDataWriter();
Austin Schuhb8bca732021-07-30 22:32:00 -070058
Austin Schuh572924a2021-07-30 22:32:12 -070059 // Rotates the log file, delaying writing the new header until data arrives.
60 void Rotate();
Austin Schuhb8bca732021-07-30 22:32:00 -070061
Austin Schuhf5f99f32022-02-07 20:05:37 -080062 // Updates all the metadata in the log file about the remote node which this
63 // message is from.
Austin Schuh72211ae2021-08-05 14:02:30 -070064 void UpdateRemote(size_t remote_node_index, const UUID &remote_node_boot_uuid,
65 monotonic_clock::time_point monotonic_remote_time,
66 monotonic_clock::time_point monotonic_event_time,
Austin Schuhf5f99f32022-02-07 20:05:37 -080067 bool reliable,
68 monotonic_clock::time_point monotonic_timestamp_time =
69 monotonic_clock::min_time);
Austin Schuh48d10d62022-10-16 22:19:23 -070070 // Coppies a message with the provided boot UUID.
71 void CopyMessage(DataEncoder::Copier *coppier,
72 const UUID &source_node_boot_uuid,
73 aos::monotonic_clock::time_point now);
Austin Schuhb8bca732021-07-30 22:32:00 -070074
Austin Schuh5e14d842022-01-21 12:02:15 -080075 // Updates the current boot for the source node. This is useful when you want
76 // to queue a message that may trigger a reboot rotation, but then need to
77 // update the remote timestamps.
78 void UpdateBoot(const UUID &source_node_boot_uuid);
79
Austin Schuh572924a2021-07-30 22:32:12 -070080 // Returns the filename of the writer.
Austin Schuh58646e22021-08-23 23:51:46 -070081 std::string_view filename() const {
82 return writer ? writer->filename() : "(closed)";
83 }
Austin Schuhb8bca732021-07-30 22:32:00 -070084
Austin Schuh572924a2021-07-30 22:32:12 -070085 void Close();
Austin Schuhb8bca732021-07-30 22:32:00 -070086
87 std::unique_ptr<DetachedBufferWriter> writer = nullptr;
Austin Schuh572924a2021-07-30 22:32:12 -070088
89 size_t node_index() const { return node_index_; }
90 const UUID &parts_uuid() const { return parts_uuid_; }
91 size_t parts_index() const { return parts_index_; }
92 const Node *node() const { return node_; }
Austin Schuhb8bca732021-07-30 22:32:00 -070093
Austin Schuh72211ae2021-08-05 14:02:30 -070094 // Datastructure used to capture all the information about a remote node.
95 struct State {
96 // Boot UUID of the node.
97 UUID boot_uuid = UUID::Zero();
98 // Timestamp on the remote monotonic clock of the oldest message sent to
99 // node_index_.
100 monotonic_clock::time_point oldest_remote_monotonic_timestamp =
101 monotonic_clock::max_time;
102 // Timestamp on the local monotonic clock of the message in
103 // oldest_remote_monotonic_timestamp.
104 monotonic_clock::time_point oldest_local_monotonic_timestamp =
105 monotonic_clock::max_time;
106 // Timestamp on the remote monotonic clock of the oldest message sent to
107 // node_index_, excluding messages forwarded with time_to_live() == 0.
108 monotonic_clock::time_point oldest_remote_unreliable_monotonic_timestamp =
109 monotonic_clock::max_time;
110 // Timestamp on the local monotonic clock of the message in
111 // oldest_local_unreliable_monotonic_timestamp.
112 monotonic_clock::time_point oldest_local_unreliable_monotonic_timestamp =
113 monotonic_clock::max_time;
Austin Schuhbfe6c572022-01-27 20:48:20 -0800114
115 // Timestamp on the remote monotonic clock of the oldest message sent to
116 // node_index_, only including messages forwarded with time_to_live() == 0.
117 monotonic_clock::time_point oldest_remote_reliable_monotonic_timestamp =
118 monotonic_clock::max_time;
119 // Timestamp on the local monotonic clock of the message in
120 // oldest_local_reliable_monotonic_timestamp.
121 monotonic_clock::time_point oldest_local_reliable_monotonic_timestamp =
122 monotonic_clock::max_time;
Austin Schuhf5f99f32022-02-07 20:05:37 -0800123
124 // Timestamp on the remote monotonic clock of the oldest message timestamp
125 // sent back to logger_node_index_. The remote here will be the node this
126 // part is from the perspective of, ie node_index_.
127 monotonic_clock::time_point
128 oldest_logger_remote_unreliable_monotonic_timestamp =
129 monotonic_clock::max_time;
130 // The time on the monotonic clock of the logger when this timestamp made it
131 // back to the logger (logger_node_index_).
132 monotonic_clock::time_point
133 oldest_logger_local_unreliable_monotonic_timestamp =
134 monotonic_clock::max_time;
Austin Schuh72211ae2021-08-05 14:02:30 -0700135 };
136
Austin Schuhb8bca732021-07-30 22:32:00 -0700137 private:
Austin Schuhe46492f2021-07-31 19:49:41 -0700138 // Signals that a node has rebooted.
Austin Schuh5e14d842022-01-21 12:02:15 -0800139 void Reboot(const UUID &source_node_boot_uuid);
Austin Schuhe46492f2021-07-31 19:49:41 -0700140
Austin Schuh572924a2021-07-30 22:32:12 -0700141 void QueueHeader(
142 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> &&header);
143
Austin Schuhe46492f2021-07-31 19:49:41 -0700144 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> MakeHeader();
145
Austin Schuh58646e22021-08-23 23:51:46 -0700146 monotonic_clock::time_point monotonic_start_time_ = monotonic_clock::min_time;
147
Austin Schuh577610e2021-12-08 12:07:19 -0800148 const Node *node_ = nullptr;
149 size_t node_index_ = 0;
Austin Schuhf5f99f32022-02-07 20:05:37 -0800150 size_t logger_node_index_ = 0;
Austin Schuh572924a2021-07-30 22:32:12 -0700151 LogNamer *log_namer_;
152 UUID parts_uuid_ = UUID::Random();
153 size_t parts_index_ = 0;
154
Austin Schuhb8bca732021-07-30 22:32:00 -0700155 std::function<void(NewDataWriter *)> reopen_;
156 std::function<void(NewDataWriter *)> close_;
Austin Schuh572924a2021-07-30 22:32:12 -0700157 bool header_written_ = false;
Austin Schuhe46492f2021-07-31 19:49:41 -0700158
Austin Schuh72211ae2021-08-05 14:02:30 -0700159 std::vector<State> state_;
Austin Schuh48d10d62022-10-16 22:19:23 -0700160
161 size_t max_message_size_;
Austin Schuhb8bca732021-07-30 22:32:00 -0700162};
163
Austin Schuhcb5601b2020-09-10 15:29:59 -0700164// Interface describing how to name, track, and add headers to log file parts.
165class LogNamer {
166 public:
167 // Constructs a LogNamer with the primary node (ie the one the logger runs on)
168 // being node.
Austin Schuh5b728b72021-06-16 14:57:15 -0700169 LogNamer(const aos::Configuration *configuration, EventLoop *event_loop,
170 const aos::Node *node)
Austin Schuha499cea2021-07-31 19:49:53 -0700171 : event_loop_(event_loop),
Austin Schuh5b728b72021-06-16 14:57:15 -0700172 configuration_(configuration),
173 node_(node),
Austin Schuha499cea2021-07-31 19:49:53 -0700174 logger_node_index_(configuration::GetNodeIndex(configuration_, node_)) {
Austin Schuh73340842021-07-30 22:32:06 -0700175 nodes_.emplace_back(node_);
Austin Schuh73340842021-07-30 22:32:06 -0700176 }
Alexei Strots01395492023-03-20 13:59:56 -0700177 virtual ~LogNamer() = default;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700178
Austin Schuh6bb8a822021-03-31 23:04:39 -0700179 virtual std::string_view base_name() const = 0;
180
181 // Rotate should be called at least once in between calls to set_base_name.
182 // Otherwise temporary files will not be recoverable.
183 // Rotate is called by Logger::RenameLogBase, which is currently the only user
184 // of this method.
185 // Only renaming the folder is supported, not the file base name.
Alexei Strots01395492023-03-20 13:59:56 -0700186 // TODO (Alexei): it should not be in interface, since it is not applied to
187 // files.
Austin Schuh6bb8a822021-03-31 23:04:39 -0700188 virtual void set_base_name(std::string_view base_name) = 0;
189
Brian Silverman87ac0402020-09-17 14:47:01 -0700190 // Returns a writer for writing data from messages on this channel (on the
191 // primary node).
192 //
193 // The returned pointer will stay valid across rotations, but the object it
194 // points to will be assigned to.
Austin Schuhb8bca732021-07-30 22:32:00 -0700195 virtual NewDataWriter *MakeWriter(const Channel *channel) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700196
Brian Silverman87ac0402020-09-17 14:47:01 -0700197 // Returns a writer for writing timestamps from messages on this channel (on
198 // the primary node).
199 //
200 // The returned pointer will stay valid across rotations, but the object it
201 // points to will be assigned to.
Austin Schuhb8bca732021-07-30 22:32:00 -0700202 virtual NewDataWriter *MakeTimestampWriter(const Channel *channel) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700203
204 // Returns a writer for writing timestamps delivered over the special
205 // /aos/remote_timestamps/* channels. node is the node that the timestamps
Brian Silverman87ac0402020-09-17 14:47:01 -0700206 // are forwarded back from (to the primary node).
207 //
208 // The returned pointer will stay valid across rotations, but the object it
209 // points to will be assigned to.
Austin Schuh73340842021-07-30 22:32:06 -0700210 virtual NewDataWriter *MakeForwardedTimestampWriter(const Channel *channel,
211 const Node *node) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700212
Austin Schuh73340842021-07-30 22:32:06 -0700213 // Rotates all log files for the provided node.
214 virtual void Rotate(const Node *node) = 0;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700215
216 // Returns all the nodes that data is being written for.
217 const std::vector<const Node *> &nodes() const { return nodes_; }
218
Austin Schuh08dba8f2023-05-01 08:29:30 -0700219 // Closes all existing log data writers. No more data may be written after
220 // this.
221 virtual WriteCode Close() = 0;
222
Austin Schuhcb5601b2020-09-10 15:29:59 -0700223 // Returns the node the logger is running on.
224 const Node *node() const { return node_; }
Austin Schuhe46492f2021-07-31 19:49:41 -0700225 const UUID &logger_node_boot_uuid() const { return logger_node_boot_uuid_; }
226 size_t logger_node_index() const { return logger_node_index_; }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700227
Austin Schuh8c399962020-12-25 21:51:45 -0800228 // Writes out the nested Configuration object to the config file location.
229 virtual void WriteConfiguration(
230 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
231 std::string_view config_sha256) = 0;
232
Austin Schuh73340842021-07-30 22:32:06 -0700233 void SetHeaderTemplate(
234 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> header) {
235 header_ = std::move(header);
Austin Schuhe46492f2021-07-31 19:49:41 -0700236 logger_node_boot_uuid_ =
237 UUID::FromString(header_.message().logger_node_boot_uuid());
Austin Schuh73340842021-07-30 22:32:06 -0700238 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700239
Austin Schuh60e77942022-05-16 17:48:24 -0700240 void ClearStartTimes() { node_states_.clear(); }
Austin Schuh58646e22021-08-23 23:51:46 -0700241
242 void SetStartTimes(size_t node_index, const UUID &boot_uuid,
Austin Schuh73340842021-07-30 22:32:06 -0700243 monotonic_clock::time_point monotonic_start_time,
244 realtime_clock::time_point realtime_start_time,
245 monotonic_clock::time_point logger_monotonic_start_time,
246 realtime_clock::time_point logger_realtime_start_time) {
Austin Schuh58646e22021-08-23 23:51:46 -0700247 VLOG(1) << "Setting node " << node_index << " to start time "
248 << monotonic_start_time << " rt " << realtime_start_time << " UUID "
249 << boot_uuid;
250 NodeState *node_state = GetNodeState(node_index, boot_uuid);
251 node_state->monotonic_start_time = monotonic_start_time;
252 node_state->realtime_start_time = realtime_start_time;
253 node_state->logger_monotonic_start_time = logger_monotonic_start_time;
254 node_state->logger_realtime_start_time = logger_realtime_start_time;
Austin Schuh73340842021-07-30 22:32:06 -0700255 }
256
Austin Schuh58646e22021-08-23 23:51:46 -0700257 monotonic_clock::time_point monotonic_start_time(size_t node_index,
258 const UUID &boot_uuid) {
259 DCHECK_NE(boot_uuid, UUID::Zero());
260
261 NodeState *node_state = GetNodeState(node_index, boot_uuid);
262 return node_state->monotonic_start_time;
Austin Schuh73340842021-07-30 22:32:06 -0700263 }
264
Austin Schuh73340842021-07-30 22:32:06 -0700265 protected:
Austin Schuh73340842021-07-30 22:32:06 -0700266 // Structure with state per node about times and such.
Austin Schuh73340842021-07-30 22:32:06 -0700267 struct NodeState {
268 // Time when this node started logging.
269 monotonic_clock::time_point monotonic_start_time =
270 monotonic_clock::min_time;
271 realtime_clock::time_point realtime_start_time = realtime_clock::min_time;
272
273 // Corresponding time on the logger node when it started logging.
274 monotonic_clock::time_point logger_monotonic_start_time =
275 monotonic_clock::min_time;
276 realtime_clock::time_point logger_realtime_start_time =
277 realtime_clock::min_time;
Austin Schuh73340842021-07-30 22:32:06 -0700278 };
Austin Schuh58646e22021-08-23 23:51:46 -0700279
280 // Creates a new header by copying fields out of the template and combining
281 // them with the arguments provided.
282 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> MakeHeader(
283 size_t node_index, const std::vector<NewDataWriter::State> &state,
284 const UUID &parts_uuid, int parts_index);
285
286 EventLoop *event_loop_;
287 const Configuration *const configuration_;
288 const Node *const node_;
289 const size_t logger_node_index_;
290 UUID logger_node_boot_uuid_;
291 std::vector<const Node *> nodes_;
292
293 friend NewDataWriter;
294
295 // Returns the start/stop time state structure for a node and boot. We can
296 // have data from multiple boots, and it makes sense to reuse the start/stop
297 // times if we get data from the same boot again.
298 NodeState *GetNodeState(size_t node_index, const UUID &boot_uuid);
299
300 absl::btree_map<std::pair<size_t, UUID>, NodeState> node_states_;
Austin Schuh73340842021-07-30 22:32:06 -0700301
302 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> header_ =
303 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader>::Empty();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700304};
305
Alexei Strots01395492023-03-20 13:59:56 -0700306// Log namer which uses a config to name a bunch of files.
Austin Schuhcb5601b2020-09-10 15:29:59 -0700307class MultiNodeLogNamer : public LogNamer {
308 public:
Alexei Strots01395492023-03-20 13:59:56 -0700309 MultiNodeLogNamer(std::unique_ptr<RenamableFileBackend> log_backend,
310 EventLoop *event_loop);
311 MultiNodeLogNamer(std::unique_ptr<RenamableFileBackend> log_backend,
Austin Schuh5b728b72021-06-16 14:57:15 -0700312 const Configuration *configuration, EventLoop *event_loop,
313 const Node *node);
Brian Silvermancb805822020-10-06 17:43:35 -0700314 ~MultiNodeLogNamer() override;
315
Alexei Strots01395492023-03-20 13:59:56 -0700316 std::string_view base_name() const final { return log_backend_->base_name(); }
Austin Schuh6bb8a822021-03-31 23:04:39 -0700317
318 void set_base_name(std::string_view base_name) final {
Alexei Strots01395492023-03-20 13:59:56 -0700319 log_backend_->RenameLogBase(base_name);
Austin Schuh6bb8a822021-03-31 23:04:39 -0700320 }
Brian Silvermancb805822020-10-06 17:43:35 -0700321
Alexei Strots01395492023-03-20 13:59:56 -0700322 // When enabled, this will write files under names beginning
323 // with the .tmp suffix, and then rename them to the desired name after
Brian Silverman48deab12020-09-30 18:39:28 -0700324 // they are fully written.
325 //
326 // This is useful to enable incremental copying of the log files.
327 //
328 // Defaults to writing directly to the final filename.
Alexei Strots01395492023-03-20 13:59:56 -0700329 void EnableTempFiles() { log_backend_->EnableTempFiles(); }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700330
Austin Schuh48d10d62022-10-16 22:19:23 -0700331 // Sets the function for creating encoders. The argument is the max message
332 // size (including headers) that will be written into this encoder.
Brian Silvermancb805822020-10-06 17:43:35 -0700333 //
334 // Defaults to just creating DummyEncoders.
335 void set_encoder_factory(
Austin Schuh48d10d62022-10-16 22:19:23 -0700336 std::function<std::unique_ptr<DataEncoder>(size_t)> encoder_factory) {
Brian Silvermancb805822020-10-06 17:43:35 -0700337 encoder_factory_ = std::move(encoder_factory);
338 }
339
340 // Sets an additional file extension.
341 //
342 // Defaults to nothing.
343 void set_extension(std::string_view extension) { extension_ = extension; }
Brian Silverman1f345222020-09-24 21:14:48 -0700344
Brian Silvermana621f522020-09-30 16:52:43 -0700345 // A list of all the filenames we've written.
346 //
347 // This only includes the part after base_name().
348 const std::vector<std::string> &all_filenames() const {
349 return all_filenames_;
350 }
351
Austin Schuh73340842021-07-30 22:32:06 -0700352 void Rotate(const Node *node) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700353
Austin Schuh8c399962020-12-25 21:51:45 -0800354 void WriteConfiguration(
355 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
356 std::string_view config_sha256) override;
357
Austin Schuhb8bca732021-07-30 22:32:00 -0700358 NewDataWriter *MakeWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700359
Austin Schuhb8bca732021-07-30 22:32:00 -0700360 NewDataWriter *MakeForwardedTimestampWriter(const Channel *channel,
Austin Schuh73340842021-07-30 22:32:06 -0700361 const Node *node) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700362
Austin Schuhb8bca732021-07-30 22:32:00 -0700363 NewDataWriter *MakeTimestampWriter(const Channel *channel) override;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700364
Brian Silverman0465fcf2020-09-24 00:29:18 -0700365 // Indicates that at least one file ran out of space. Once this happens, we
366 // stop trying to open new files, to avoid writing any files with holes from
367 // previous parts.
368 //
369 // Besides this function, this object will silently stop logging data when
370 // this occurs. If you want to ensure log files are complete, you must call
371 // this method.
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700372 bool ran_out_of_space() const {
373 return accumulate_data_writers<bool>(
Austin Schuhb8bca732021-07-30 22:32:00 -0700374 ran_out_of_space_, [](bool x, const NewDataWriter &data_writer) {
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700375 return x ||
376 (data_writer.writer && data_writer.writer->ran_out_of_space());
377 });
378 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700379
Brian Silverman1f345222020-09-24 21:14:48 -0700380 // Returns the maximum total_bytes() value for all existing
381 // DetachedBufferWriters.
382 //
383 // Returns 0 if no files are open.
384 size_t maximum_total_bytes() const {
Brian Silvermancb805822020-10-06 17:43:35 -0700385 return accumulate_data_writers<size_t>(
Austin Schuhb8bca732021-07-30 22:32:00 -0700386 0, [](size_t x, const NewDataWriter &data_writer) {
Brian Silvermancb805822020-10-06 17:43:35 -0700387 return std::max(x, data_writer.writer->total_bytes());
388 });
Brian Silverman1f345222020-09-24 21:14:48 -0700389 }
390
Brian Silverman0465fcf2020-09-24 00:29:18 -0700391 // Closes all existing log files. No more data may be written after this.
392 //
393 // This may set ran_out_of_space().
Austin Schuh08dba8f2023-05-01 08:29:30 -0700394 WriteCode Close() override;
Brian Silverman0465fcf2020-09-24 00:29:18 -0700395
Brian Silvermancb805822020-10-06 17:43:35 -0700396 // Accessors for various statistics. See the identically-named methods in
397 // DetachedBufferWriter for documentation. These are aggregated across all
398 // past and present DetachedBufferWriters.
399 std::chrono::nanoseconds max_write_time() const {
400 return accumulate_data_writers(
401 max_write_time_,
Austin Schuhb8bca732021-07-30 22:32:00 -0700402 [](std::chrono::nanoseconds x, const NewDataWriter &data_writer) {
Alexei Strots01395492023-03-20 13:59:56 -0700403 return std::max(
404 x, data_writer.writer->WriteStatistics()->max_write_time());
Brian Silvermancb805822020-10-06 17:43:35 -0700405 });
406 }
407 int max_write_time_bytes() const {
408 return std::get<0>(accumulate_data_writers(
409 std::make_tuple(max_write_time_bytes_, max_write_time_),
410 [](std::tuple<int, std::chrono::nanoseconds> x,
Austin Schuhb8bca732021-07-30 22:32:00 -0700411 const NewDataWriter &data_writer) {
Alexei Strots01395492023-03-20 13:59:56 -0700412 if (data_writer.writer->WriteStatistics()->max_write_time() >
413 std::get<1>(x)) {
414 return std::make_tuple(
415 data_writer.writer->WriteStatistics()->max_write_time_bytes(),
416 data_writer.writer->WriteStatistics()->max_write_time());
Brian Silvermancb805822020-10-06 17:43:35 -0700417 }
418 return x;
419 }));
420 }
421 int max_write_time_messages() const {
422 return std::get<0>(accumulate_data_writers(
423 std::make_tuple(max_write_time_messages_, max_write_time_),
424 [](std::tuple<int, std::chrono::nanoseconds> x,
Austin Schuhb8bca732021-07-30 22:32:00 -0700425 const NewDataWriter &data_writer) {
Alexei Strots01395492023-03-20 13:59:56 -0700426 if (data_writer.writer->WriteStatistics()->max_write_time() >
427 std::get<1>(x)) {
Brian Silvermancb805822020-10-06 17:43:35 -0700428 return std::make_tuple(
Alexei Strots01395492023-03-20 13:59:56 -0700429 data_writer.writer->WriteStatistics()
430 ->max_write_time_messages(),
431 data_writer.writer->WriteStatistics()->max_write_time());
Brian Silvermancb805822020-10-06 17:43:35 -0700432 }
433 return x;
434 }));
435 }
436 std::chrono::nanoseconds total_write_time() const {
437 return accumulate_data_writers(
438 total_write_time_,
Austin Schuhb8bca732021-07-30 22:32:00 -0700439 [](std::chrono::nanoseconds x, const NewDataWriter &data_writer) {
Alexei Strots01395492023-03-20 13:59:56 -0700440 return x + data_writer.writer->WriteStatistics()->total_write_time();
Brian Silvermancb805822020-10-06 17:43:35 -0700441 });
442 }
443 int total_write_count() const {
444 return accumulate_data_writers(
Austin Schuhb8bca732021-07-30 22:32:00 -0700445 total_write_count_, [](int x, const NewDataWriter &data_writer) {
Alexei Strots01395492023-03-20 13:59:56 -0700446 return x + data_writer.writer->WriteStatistics()->total_write_count();
Brian Silvermancb805822020-10-06 17:43:35 -0700447 });
448 }
449 int total_write_messages() const {
450 return accumulate_data_writers(
Austin Schuhb8bca732021-07-30 22:32:00 -0700451 total_write_messages_, [](int x, const NewDataWriter &data_writer) {
Alexei Strots01395492023-03-20 13:59:56 -0700452 return x +
453 data_writer.writer->WriteStatistics()->total_write_messages();
Brian Silvermancb805822020-10-06 17:43:35 -0700454 });
455 }
456 int total_write_bytes() const {
457 return accumulate_data_writers(
Austin Schuhb8bca732021-07-30 22:32:00 -0700458 total_write_bytes_, [](int x, const NewDataWriter &data_writer) {
Alexei Strots01395492023-03-20 13:59:56 -0700459 return x + data_writer.writer->WriteStatistics()->total_write_bytes();
Brian Silvermancb805822020-10-06 17:43:35 -0700460 });
461 }
462
463 void ResetStatistics();
464
Austin Schuhcb5601b2020-09-10 15:29:59 -0700465 private:
Austin Schuhcb5601b2020-09-10 15:29:59 -0700466 // Opens up a writer for timestamps forwarded back.
467 void OpenForwardedTimestampWriter(const Channel *channel,
Austin Schuhb8bca732021-07-30 22:32:00 -0700468 NewDataWriter *data_writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700469
470 // Opens up a writer for remote data.
Austin Schuhb8bca732021-07-30 22:32:00 -0700471 void OpenWriter(const Channel *channel, NewDataWriter *data_writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700472
473 // Opens the main data writer file for this node responsible for data_writer_.
Austin Schuh48d10d62022-10-16 22:19:23 -0700474 void MakeDataWriter();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700475
Austin Schuh48d10d62022-10-16 22:19:23 -0700476 void CreateBufferWriter(std::string_view path, size_t max_message_size,
Brian Silverman0465fcf2020-09-24 00:29:18 -0700477 std::unique_ptr<DetachedBufferWriter> *destination);
478
Brian Silvermancb805822020-10-06 17:43:35 -0700479 void CloseWriter(std::unique_ptr<DetachedBufferWriter> *writer_pointer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700480
Brian Silvermancb805822020-10-06 17:43:35 -0700481 // A version of std::accumulate which operates over all of our DataWriters.
482 template <typename T, typename BinaryOperation>
483 T accumulate_data_writers(T t, BinaryOperation op) const {
Austin Schuhb8bca732021-07-30 22:32:00 -0700484 for (const std::pair<const Channel *const, NewDataWriter> &data_writer :
Brian Silvermancb805822020-10-06 17:43:35 -0700485 data_writers_) {
Austin Schuhad0cfc32020-12-21 12:34:26 -0800486 if (!data_writer.second.writer) continue;
Brian Silvermancb805822020-10-06 17:43:35 -0700487 t = op(std::move(t), data_writer.second);
488 }
Austin Schuhb8bca732021-07-30 22:32:00 -0700489 if (data_writer_) {
490 t = op(std::move(t), *data_writer_);
Brian Silvermancb805822020-10-06 17:43:35 -0700491 }
492 return t;
493 }
494
Alexei Strots01395492023-03-20 13:59:56 -0700495 std::unique_ptr<RenamableFileBackend> log_backend_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700496
Brian Silverman0465fcf2020-09-24 00:29:18 -0700497 bool ran_out_of_space_ = false;
Brian Silvermana621f522020-09-30 16:52:43 -0700498 std::vector<std::string> all_filenames_;
Brian Silverman0465fcf2020-09-24 00:29:18 -0700499
Austin Schuh8bdfc492023-02-11 12:53:13 -0800500 std::function<std::unique_ptr<DataEncoder>(size_t)> encoder_factory_;
Brian Silvermancb805822020-10-06 17:43:35 -0700501 std::string extension_;
502
503 // Storage for statistics from previously-rotated DetachedBufferWriters.
504 std::chrono::nanoseconds max_write_time_ = std::chrono::nanoseconds::zero();
505 int max_write_time_bytes_ = -1;
506 int max_write_time_messages_ = -1;
507 std::chrono::nanoseconds total_write_time_ = std::chrono::nanoseconds::zero();
508 int total_write_count_ = 0;
509 int total_write_messages_ = 0;
510 int total_write_bytes_ = 0;
511
Austin Schuhcb5601b2020-09-10 15:29:59 -0700512 // File to write both delivery timestamps and local data to.
Austin Schuhb8bca732021-07-30 22:32:00 -0700513 std::unique_ptr<NewDataWriter> data_writer_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700514
Austin Schuhb8bca732021-07-30 22:32:00 -0700515 std::map<const Channel *, NewDataWriter> data_writers_;
Austin Schuhcb5601b2020-09-10 15:29:59 -0700516};
517
Alexei Strots01395492023-03-20 13:59:56 -0700518// This is specialized log namer that deals with directory centric log events.
519class MultiNodeFilesLogNamer : public MultiNodeLogNamer {
520 public:
521 MultiNodeFilesLogNamer(std::string_view base_name, EventLoop *event_loop)
522 : MultiNodeLogNamer(std::make_unique<RenamableFileBackend>(base_name),
523 event_loop) {}
524
525 MultiNodeFilesLogNamer(std::string_view base_name,
526 const Configuration *configuration,
527 EventLoop *event_loop, const Node *node)
528 : MultiNodeLogNamer(std::make_unique<RenamableFileBackend>(base_name),
529 configuration, event_loop, node) {}
530 ~MultiNodeFilesLogNamer() override = default;
531};
532
Austin Schuhcb5601b2020-09-10 15:29:59 -0700533} // namespace logger
534} // namespace aos
535
536#endif // AOS_EVENTS_LOGGING_LOG_NAMER_H_