bux API Reference 1.11.0
Static library of whatever are seen required in general purpose but not directly supported from Modern C++. Or whatever reusable originated from my side projects.
Loading...
Searching...
No Matches
FileLog.cpp
Go to the documentation of this file.
1#include "FileLog.h"
2#include <format> // std::vformat()
3
4namespace fs = std::filesystem;
5
6namespace bux {
7
8//
9// Class Implementation
10//
12{
13 configPath("{:%Y%m%d}.log");
14}
15
22{
23 if (_pathFmt.empty())
24 RUNTIME_ERROR("Null path format");
25
26 m_PathFmts.clear();
27 m_PathFmts.emplace_back(fs::absolute(_pathFmt).string());
28 m_FileSizeLimit =
29 m_CurPathFmt = 0;
30 return *this;
31}
32
39{
40 m_AutoMkDir = yes;
41 return *this;
42}
43
48{
49 m_OpenMode = std::ios_base::out;
50 if (enabled)
51 m_OpenMode |= std::ios_base::binary;
52
53 m_CurrPath.clear(); // trigger reopen
54 return *this;
55}
56
58{
59 const auto t = time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now());
60 const auto get_new_path = [t,this](auto indFmt) {
61 std::string_view pathFmt = m_PathFmts.at(indFmt);
62 if (m_tz)
63 {
64#if LOCALZONE_IS_TIMEZONE
65 auto ltm = m_tz->to_local(t);
66#else
67 auto sys_t = std::chrono::system_clock::to_time_t(t);
68 std::chrono::local_time<std::chrono::seconds> ltm(t.time_since_epoch() + std::chrono::seconds(localtime(&sys_t)->tm_gmtoff));
69#endif
70 return std::vformat(pathFmt, make_format_args(ltm));
71 }
72 return std::vformat(pathFmt, make_format_args(t));
73 };
74 std::string nextPath;
75 if (m_OldTime == t)
76 nextPath = m_CurrPath;
77 else
78 {
79 m_OldTime = t;
80 nextPath = get_new_path(m_CurPathFmt);
81 }
82OpenNewFile:
83 if (nextPath.empty())
84 return nullptr;
85
86 if (m_CurrPath != nextPath)
87 // Different paths -- Repoen it
88 {
89 if (m_CurrPath.empty())
90 // First time
91 {
92 if (m_FileSizeLimit)
93 while (m_CurPathFmt + 1 < m_PathFmts.size() &&
94 fs::is_regular_file(nextPath) &&
95 fs::file_size(nextPath) >= m_FileSizeLimit)
96 nextPath = get_new_path(++m_CurPathFmt);
97 }
98 else
99 // Find the lowest fallback
100 while (m_CurPathFmt)
101 {
102 auto s2 = get_new_path(m_CurPathFmt - 1);
103 if (fs::exists(s2))
104 break;
105
106 --m_CurPathFmt;
107 nextPath = std::move(s2);
108 }
109
110 // At this stage, nextPath is finalized as the new log path for sure
111 if (m_AutoMkDir)
112 (void)create_directories(fs::path(nextPath).parent_path());
113
114 m_Out.clear();
115 if (m_CurrPath.empty())
116 // First open
117 m_Out.open(nextPath, m_OpenMode|std::ios::ate|std::ios::in);
118 else
119 // Close the opened file
120 m_Out.close();
121
122 if (!m_Out.is_open())
123 // Mostly serve for the latter case
124 {
125 m_Out.clear();
126 m_Out.open(nextPath, m_OpenMode);
127 }
128 if (!m_Out.is_open())
129 RUNTIME_ERROR("{}", nextPath);
130
131 m_CurrPath = nextPath;
132 }
133 else if (
134 m_FileSizeLimit &&
135 m_CurPathFmt + 1 < m_PathFmts.size() &&
136 m_Out.tellp() >= std::streamoff(m_FileSizeLimit))
137 // Size limit is reached and we can fallback to use the next path format
138 {
139 nextPath = get_new_path(++m_CurPathFmt);
140 goto OpenNewFile;
141 }
142 return &m_Out;
143}
144
145} // namespace bux
#define RUNTIME_ERROR(fmtStr,...)
Wrap FILE(DATE)#__LINE__ FUNCTION: msg into std::runtime_error.
Definition XException.h:32
C_PathFmtLogSnap & enableAutoMkDir(bool yes=true)
Definition FileLog.cpp:33
std::ostream * snap() override
Snap the current T value.
Definition FileLog.cpp:57
C_PathFmtLogSnap(T_LocalZone tz=local_zone())
Definition FileLog.cpp:11
C_PathFmtLogSnap & setBinaryMode(bool enabled)
Definition FileLog.cpp:44
C_PathFmtLogSnap & configPath(const std::string &pathFmt)
Definition FileLog.cpp:16
THE common namespace of bux library.
Definition AtomiX.cpp:3
const std::chrono::time_zone * T_LocalZone
Definition XPlatform.h:18