@@ -84,13 +84,21 @@ Logger& Logger::get_instance()
8484
8585void Logger::start_logging (std::filesystem::path dir)
8686{
87- log_dir_ = std::move (dir);
88- if (log_dir_.empty ()) {
89- log_path_.clear ();
90- }
91- else {
92- log_path_ = log_dir_ / kLogFilename ;
87+ {
88+ std::unique_lock init_lock (perf_init_mutex_);
89+
90+ log_dir_ = std::move (dir);
91+ if (log_dir_.empty ()) {
92+ log_path_.clear ();
93+ }
94+ else {
95+ log_path_ = log_dir_ / kLogFilename ;
96+ }
97+
98+ perf_reset_locked ();
99+ perf_try_open_locked ();
93100 }
101+
94102 reinit ();
95103}
96104
@@ -132,7 +140,7 @@ static void remove_old_files(const std::filesystem::path& dir)
132140 }
133141
134142 const auto ext = path_to_utf8_string (entry.path ().extension ());
135- if (ext != " .log" && ext != " .jpg" && ext != " .png" ) {
143+ if (ext != " .log" && ext != " .jpg" && ext != " .png" && ext != " .csv " ) {
136144 continue ;
137145 }
138146
@@ -215,9 +223,15 @@ void Logger::close()
215223 internal_dbg () << " Close log" ;
216224 internal_dbg () << kSplitLine ;
217225
218- std::unique_lock trace_lock (trace_mutex_);
219- if (ofs_.is_open ()) {
220- ofs_.close ();
226+ {
227+ std::unique_lock trace_lock (trace_mutex_);
228+ if (ofs_.is_open ()) {
229+ ofs_.close ();
230+ }
231+ }
232+ {
233+ std::unique_lock init_lock (perf_init_mutex_);
234+ perf_close_locked ();
221235 }
222236}
223237
@@ -282,4 +296,72 @@ LogStream Logger::internal_dbg()
282296 return debug (" Logger" );
283297}
284298
299+ PerfLogStream Logger::perf_stream ()
300+ {
301+ std::unique_lock init_lock (perf_init_mutex_);
302+ // 注意: 此处返回的 PerfLogStream 析构时会拿 perf_mutex_ 写。
303+ // 若 perf_ofs_ 没打开(log_dir 空,或打开失败),PerfLogStream 析构静默丢弃。
304+ return PerfLogStream (perf_mutex_, perf_ofs_);
305+ }
306+
307+ void Logger::perf_reset_locked ()
308+ {
309+ // 切换 log_dir 时重置 perf 通道,随后由 start_logging() 按新目录重开
310+ perf_close_locked ();
311+ perf_initialized_ = false ;
312+ }
313+
314+ void Logger::perf_try_open_locked ()
315+ {
316+ if (perf_initialized_) {
317+ return ;
318+ }
319+ if (log_dir_.empty ()) {
320+ return ;
321+ }
322+
323+ std::error_code ec;
324+ const std::filesystem::path perf_dir = log_dir_ / kPerfTraceSubdir ;
325+ std::filesystem::create_directories (perf_dir, ec);
326+ if (ec) {
327+ return ;
328+ }
329+
330+ const auto filename = std::format (kPerfTraceFilenameFormat , format_now_for_filename ());
331+ const std::filesystem::path perf_path = perf_dir / filename;
332+
333+ {
334+ std::unique_lock perf_lock (perf_mutex_);
335+ if (perf_ofs_.is_open ()) {
336+ perf_ofs_.close ();
337+ }
338+ #ifdef _WIN32
339+ std::string str_path = perf_path.string ();
340+ FILE * fp = fopen (str_path.c_str (), " w" );
341+ if (!fp) {
342+ return ;
343+ }
344+ SetHandleInformation ((HANDLE )_get_osfhandle (_fileno (fp)), HANDLE_FLAG_INHERIT , 0 );
345+ perf_ofs_ = std::ofstream (fp);
346+ #else
347+ perf_ofs_ = std::ofstream (perf_path, std::ios::out | std::ios::trunc);
348+ #endif
349+ if (!perf_ofs_.is_open ()) {
350+ return ;
351+ }
352+ perf_ofs_ << kPerfTraceCsvHeader << ' \n ' ;
353+ }
354+
355+ perf_initialized_ = true ;
356+ }
357+
358+ void Logger::perf_close_locked ()
359+ {
360+ std::unique_lock perf_lock (perf_mutex_);
361+ if (perf_ofs_.is_open ()) {
362+ perf_ofs_.flush ();
363+ perf_ofs_.close ();
364+ }
365+ }
366+
285367MAA_LOG_NS_END
0 commit comments