qxLib
base_file_logger_stream.inl
Go to the documentation of this file.
1 /**
2 
3  @file base_file_logger_stream.inl
4  @author Khrapov
5  @date 30.07.2021
6  @copyright © Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 inline base_file_logger_stream::base_file_logger_stream(const config& streamConfig) noexcept
14  : base_logger_stream(streamConfig)
15 {
16 }
17 
19  const config& config) noexcept
20 {
21  // make sure the destination directory exists
22  std::filesystem::path logDirPath = config.svLogsDirectory;
23  if (!std::filesystem::exists(logDirPath))
24  {
25  if (!std::filesystem::create_directory(logDirPath))
26  {
27  details::get_cerr<char_type>::get() << QXT("Can't create output folder ") << logDirPath;
28  return std::filesystem::path();
29  }
30  }
31 
32  // construct the log name
33  string sLogFile = config.svLogsDirectory;
34  if (!config.svLogsDirectory.empty() && !config.svLogsDirectory.ends_with(QXT('/'))
35  && !config.svLogsDirectory.ends_with(QXT('\\')))
36  {
37  sLogFile += QXT('/');
38  }
39  sLogFile += config.svFilePrefix;
40 
41  if (config.eLogFilePolicy == log_file_policy::time_name)
42  {
43  sLogFile += QXT('_');
44  append_time_string(std::back_inserter(sLogFile), QXT('-'), QXT('-'), std::chrono::system_clock::now());
45  }
46 
47  sLogFile += config.svFileExtension;
48 
49 
50  // rotate logs
51  if ((config.eLogFilePolicy == log_file_policy::time_name
52  || config.eLogFilePolicy == log_file_policy::time_name_keep_current)
53  && config.nMaxLogFiles > 0)
54  {
55  if (config.eLogFilePolicy == log_file_policy::time_name_keep_current
56  && std::filesystem::exists(sLogFile.c_str()))
57  {
58  std::filesystem::file_time_type lastWriteTimeFileClock = std::filesystem::last_write_time(sLogFile.c_str());
59  auto lastWriteTimeSystemClock = std::chrono::clock_cast<std::chrono::system_clock>(lastWriteTimeFileClock);
60 
61  string sNewFileName = sLogFile;
62  sNewFileName.remove_suffix(config.svFileExtension);
63  sNewFileName += QXT('_');
64  append_time_string(std::back_inserter(sNewFileName), QXT('-'), QXT('-'), lastWriteTimeSystemClock);
65  sNewFileName += config.svFileExtension;
66 
67  std::filesystem::rename(sLogFile.c_str(), sNewFileName.c_str());
68  }
69 
70  std::vector<std::filesystem::directory_entry> logFiles;
71  for (const std::filesystem::directory_entry& entry :
72  std::filesystem::directory_iterator(logDirPath)
73  | std::views::filter(
74  [&config](const std::filesystem::directory_entry& entry)
75  {
76  return entry.path().extension() == config.svFileExtension;
77  }))
78  {
79  const std::wstring sFilename = entry.path().filename().wstring();
80  if (sFilename.starts_with(config.svFilePrefix))
81  logFiles.push_back(entry);
82  }
83 
84  if (logFiles.size() > config.nMaxLogFiles - 1)
85  {
86  std::ranges::sort(
87  logFiles,
88  [](const std::filesystem::directory_entry& left, const std::filesystem::directory_entry& right)
89  {
90  return std::filesystem::last_write_time(left) > std::filesystem::last_write_time(right);
91  });
92 
93  for (size_t i = config.nMaxLogFiles - 1; i < logFiles.size(); ++i)
94  std::filesystem::remove(logFiles[i]);
95  }
96  }
97 
98  return sLogFile.c_str();
99 }
100 
101 } // namespace qx
base_file_logger_stream(const config &streamConfig) noexcept
file_logger_stream object constructor
std::filesystem::path prepare_folder_and_get_log_file_path(const config &config) noexcept
Create a folder (if required) and get log file path.
Base class for logger streams.
bool remove_suffix(value_type chSymbol) noexcept
Remove string suffix if matches.
Definition: string.inl:1029
const_pointer c_str() const noexcept
Get pointer to string zero terminated.
Definition: string.inl:244
void append_time_string(out_it_t it, char_type chDateDelimiter, char_type chTimeDelimiter, std::chrono::system_clock::time_point time) noexcept
Format time string to the buffer.