blob: 44e8f5a939b1c17d414d45f6704ddf49a14b878e [file] [log] [blame]
Austin Schuhcb5601b2020-09-10 15:29:59 -07001#include "aos/events/logging/log_namer.h"
2
3#include <functional>
4#include <map>
5#include <memory>
6#include <string_view>
7#include <vector>
8
9#include "absl/strings/str_cat.h"
10#include "aos/events/logging/logfile_utils.h"
11#include "aos/events/logging/logger_generated.h"
12#include "aos/events/logging/uuid.h"
13#include "flatbuffers/flatbuffers.h"
14#include "glog/logging.h"
15
16namespace aos {
17namespace logger {
18
19void LogNamer::UpdateHeader(
20 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
21 const UUID &uuid, int parts_index) const {
22 header->mutable_message()->mutate_parts_index(parts_index);
23 CHECK_EQ(uuid.string_view().size(),
24 header->mutable_message()->mutable_parts_uuid()->size());
25 std::copy(uuid.string_view().begin(), uuid.string_view().end(),
26 reinterpret_cast<char *>(
27 header->mutable_message()->mutable_parts_uuid()->Data()));
28}
29
30void LocalLogNamer::WriteHeader(
31 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
32 const Node *node) {
33 CHECK_EQ(node, this->node());
34 UpdateHeader(header, uuid_, part_number_);
Austin Schuhadd6eb32020-11-09 21:24:26 -080035 data_writer_->QueueSpan(header->span());
Austin Schuhcb5601b2020-09-10 15:29:59 -070036}
37
38DetachedBufferWriter *LocalLogNamer::MakeWriter(const Channel *channel) {
Austin Schuhdf576472020-10-19 09:39:37 -070039 CHECK(configuration::ChannelIsSendableOnNode(channel, node()))
40 << ": " << configuration::CleanedChannelToString(channel);
Austin Schuhcb5601b2020-09-10 15:29:59 -070041 return data_writer_.get();
42}
43
44void LocalLogNamer::Rotate(
45 const Node *node,
46 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header) {
47 CHECK(node == this->node());
48 ++part_number_;
49 *data_writer_ = std::move(*OpenDataWriter());
50 UpdateHeader(header, uuid_, part_number_);
Austin Schuhadd6eb32020-11-09 21:24:26 -080051 data_writer_->QueueSpan(header->span());
Austin Schuhcb5601b2020-09-10 15:29:59 -070052}
Austin Schuh8c399962020-12-25 21:51:45 -080053
54void LocalLogNamer::WriteConfiguration(
55 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
56 std::string_view config_sha256) {
57 const std::string filename = absl::StrCat(base_name_, config_sha256, ".bfbs");
58
59 std::unique_ptr<DetachedBufferWriter> writer =
60 std::make_unique<DetachedBufferWriter>(
61 filename, std::make_unique<aos::logger::DummyEncoder>());
62 writer->QueueSizedFlatbuffer(header->Release());
63}
64
Austin Schuh315b96b2020-12-11 21:21:12 -080065void LocalLogNamer::Reboot(
66 const Node * /*node*/,
67 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> * /*header*/) {
68 LOG(FATAL) << "Can't reboot a single node.";
69}
Austin Schuhcb5601b2020-09-10 15:29:59 -070070
71DetachedBufferWriter *LocalLogNamer::MakeTimestampWriter(
72 const Channel *channel) {
73 CHECK(configuration::ChannelIsReadableOnNode(channel, node_))
74 << ": Message is not delivered to this node.";
75 CHECK(node_ != nullptr) << ": Can't log timestamps in a single node world";
76 CHECK(configuration::ConnectionDeliveryTimeIsLoggedOnNode(channel, node_,
77 node_))
78 << ": Delivery times aren't logged for this channel on this node.";
79 return data_writer_.get();
80}
81
82DetachedBufferWriter *LocalLogNamer::MakeForwardedTimestampWriter(
83 const Channel * /*channel*/, const Node * /*node*/) {
84 LOG(FATAL) << "Can't log forwarded timestamps in a singe log file.";
85 return nullptr;
86}
87
88MultiNodeLogNamer::MultiNodeLogNamer(std::string_view base_name,
89 const Configuration *configuration,
Brian Silvermancb805822020-10-06 17:43:35 -070090 const Node *node)
91 : LogNamer(node), base_name_(base_name), configuration_(configuration) {}
Austin Schuhcb5601b2020-09-10 15:29:59 -070092
Brian Silverman48deab12020-09-30 18:39:28 -070093MultiNodeLogNamer::~MultiNodeLogNamer() {
94 if (!ran_out_of_space_) {
95 // This handles renaming temporary files etc.
96 Close();
97 }
98}
99
Austin Schuhcb5601b2020-09-10 15:29:59 -0700100void MultiNodeLogNamer::WriteHeader(
101 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
102 const Node *node) {
103 if (node == this->node()) {
Brian Silvermancb805822020-10-06 17:43:35 -0700104 if (!data_writer_.writer) {
105 OpenDataWriter();
106 }
107 UpdateHeader(header, data_writer_.uuid, data_writer_.part_number);
Austin Schuhadd6eb32020-11-09 21:24:26 -0800108 data_writer_.writer->QueueSpan(header->span());
Austin Schuhcb5601b2020-09-10 15:29:59 -0700109 } else {
110 for (std::pair<const Channel *const, DataWriter> &data_writer :
111 data_writers_) {
112 if (node == data_writer.second.node) {
113 UpdateHeader(header, data_writer.second.uuid,
114 data_writer.second.part_number);
Austin Schuhadd6eb32020-11-09 21:24:26 -0800115 data_writer.second.writer->QueueSpan(header->span());
Austin Schuhcb5601b2020-09-10 15:29:59 -0700116 }
117 }
118 }
119}
120
121void MultiNodeLogNamer::Rotate(
122 const Node *node,
123 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header) {
Austin Schuh315b96b2020-12-11 21:21:12 -0800124 DoRotate(node, header, false);
125}
126
127void MultiNodeLogNamer::Reboot(
128 const Node *node,
129 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header) {
130 DoRotate(node, header, true);
131}
132
133void MultiNodeLogNamer::DoRotate(
134 const Node *node,
Austin Schuh8c399962020-12-25 21:51:45 -0800135 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
136 bool reboot) {
Austin Schuhcb5601b2020-09-10 15:29:59 -0700137 if (node == this->node()) {
Brian Silvermancb805822020-10-06 17:43:35 -0700138 if (data_writer_.writer) {
Austin Schuh315b96b2020-12-11 21:21:12 -0800139 if (reboot) {
140 data_writer_.uuid = UUID::Random();
141 }
Brian Silvermancb805822020-10-06 17:43:35 -0700142 ++data_writer_.part_number;
143 }
Brian Silvermana621f522020-09-30 16:52:43 -0700144 OpenDataWriter();
Brian Silvermancb805822020-10-06 17:43:35 -0700145 UpdateHeader(header, data_writer_.uuid, data_writer_.part_number);
Austin Schuhadd6eb32020-11-09 21:24:26 -0800146 data_writer_.writer->QueueSpan(header->span());
Austin Schuhcb5601b2020-09-10 15:29:59 -0700147 } else {
148 for (std::pair<const Channel *const, DataWriter> &data_writer :
149 data_writers_) {
150 if (node == data_writer.second.node) {
Austin Schuh315b96b2020-12-11 21:21:12 -0800151 if (reboot) {
152 data_writer.second.uuid = UUID::Random();
153 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700154 ++data_writer.second.part_number;
155 data_writer.second.rotate(data_writer.first, &data_writer.second);
156 UpdateHeader(header, data_writer.second.uuid,
157 data_writer.second.part_number);
Austin Schuhadd6eb32020-11-09 21:24:26 -0800158 data_writer.second.writer->QueueSpan(header->span());
Austin Schuhcb5601b2020-09-10 15:29:59 -0700159 }
160 }
161 }
162}
163
Austin Schuh8c399962020-12-25 21:51:45 -0800164void MultiNodeLogNamer::WriteConfiguration(
165 aos::SizePrefixedFlatbufferDetachedBuffer<LogFileHeader> *header,
166 std::string_view config_sha256) {
167 if (ran_out_of_space_) {
168 return;
169 }
170
171 const std::string_view separator = base_name_.back() == '/' ? "" : "_";
172 const std::string filename = absl::StrCat(
173 base_name_, separator, config_sha256, ".bfbs", extension_, temp_suffix_);
174
175 std::unique_ptr<DetachedBufferWriter> writer =
176 std::make_unique<DetachedBufferWriter>(filename, encoder_factory_());
177
178 writer->QueueSizedFlatbuffer(header->Release());
179
180 if (!writer->ran_out_of_space()) {
181 all_filenames_.emplace_back(filename);
182 }
183 CloseWriter(&writer);
184}
185
Austin Schuhcb5601b2020-09-10 15:29:59 -0700186DetachedBufferWriter *MultiNodeLogNamer::MakeWriter(const Channel *channel) {
187 // See if we can read the data on this node at all.
188 const bool is_readable =
189 configuration::ChannelIsReadableOnNode(channel, this->node());
190 if (!is_readable) {
191 return nullptr;
192 }
193
194 // Then, see if we are supposed to log the data here.
195 const bool log_message =
196 configuration::ChannelMessageIsLoggedOnNode(channel, this->node());
197
198 if (!log_message) {
199 return nullptr;
200 }
201
202 // Now, sort out if this is data generated on this node, or not. It is
203 // generated if it is sendable on this node.
204 if (configuration::ChannelIsSendableOnNode(channel, this->node())) {
Brian Silvermancb805822020-10-06 17:43:35 -0700205 if (!data_writer_.writer) {
206 OpenDataWriter();
207 }
208 return data_writer_.writer.get();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700209 }
210
211 // Ok, we have data that is being forwarded to us that we are supposed to
212 // log. It needs to be logged with send timestamps, but be sorted enough
213 // to be able to be processed.
214 CHECK(data_writers_.find(channel) == data_writers_.end());
215
216 // Track that this node is being logged.
217 const Node *source_node = configuration::GetNode(
218 configuration_, channel->source_node()->string_view());
219
220 if (std::find(nodes_.begin(), nodes_.end(), source_node) == nodes_.end()) {
221 nodes_.emplace_back(source_node);
222 }
223
224 DataWriter data_writer;
225 data_writer.node = source_node;
226 data_writer.rotate = [this](const Channel *channel, DataWriter *data_writer) {
227 OpenWriter(channel, data_writer);
228 };
229 data_writer.rotate(channel, &data_writer);
230
231 return data_writers_.insert(std::make_pair(channel, std::move(data_writer)))
232 .first->second.writer.get();
233}
234
235DetachedBufferWriter *MultiNodeLogNamer::MakeForwardedTimestampWriter(
236 const Channel *channel, const Node *node) {
237 // See if we can read the data on this node at all.
238 const bool is_readable =
239 configuration::ChannelIsReadableOnNode(channel, this->node());
240 CHECK(is_readable) << ": " << configuration::CleanedChannelToString(channel);
241
242 CHECK(data_writers_.find(channel) == data_writers_.end());
243
244 if (std::find(nodes_.begin(), nodes_.end(), node) == nodes_.end()) {
245 nodes_.emplace_back(node);
246 }
247
248 DataWriter data_writer;
249 data_writer.node = node;
250 data_writer.rotate = [this](const Channel *channel, DataWriter *data_writer) {
251 OpenForwardedTimestampWriter(channel, data_writer);
252 };
253 data_writer.rotate(channel, &data_writer);
254
255 return data_writers_.insert(std::make_pair(channel, std::move(data_writer)))
256 .first->second.writer.get();
257}
258
259DetachedBufferWriter *MultiNodeLogNamer::MakeTimestampWriter(
260 const Channel *channel) {
Brian Silverman0465fcf2020-09-24 00:29:18 -0700261 bool log_delivery_times = false;
262 if (this->node() != nullptr) {
263 log_delivery_times = configuration::ConnectionDeliveryTimeIsLoggedOnNode(
264 channel, this->node(), this->node());
265 }
Austin Schuhcb5601b2020-09-10 15:29:59 -0700266 if (!log_delivery_times) {
267 return nullptr;
268 }
269
Brian Silvermancb805822020-10-06 17:43:35 -0700270 if (!data_writer_.writer) {
271 OpenDataWriter();
272 }
273 return data_writer_.writer.get();
Austin Schuhcb5601b2020-09-10 15:29:59 -0700274}
275
Brian Silverman0465fcf2020-09-24 00:29:18 -0700276void MultiNodeLogNamer::Close() {
277 for (std::pair<const Channel *const, DataWriter> &data_writer :
278 data_writers_) {
Brian Silvermancb805822020-10-06 17:43:35 -0700279 CloseWriter(&data_writer.second.writer);
280 data_writer.second.writer.reset();
Brian Silverman0465fcf2020-09-24 00:29:18 -0700281 }
Brian Silvermancb805822020-10-06 17:43:35 -0700282 CloseWriter(&data_writer_.writer);
283 data_writer_.writer.reset();
284}
285
286void MultiNodeLogNamer::ResetStatistics() {
287 for (std::pair<const Channel *const, DataWriter> &data_writer :
288 data_writers_) {
Austin Schuhad0cfc32020-12-21 12:34:26 -0800289 if (!data_writer.second.writer) continue;
Brian Silvermancb805822020-10-06 17:43:35 -0700290 data_writer.second.writer->ResetStatistics();
Brian Silverman0465fcf2020-09-24 00:29:18 -0700291 }
Brian Silvermancb805822020-10-06 17:43:35 -0700292 if (data_writer_.writer) {
293 data_writer_.writer->ResetStatistics();
294 }
295 max_write_time_ = std::chrono::nanoseconds::zero();
296 max_write_time_bytes_ = -1;
297 max_write_time_messages_ = -1;
298 total_write_time_ = std::chrono::nanoseconds::zero();
299 total_write_count_ = 0;
300 total_write_messages_ = 0;
301 total_write_bytes_ = 0;
Brian Silverman0465fcf2020-09-24 00:29:18 -0700302}
303
Austin Schuhcb5601b2020-09-10 15:29:59 -0700304void MultiNodeLogNamer::OpenForwardedTimestampWriter(const Channel *channel,
305 DataWriter *data_writer) {
306 std::string filename =
Austin Schuhe715eae2020-10-10 15:39:30 -0700307 absl::StrCat("timestamps", channel->name()->string_view(), "/",
Brian Silvermana621f522020-09-30 16:52:43 -0700308 channel->type()->string_view(), ".part",
Brian Silverman1b071eb2020-10-09 12:24:10 -0700309 data_writer->part_number, ".bfbs", extension_);
Brian Silverman0465fcf2020-09-24 00:29:18 -0700310 CreateBufferWriter(filename, &data_writer->writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700311}
312
313void MultiNodeLogNamer::OpenWriter(const Channel *channel,
314 DataWriter *data_writer) {
315 const std::string filename = absl::StrCat(
Austin Schuhe715eae2020-10-10 15:39:30 -0700316 CHECK_NOTNULL(channel->source_node())->string_view(), "_data",
Brian Silvermana621f522020-09-30 16:52:43 -0700317 channel->name()->string_view(), "/", channel->type()->string_view(),
Brian Silvermancb805822020-10-06 17:43:35 -0700318 ".part", data_writer->part_number, ".bfbs", extension_);
Brian Silverman0465fcf2020-09-24 00:29:18 -0700319 CreateBufferWriter(filename, &data_writer->writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700320}
321
Brian Silvermana621f522020-09-30 16:52:43 -0700322void MultiNodeLogNamer::OpenDataWriter() {
323 std::string name;
Brian Silverman7af8c902020-09-29 16:14:04 -0700324 if (node() != nullptr) {
Austin Schuhe715eae2020-10-10 15:39:30 -0700325 name = absl::StrCat(name, node()->name()->string_view(), "_");
Brian Silverman7af8c902020-09-29 16:14:04 -0700326 }
Austin Schuhe715eae2020-10-10 15:39:30 -0700327 absl::StrAppend(&name, "data.part", data_writer_.part_number, ".bfbs",
Brian Silvermancb805822020-10-06 17:43:35 -0700328 extension_);
329 CreateBufferWriter(name, &data_writer_.writer);
Austin Schuhcb5601b2020-09-10 15:29:59 -0700330}
331
Brian Silverman0465fcf2020-09-24 00:29:18 -0700332void MultiNodeLogNamer::CreateBufferWriter(
Brian Silvermana621f522020-09-30 16:52:43 -0700333 std::string_view path, std::unique_ptr<DetachedBufferWriter> *destination) {
Brian Silverman0465fcf2020-09-24 00:29:18 -0700334 if (ran_out_of_space_) {
335 // Refuse to open any new files, which might skip data. Any existing files
336 // are in the same folder, which means they're on the same filesystem, which
337 // means they're probably going to run out of space and get stuck too.
338 return;
339 }
Austin Schuhe715eae2020-10-10 15:39:30 -0700340 const std::string_view separator = base_name_.back() == '/' ? "" : "_";
341 const std::string filename =
342 absl::StrCat(base_name_, separator, path, temp_suffix_);
Brian Silverman0465fcf2020-09-24 00:29:18 -0700343 if (!destination->get()) {
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700344 if (ran_out_of_space_) {
345 *destination = std::make_unique<DetachedBufferWriter>(
346 DetachedBufferWriter::already_out_of_space_t());
347 return;
348 }
Brian Silvermancb805822020-10-06 17:43:35 -0700349 *destination =
350 std::make_unique<DetachedBufferWriter>(filename, encoder_factory_());
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700351 if (!destination->get()->ran_out_of_space()) {
352 all_filenames_.emplace_back(path);
353 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700354 return;
355 }
Brian Silvermancb805822020-10-06 17:43:35 -0700356
357 CloseWriter(destination);
358 if (ran_out_of_space_) {
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700359 *destination->get() =
360 DetachedBufferWriter(DetachedBufferWriter::already_out_of_space_t());
Brian Silverman0465fcf2020-09-24 00:29:18 -0700361 return;
362 }
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700363
Brian Silvermancb805822020-10-06 17:43:35 -0700364 *destination->get() = DetachedBufferWriter(filename, encoder_factory_());
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700365 if (!destination->get()->ran_out_of_space()) {
366 all_filenames_.emplace_back(path);
367 }
Brian Silverman0465fcf2020-09-24 00:29:18 -0700368}
369
Brian Silverman48deab12020-09-30 18:39:28 -0700370void MultiNodeLogNamer::RenameTempFile(DetachedBufferWriter *destination) {
371 if (temp_suffix_.empty()) {
372 return;
373 }
374 const std::string current_filename = std::string(destination->filename());
375 CHECK(current_filename.size() > temp_suffix_.size());
376 const std::string final_filename =
377 current_filename.substr(0, current_filename.size() - temp_suffix_.size());
378 const int result = rename(current_filename.c_str(), final_filename.c_str());
379 if (result != 0) {
380 if (errno == ENOSPC) {
381 ran_out_of_space_ = true;
382 return;
383 } else {
384 PLOG(FATAL) << "Renaming " << current_filename << " to " << final_filename
385 << " failed";
386 }
387 }
388}
389
Brian Silvermancb805822020-10-06 17:43:35 -0700390void MultiNodeLogNamer::CloseWriter(
391 std::unique_ptr<DetachedBufferWriter> *writer_pointer) {
392 DetachedBufferWriter *const writer = writer_pointer->get();
393 if (!writer) {
394 return;
395 }
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700396 const bool was_open = writer->is_open();
Brian Silvermancb805822020-10-06 17:43:35 -0700397 writer->Close();
398
399 if (writer->max_write_time() > max_write_time_) {
400 max_write_time_ = writer->max_write_time();
401 max_write_time_bytes_ = writer->max_write_time_bytes();
402 max_write_time_messages_ = writer->max_write_time_messages();
403 }
404 total_write_time_ += writer->total_write_time();
405 total_write_count_ += writer->total_write_count();
406 total_write_messages_ += writer->total_write_messages();
407 total_write_bytes_ += writer->total_write_bytes();
408
409 if (writer->ran_out_of_space()) {
410 ran_out_of_space_ = true;
411 writer->acknowledge_out_of_space();
412 }
Brian Silvermana9f2ec92020-10-06 18:00:53 -0700413 if (was_open) {
414 RenameTempFile(writer);
415 } else {
416 CHECK(access(std::string(writer->filename()).c_str(), F_OK) == -1)
417 << ": File should not exist: " << writer->filename();
418 }
Brian Silvermancb805822020-10-06 17:43:35 -0700419}
420
Austin Schuhcb5601b2020-09-10 15:29:59 -0700421} // namespace logger
422} // namespace aos