Skip to content

Commit 819ee4e

Browse files
authored
Separate variable reference, type, causality into separate header lines (#725)
* changed file logger headers * remove extra header lines * added metadata file * only log metadata for configured variables * use same timestamp for metadata and csv * clang-tidy * fix dynamic logging test
1 parent 106d494 commit 819ee4e

3 files changed

Lines changed: 84 additions & 12 deletions

File tree

src/cosim/observer/file_observer.cpp

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ class file_observer::slave_value_writer
7575
std::lock_guard<std::mutex> lock(mutex_);
7676
if (recording_) {
7777
if (!fsw_.is_open()) {
78-
create_log_file();
78+
auto dataFileName = create_log_file();
79+
create_metadata_file(dataFileName);
7980
}
8081
if (timeStep % decimationFactor_ == 0) {
8182

@@ -130,6 +131,8 @@ class file_observer::slave_value_writer
130131
}
131132

132133
private:
134+
int keyWidth_ = 14;
135+
133136
template<typename T>
134137
void write(const std::vector<T>& values, std::stringstream& ss)
135138
{
@@ -160,7 +163,7 @@ class file_observer::slave_value_writer
160163
}
161164
}
162165

163-
/** Default constructor initialization, all variables are logged. */
166+
/** Default constructor initialization, all variables - except those with causality local - are logged. */
164167
void initialize_default()
165168
{
166169
if (!timeStampedFileNames_) {
@@ -188,14 +191,16 @@ class file_observer::slave_value_writer
188191
}
189192
}
190193

191-
void create_log_file()
194+
std::string create_log_file()
192195
{
193196
std::string filename;
194197
std::stringstream ss;
198+
std::string time_str;
199+
195200
if (!timeStampedFileNames_) {
196201
filename = observable_->name().append(".csv");
197202
} else {
198-
auto time_str = format_time(boost::posix_time::microsec_clock::local_time());
203+
time_str = format_time(boost::posix_time::microsec_clock::local_time());
199204
filename = observable_->name().append("_").append(time_str).append(".csv");
200205
}
201206

@@ -204,29 +209,93 @@ class file_observer::slave_value_writer
204209
fsw_.open(filePath, std::ios_base::out | std::ios_base::app);
205210

206211
if (fsw_.fail()) {
207-
throw std::runtime_error("Failed to open file stream for logging");
212+
std::stringstream error;
213+
error << "Failed to open log file stream: " << filePath.c_str();
214+
throw std::runtime_error(error.str());
208215
}
209216

210217
ss << "Time,StepCount";
211218

219+
// Add variable names
212220
for (const auto& vd : realVars_) {
213-
ss << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
221+
ss << "," << vd.name;
214222
}
215223
for (const auto& vd : intVars_) {
216-
ss << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
224+
ss << "," << vd.name;
217225
}
218226
for (const auto& vd : boolVars_) {
219-
ss << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
227+
ss << "," << vd.name;
220228
}
221229
for (const auto& vd : stringVars_) {
222-
ss << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
230+
ss << "," << vd.name;
223231
}
224232

225233
ss << std::endl;
226234

227235
if (fsw_.is_open()) {
228236
fsw_ << ss.rdbuf();
229237
}
238+
239+
return time_str;
240+
}
241+
242+
void write_variable_metadata(std::stringstream& ss, std::vector<variable_description>& variables) const
243+
{
244+
for (const auto& v : variables) {
245+
ss << " - " << std::setw(keyWidth_) << "name:" << v.name << std::endl
246+
<< " " << std::setw(keyWidth_) << "reference:" << v.reference << std::endl
247+
<< " " << std::setw(keyWidth_) << "type:" << v.type << std::endl
248+
<< " " << std::setw(keyWidth_) << "causality:" << v.causality << std::endl
249+
<< " " << std::setw(keyWidth_) << "variability:" << v.variability << std::endl;
250+
251+
if (v.start.has_value()) {
252+
ss << " " << std::setw(keyWidth_) << "start value:";
253+
std::visit([&](const auto& val) { ss << val << std::endl; }, v.start.value());
254+
}
255+
}
256+
}
257+
258+
void create_metadata_file(const std::string& time_str)
259+
{
260+
std::ofstream metadata_fw;
261+
std::string filename;
262+
std::stringstream ss;
263+
264+
if (!timeStampedFileNames_) {
265+
filename = observable_->name().append("_metadata.yaml");
266+
} else {
267+
filename = observable_->name().append("_").append(time_str).append("_metadata.yaml");
268+
}
269+
270+
const auto filePath = logDir_ / filename;
271+
metadata_fw.open(filePath, std::ios_base::out | std::ios_base::app);
272+
273+
if (fsw_.fail()) {
274+
std::stringstream error;
275+
error << "Failed to open log metadata file stream: " << filePath.c_str();
276+
throw std::runtime_error(error.str());
277+
}
278+
279+
auto md = observable_->model_description();
280+
281+
ss << std::left
282+
<< std::setw(keyWidth_) << "name:" << md.name << std::endl
283+
<< std::setw(keyWidth_) << "uuid:" << md.uuid << std::endl
284+
<< std::setw(keyWidth_) << "description:" << md.description << std::endl
285+
<< std::setw(keyWidth_) << "author:" << md.description << std::endl
286+
<< std::setw(keyWidth_) << "version:" << md.version << std::endl;
287+
288+
ss << "variables:" << std::endl;
289+
290+
write_variable_metadata(ss, realVars_);
291+
write_variable_metadata(ss, intVars_);
292+
write_variable_metadata(ss, boolVars_);
293+
write_variable_metadata(ss, stringVars_);
294+
295+
if (metadata_fw.is_open()) {
296+
metadata_fw << ss.rdbuf();
297+
}
298+
metadata_fw.close();
230299
}
231300

232301
void persist()

tests/data/LogConfig.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<simulator name="slave" decimationFactor="20">
66
<variable name="realOut"/>
77
<variable name="intOut"/>
8-
<variable name="booleanOut"/>
8+
<!--variable name="booleanOut"/-->
99
<variable name="stringOut"/>
1010
</simulator>
1111
<simulator name="slave2">

tests/file_observer_dynamic_logging_test.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <cosim/observer/file_observer.hpp>
88

99
#include <exception>
10+
#include <iostream>
1011
#include <memory>
1112
#include <stdexcept>
1213
#include <thread>
@@ -74,7 +75,7 @@ int main()
7475
observer->stop_recording();
7576
REQUIRE(!observer->is_recording());
7677

77-
REQUIRE(filecount(logPath) == 2);
78+
REQUIRE(filecount(logPath) == 4);
7879

7980
remove_directory_contents(logPath);
8081
REQUIRE(filecount(logPath) == 0);
@@ -91,10 +92,12 @@ int main()
9192

9293
execution.stop_simulation();
9394
t.get();
94-
REQUIRE(filecount(logPath) == 4);
95+
96+
REQUIRE(filecount(logPath) == 8);
9597

9698
// Test that files are released.
9799
remove_directory_contents(logPath);
100+
98101
REQUIRE(filecount(logPath) == 0);
99102

100103
} catch (const std::exception& e) {

0 commit comments

Comments
 (0)