Add LogReplayerStats message
This change adds start and stop times of when replay happens in
log_replayer and the replay_config used as an fbs message that is sent
on the /replay channel when replay is complete.
The start and stop times are needed to properly determine
when exactly log replay was happening to analyze the results of a
resulting diagnostic log only within the context of replay.
Change-Id: Ic86c41f11689597986e02b6154f18bb5c8552b2c
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/aos/events/logging/BUILD b/aos/events/logging/BUILD
index fef834b..a687748 100644
--- a/aos/events/logging/BUILD
+++ b/aos/events/logging/BUILD
@@ -28,14 +28,31 @@
)
flatbuffer_cc_library(
+ name = "log_replayer_stats_fbs",
+ srcs = ["log_replayer_stats.fbs"],
+ gen_reflections = True,
+ target_compatible_with = ["@platforms//os:linux"],
+ deps = [
+ ":replay_config_fbs",
+ ],
+)
+
+cc_static_flatbuffer(
+ name = "log_replayer_stats_schema",
+ function = "aos::LogReplayerStatsSchema",
+ target = ":log_replayer_stats_fbs_reflection_out",
+ visibility = ["//visibility:public"],
+)
+
+flatbuffer_cc_library(
name = "replay_config_fbs",
srcs = ["log_replayer_config.fbs"],
gen_reflections = True,
- includes = [
- "//aos:configuration_fbs_includes",
- ],
target_compatible_with = ["@platforms//os:linux"],
visibility = ["//visibility:public"],
+ deps = [
+ "//aos:configuration_fbs",
+ ],
)
cc_library(
@@ -59,6 +76,8 @@
deps = [
":log_reader",
":log_reader_utils",
+ ":log_replayer_stats_fbs",
+ ":log_replayer_stats_schema",
":replay_config_fbs",
":replay_timing_fbs",
":replay_timing_schema",
diff --git a/aos/events/logging/log_replayer.cc b/aos/events/logging/log_replayer.cc
index b69df4a..22d8b39 100644
--- a/aos/events/logging/log_replayer.cc
+++ b/aos/events/logging/log_replayer.cc
@@ -16,6 +16,8 @@
#include "aos/events/logging/log_reader.h"
#include "aos/events/logging/log_reader_utils.h"
#include "aos/events/logging/log_replayer_config_generated.h"
+#include "aos/events/logging/log_replayer_stats_generated.h"
+#include "aos/events/logging/log_replayer_stats_schema.h"
#include "aos/events/logging/logfile_sorting.h"
#include "aos/events/logging/logfile_utils.h"
#include "aos/events/logging/replay_timing_generated.h"
@@ -48,6 +50,8 @@
DEFINE_string(merge_with_config, "",
"A valid json string to be merged with config. This is used to "
"add extra applications needed to run only for log_replayer");
+DEFINE_bool(print_stats, true,
+ "if set, prints the LogReplayerStats message as JSON to stdout");
namespace aos::logger {
@@ -75,6 +79,16 @@
aos::configuration::GetMyNode(raw_config), channel_overrides);
}
+ // Add the LogReplayerStats channel
+ const aos::Configuration *raw_config = &config.message();
+ aos::ChannelT channel_overrides;
+ channel_overrides.max_size = 10000;
+ channel_overrides.frequency = 1;
+ config = aos::configuration::AddChannelToConfiguration(
+ raw_config, "/replay",
+ aos::FlatbufferSpan<reflection::Schema>(aos::LogReplayerStatsSchema()),
+ aos::configuration::GetMyNode(raw_config), channel_overrides);
+
if (!FLAGS_merge_with_config.empty()) {
config = aos::configuration::MergeWithConfig(&config.message(),
FLAGS_merge_with_config);
@@ -139,7 +153,49 @@
event_loop.SkipAosLog();
event_loop.SkipTimingReport();
+ aos::Sender<aos::LogReplayerStats> stats_sender =
+ event_loop.MakeSender<aos::LogReplayerStats>("/replay");
+ auto builder = stats_sender.MakeBuilder();
+ auto node_name = builder.fbb()->CreateString(event_loop.node()->name());
+ flatbuffers::Offset<aos::ReplayConfig> replay_config_offset;
+ if (replay_config.has_value()) {
+ replay_config_offset =
+ aos::CopyFlatBuffer(&replay_config.value().message(), builder.fbb());
+ }
+
+ auto stats_builder = builder.MakeBuilder<aos::LogReplayerStats>();
+ if (replay_config.has_value()) {
+ stats_builder.add_replay_config(replay_config_offset);
+ }
+
reader.Register(&event_loop);
+
+ // Save off the start and end times of replay.
+ reader.OnStart(event_loop.node(), [&event_loop, &stats_builder,
+ &node_name]() {
+ stats_builder.add_node(node_name);
+ stats_builder.add_realtime_start_time(
+ std::chrono::nanoseconds(event_loop.realtime_now().time_since_epoch())
+ .count());
+
+ stats_builder.add_monotonic_start_time(
+ std::chrono::nanoseconds(
+ event_loop.monotonic_now().time_since_epoch())
+ .count());
+ });
+
+ reader.OnEnd(event_loop.node(), [&event_loop, &stats_builder, &builder]() {
+ stats_builder.add_realtime_end_time(
+ std::chrono::nanoseconds(event_loop.realtime_now().time_since_epoch())
+ .count());
+
+ stats_builder.add_monotonic_end_time(
+ std::chrono::nanoseconds(
+ event_loop.monotonic_now().time_since_epoch())
+ .count());
+ builder.CheckOk(builder.Send(stats_builder.Finish()));
+ });
+
reader.OnEnd(event_loop.node(), [&event_loop]() { event_loop.Exit(); });
if (FLAGS_plot_timing) {
@@ -152,6 +208,13 @@
event_loop.Run();
reader.Deregister();
+
+ if (FLAGS_print_stats) {
+ aos::Fetcher<aos::LogReplayerStats> stats_fetcher =
+ event_loop.MakeFetcher<aos::LogReplayerStats>("/replay");
+ CHECK(stats_fetcher.Fetch()) << "Failed to fetch LogReplayerStats!";
+ std::cout << aos::FlatbufferToJson(stats_fetcher.get());
+ }
}
return EXIT_SUCCESS;
diff --git a/aos/events/logging/log_replayer_stats.fbs b/aos/events/logging/log_replayer_stats.fbs
new file mode 100644
index 0000000..8e54fdb
--- /dev/null
+++ b/aos/events/logging/log_replayer_stats.fbs
@@ -0,0 +1,19 @@
+include "log_replayer_config.fbs";
+
+namespace aos;
+
+table LogReplayerStats {
+ // The ReplayConfig passed to log_replayer.
+ replay_config:ReplayConfig (id: 0);
+ // Realtime start and end times of log replay, in nanoseconds.
+ realtime_start_time:int64 (id: 1);
+ realtime_end_time:int64 (id: 2);
+ // Monotonic start and end times of log replay, in nanoseconds.
+ monotonic_start_time:int64 (id: 3);
+ monotonic_end_time:int64 (id: 4);
+ // Name of the node where the log originated from.
+ // Note: Currently, only single node replay is supported.
+ node:string (id: 5);
+}
+
+root_type LogReplayerStats;