Recording and Replay
AstuteDDS provides DataLogTool (<astutedds/dcps/record_replay.hpp>) for capturing
raw DDS payload streams to disk and replaying them later, preserving the original
inter-sample timing.
Use Cases
- System-level regression testing: Record production traffic, replay against new software versions.
- Simulation and training: Pre-record realistic sensor feeds and replay on demand.
- Debugging: Capture anomalous behaviour for offline analysis.
- Interop logging: Archive DDS traffic for certification evidence.
Data Structures
struct astutedds::dcps::LoggedSample
{
uint64_t relative_timestamp_ns{0}; // nanoseconds since first sample
std::string topic_name;
std::vector<uint8_t> payload; // raw XCDR-serialised bytes
};
Recording
Collect samples from DataReaders and build the LoggedSample list, then write them
to a binary .addslog file:
#include <astutedds/dcps/record_replay.hpp>
std::vector<astutedds::dcps::LoggedSample> samples;
auto t0 = std::chrono::steady_clock::now();
// In your DataReader read/take loop:
for (auto& raw : raw_samples)
{
auto elapsed = std::chrono::steady_clock::now() - t0;
samples.push_back({
static_cast<uint64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count()),
"MyTopic",
raw.serialized_payload // XCDR bytes from the sample info
});
}
// Write to disk
auto rc = astutedds::dcps::DataLogTool::write_samples("capture.addslog", samples);
if (rc != astutedds::dcps::ReturnCode_t::RETCODE_OK)
std::cerr << "Failed to write log\n";
The file format uses an ADDSRPL1 magic header and FORMAT_VERSION = 1. It is
designed for forward compatibility.
Playback
Step 1 — Read the log
std::vector<astutedds::dcps::LoggedSample> samples;
auto rc = astutedds::dcps::DataLogTool::read_samples("capture.addslog", samples);
if (rc != astutedds::dcps::ReturnCode_t::RETCODE_OK)
{
std::cerr << "Failed to read log\n";
return 1;
}
Step 2 — Replay through a DomainParticipant
#include <astutedds/dcps/domain_participant.hpp>
auto participant = astutedds::dcps::DomainParticipantFactory::create_participant(0);
// Samples are replayed with the original inter-sample spacing preserved
auto rc = astutedds::dcps::DataLogTool::replay_samples(*participant, samples);
replay_samples() drives DomainParticipant::send_data() for each sample, sleeping
between samples to honour the relative_timestamp_ns deltas. Samples must be
sorted with monotonically non-decreasing timestamps; RETCODE_BAD_PARAMETER is
returned otherwise.
File Size Limits
The following limits are enforced when reading log files to prevent resource exhaustion:
| Limit | Value |
|---|---|
| Maximum topic name | 1 024 bytes |
| Maximum payload size | 32 MiB per sample |
| Maximum sample count | 1 000 000 samples |
Combining Recording with XML QoS
Configure writers and readers from an XML profile, then record:
#include <astutedds/dcps/xml_config.hpp>
#include <astutedds/dcps/record_replay.hpp>
astutedds::dcps::XmlQosLoader loader;
loader.load_file("profiles.xml");
astutedds::dcps::DataReaderQos rqos;
loader.get_datareader_qos("MyLib::ReliableProfile", rqos);
auto reader = subscriber->create_datareader(topic, rqos);
// … record samples as above …