22 #define _CRT_SECURE_NO_WARNINGS
23 #define SEPARATOR ('\\')
25 #define SEPARATOR ('/')
35 static size_t get_next_file_suffix(
const std::string& path) {
45 static const std::string make_path(
const std::string& original_path) {
46 std::string massaged_path{ original_path };
47 if (massaged_path.empty()) {
51 if (massaged_path[massaged_path.size() - 1] ==
SEPARATOR) {
52 massaged_path = massaged_path.substr(0, massaged_path.size() - 1);
68 void ologger::make_logger(
const std::string& path,
const std::string& file_prefix,
const std::string& file_suffix) {
70 size_t next_id = get_next_file_suffix(path);
71 log_stream_.open(path +
SEPARATOR + file_prefix + std::to_string(next_id) +
"." + file_suffix,
std::ofstream::out | std::ofstream::app);
73 if (!log_stream_.good()) {
74 throw std::domain_error(
"ologger error: unable to open log file: " + path +
SEPARATOR + file_prefix + std::to_string(next_id) +
"." + file_suffix);
79 const std::string& file_prefix,
80 const std::string& file_suffix,
85 path_(make_path(path)),
86 file_prefix_(file_prefix),
87 file_suffix_(file_suffix),
88 max_file_size_(max_file_size),
89 max_files_(max_files),
91 debug(*this), info(*this), error(*this) {
93 make_logger(path_, file_prefix_, file_suffix);
96 size_t ologger::changeover_if_required() {
100 const std::streampos pos = log_stream_.tellp();
102 if (
static_cast<size_t>(pos) > max_file_size_) {
103 next_id = get_next_file_suffix(path_);
104 next_id = (next_id + 1) % max_files_;
116 const std::string next_file{ path_ +
SEPARATOR + file_prefix_ + std::to_string(next_id) +
"." + file_suffix_ };
118 std::remove(next_file.c_str());
130 const auto now = std::chrono::system_clock::now();
131 const std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
133 char timestamp[50]{};
134 std::strftime(timestamp,
sizeof(timestamp),
"%Y-%m-%d,%H:%M:%S", std::localtime(&now_time_t));
136 const int millis = std::chrono::time_point_cast<std::chrono::milliseconds>(now).time_since_epoch().count() % 100;
137 snprintf(timestamp + strlen(timestamp),
sizeof(timestamp) - strlen(timestamp),
".%03d,", millis);
141 void ologger::prefix_message() {
146 ologger::ologger::Debug::Debug(
ologger& parent)
147 : parent_(parent), start_of_line_(true)
153 parent_.log_stream_ << endl;
156 parent_.changeover_if_required();
157 start_of_line_ =
true;
161 ologger::ologger::Info::Info(
ologger& parent)
162 : parent_(parent), start_of_line_(true)
168 parent_.log_stream_ << endl;
171 parent_.changeover_if_required();
172 start_of_line_ =
true;
176 ologger::ologger::Error::Error(
ologger& parent)
177 : parent_(parent), start_of_line_(true)
183 parent_.log_stream_ << endl;
186 parent_.changeover_if_required();
187 start_of_line_ =
true;
Debug & operator<<(const T &data)
Error & operator<<(const T &data)
Info & operator<<(const T &data)
std::ostream &(std::ostream &) endl_type
ologger(const std::string &path, const std::string &file_prefix, const std::string &file_suffix, size_t max_file_size, size_t max_files, log_level level=log_level::LOG_NONE)
std::string get_time_stamp()