Communication Library for Autonomous Systems v1.0
Reliable and secure communication library for autonomous vehicle systems
Loading...
Searching...
No Matches
csv_logger.h
Go to the documentation of this file.
1#ifndef CSV_LOGGER_H
2#define CSV_LOGGER_H
3
4#include <fstream>
5#include <string>
6#include <memory>
7#include <pthread.h>
8#include <chrono>
9#include <sstream>
10#include <iomanip>
11#include <cstddef>
12#include <sys/stat.h>
13#include <sys/types.h>
14#include <exception>
15#include <ios>
16#include <ostream>
17#include <ctime>
18
19class CSVLogger {
20public:
21 CSVLogger(const std::string& filepath, const std::string& header);
22 ~CSVLogger();
23
24 void log(const std::string& csv_line);
25 void flush();
26 bool is_open() const;
27
28 // Static method to create vehicle-specific log directory
29 static std::string create_vehicle_log_dir(unsigned int vehicle_id);
30
31private:
32 std::unique_ptr<std::ofstream> _file;
33 pthread_mutex_t _mutex;
34 bool _is_open;
35
36 std::string get_timestamp();
37 static bool create_directory(const std::string& path);
38 static std::string get_directory_from_path(const std::string& filepath);
39};
40
41// Implementation
42inline CSVLogger::CSVLogger(const std::string& filepath, const std::string& header) : _is_open(false) {
43 pthread_mutex_init(&_mutex, nullptr);
44
45 // Create directory if it doesn't exist
46 std::string dir_path = get_directory_from_path(filepath);
47
48 try {
49 if (!dir_path.empty()) {
50 create_directory(dir_path);
51 }
52
53 _file = std::make_unique<std::ofstream>(filepath, std::ios::out | std::ios::app);
54 if (_file->is_open()) {
55 // Check if file is empty (new file) to write header
56 _file->seekp(0, std::ios::end);
57 if (_file->tellp() == 0) {
58 (*_file) << header << std::endl;
59 }
60 _is_open = true;
61 }
62 } catch (const std::exception& e) {
63 _is_open = false;
64 }
65}
66
68 if (_file && _file->is_open()) {
69 _file->close();
70 }
71 pthread_mutex_destroy(&_mutex);
72}
73
74inline void CSVLogger::log(const std::string& csv_line) {
75 if (!_is_open || !_file) return;
76
77 pthread_mutex_lock(&_mutex);
78 (*_file) << csv_line << std::endl;
79 _file->flush();
80 pthread_mutex_unlock(&_mutex);
81}
82
83inline void CSVLogger::flush() {
84 if (!_is_open || !_file) return;
85
86 pthread_mutex_lock(&_mutex);
87 _file->flush();
88 pthread_mutex_unlock(&_mutex);
89}
90
91inline bool CSVLogger::is_open() const {
92 return _is_open;
93}
94
95inline std::string CSVLogger::create_vehicle_log_dir(unsigned int vehicle_id) {
96 std::string base_dir = "tests/logs/vehicle_" + std::to_string(vehicle_id);
97
98 if (create_directory(base_dir)) {
99 return base_dir;
100 }
101
102 // Fallback to tests/logs
103 if (create_directory("tests/logs")) {
104 return "tests/logs";
105 }
106
107 return "."; // Last resort - current directory
108}
109
110inline bool CSVLogger::create_directory(const std::string& path) {
111 // Create directory recursively
112 std::string current_path;
113 size_t pos = 0;
114
115 while (pos < path.length()) {
116 size_t next_pos = path.find('/', pos);
117 if (next_pos == std::string::npos) {
118 next_pos = path.length();
119 }
120
121 current_path += path.substr(pos, next_pos - pos);
122
123 if (!current_path.empty()) {
124 struct stat st;
125 if (stat(current_path.c_str(), &st) != 0) {
126 if (mkdir(current_path.c_str(), 0755) != 0) {
127 return false;
128 }
129 }
130 }
131
132 if (next_pos < path.length()) {
133 current_path += "/";
134 }
135 pos = next_pos + 1;
136 }
137
138 return true;
139}
140
141inline std::string CSVLogger::get_directory_from_path(const std::string& filepath) {
142 size_t last_slash = filepath.find_last_of('/');
143 if (last_slash != std::string::npos) {
144 return filepath.substr(0, last_slash);
145 }
146 return "";
147}
148
149inline std::string CSVLogger::get_timestamp() {
150 auto now = std::chrono::system_clock::now();
151 auto time_t = std::chrono::system_clock::to_time_t(now);
152 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
153 now.time_since_epoch()) % 1000;
154
155 std::ostringstream oss;
156 oss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S");
157 oss << "." << std::setfill('0') << std::setw(3) << ms.count();
158 return oss.str();
159}
160
161#endif // CSV_LOGGER_H
Definition csv_logger.h:19
void log(const std::string &csv_line)
Definition csv_logger.h:74
static std::string create_vehicle_log_dir(unsigned int vehicle_id)
Definition csv_logger.h:95
CSVLogger(const std::string &filepath, const std::string &header)
Definition csv_logger.h:42
void flush()
Definition csv_logger.h:83
bool is_open() const
Definition csv_logger.h:91
~CSVLogger()
Definition csv_logger.h:67
Select_Debug<(Traits< T >::debugged &&Traits< Debug >::error)> db(Debug_Error l)
Definition debug.h:166
Header * header()
Definition protocol.h:3