11 #include "errors/fatal.h"
12 #include "string/format.h"
13 #include "threads/thread.h"
14 #include "threads/wait_queue.h"
15 #include "time/timezone.h"
16 #include "utility/countof.h"
17 #include "utility/resource.h"
18 #include "utility/validate_aligned_storage.h"
20 #include "minizip/zip.h"
21 #if defined(_WIN32) || defined(_WIN64)
22 #include "minizip/iowin32.h"
32 class RollingFileAppender::Impl
35 static const std::string ARCHIVE_EXTENSION;
37 Impl(
RollingFileAppender& appender,
const CppCommon::Path& path,
bool archive,
bool truncate,
bool auto_flush,
bool auto_start)
38 : _appender(appender), _path(path), _archive(archive), _truncate(truncate), _auto_flush(auto_flush)
52 virtual bool IsStarted() const noexcept {
return _started; }
81 virtual void Flush() = 0;
85 CppCommon::Path _path;
90 std::atomic<bool> _started{
false};
91 CppCommon::Timestamp _retry{0};
92 CppCommon::File _file;
100 if (_file.IsFileWriteOpened())
112 catch (
const CppCommon::FileSystemException&) {
return false; }
115 std::thread _archive_thread;
116 CppCommon::WaitQueue<CppCommon::Path> _archive_queue;
118 virtual void ArchiveQueue(
const CppCommon::Path& path)
120 _archive_queue.Enqueue(path);
123 virtual void ArchiveFile(
const CppCommon::Path& path,
const CppCommon::Path& filename)
125 CppCommon::File file(path);
129 #if defined(_WIN32) || defined(_WIN64)
130 zlib_filefunc64_def ffunc;
131 fill_win32_filefunc64W(&ffunc);
132 zf = zipOpen2_64((file +
".zip").wstring().c_str(), APPEND_STATUS_CREATE,
nullptr, &ffunc);
134 zf = zipOpen64((file +
".zip").
string().c_str(), APPEND_STATUS_CREATE);
137 throwex CppCommon::FileSystemException(
"Cannot create a new zip archive!").Attach(file);
140 auto zip = CppCommon::resource(zf, [](zipFile handle) { zipClose(handle,
nullptr); });
143 int result = zipOpenNewFileInZip64(zf, filename.empty() ? file.filename().string().c_str() : filename.string().c_str(),
nullptr,
nullptr, 0,
nullptr, 0,
nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION, 1);
144 if (result != ZIP_OK)
145 throwex CppCommon::FileSystemException(
"Cannot open a new file in zip archive!").Attach(file);
148 auto zip_file = CppCommon::resource(zf, [](zipFile handle) { zipCloseFileInZip(handle); });
150 CppCommon::File source(file);
151 uint8_t buffer[16384];
155 source.Open(
true,
false);
160 size = source.Read(buffer, CppCommon::countof(buffer));
163 result = zipWriteInFileInZip(zf, buffer, (
unsigned)size);
164 if (result != ZIP_OK)
165 throwex CppCommon::FileSystemException(
"Cannot write into the zip file!").Attach(file);
173 result = zipCloseFileInZip(zf);
174 if (result != ZIP_OK)
175 throwex CppCommon::FileSystemException(
"Cannot close a file in zip archive!").Attach(file);
179 result = zipClose(zf,
nullptr);
180 if (result != ZIP_OK)
181 throwex CppCommon::FileSystemException(
"Cannot close a zip archive!").Attach(file);
185 CppCommon::File::Remove(source);
188 void ArchivationStart()
191 _archive_thread = CppCommon::Thread::Start([
this]() { ArchivationThread(); });
194 void ArchivationStop()
197 _archive_queue.Close();
198 _archive_thread.join();
201 void ArchivationThread()
204 _appender.onArchiveThreadInitialize();
208 CppCommon::Path path;
209 while (_archive_queue.Dequeue(path))
210 ArchiveFile(path,
"");
212 catch (
const std::exception& ex)
218 fatality(
"Archivation thread terminated!");
222 _appender.onArchiveThreadCleanup();
226 const std::string RollingFileAppender::Impl::ARCHIVE_EXTENSION =
"zip";
228 class TimePolicyImpl :
public RollingFileAppender::Impl
230 enum class PlaceholderType
257 PlaceholderType type;
260 explicit Placeholder(PlaceholderType t) : type(t) {}
261 Placeholder(PlaceholderType t,
const std::string& v) : type(t), value(v) {}
265 TimePolicyImpl(RollingFileAppender& appender,
const CppCommon::Path& path,
TimeRollingPolicy policy,
const std::string& pattern,
bool archive,
bool truncate,
bool auto_flush,
bool auto_start)
266 : RollingFileAppender::Impl(appender, path, archive, truncate, auto_flush, auto_start),
267 _policy(policy), _pattern(pattern)
269 std::string placeholder;
270 std::string subpattern;
273 bool read_placeholder =
false;
274 for (
char ch : pattern)
279 if (read_placeholder)
280 AppendPattern(placeholder);
282 AppendPattern(subpattern);
285 read_placeholder =
true;
290 if (read_placeholder)
292 AppendPlaceholder(placeholder);
293 read_placeholder =
false;
301 if (read_placeholder)
309 if (read_placeholder)
310 AppendPattern(placeholder);
312 AppendPattern(subpattern);
318 _rolldelay = 1000000000ull;
321 _rolldelay = 60 * 1000000000ull;
324 _rolldelay = 60 * 60 * 1000000000ull;
327 _rolldelay = 24 * 60 * 60 * 1000000000ull;
332 virtual ~TimePolicyImpl()
344 void AppendRecord(Record& record)
override
347 if (record.raw.empty())
350 size_t size = record.raw.size() - 1;
352 if (PrepareFile(record.timestamp))
357 _file.Write(record.raw.data(), size);
364 catch (
const CppCommon::FileSystemException&)
371 catch (
const CppCommon::FileSystemException&) {}
376 void Flush()
override
378 if (FlushFile(CppCommon::Timestamp::utc()))
385 catch (
const CppCommon::FileSystemException&)
392 catch (
const CppCommon::FileSystemException&) {}
399 std::string _pattern;
400 std::vector<Placeholder> _placeholders;
401 CppCommon::Timestamp _rollstamp{0};
402 CppCommon::Timespan _rolldelay{0};
405 bool FlushFile(uint64_t timestamp)
410 if (_file.IsFileWriteOpened())
413 if (timestamp < (_rollstamp + _rolldelay))
425 catch (
const CppCommon::FileSystemException&)
428 _retry = CppCommon::Timestamp::utc();
434 bool PrepareFile(uint64_t timestamp)
439 if (FlushFile(timestamp))
443 if ((CppCommon::Timestamp::utc() - _retry).milliseconds() < 100)
446 uint64_t rollstamp = timestamp;
452 rollstamp = (rollstamp / 1000000000ull) * 1000000000ull;
455 rollstamp = (rollstamp / (60 * 1000000000ull)) * (60 * 1000000000ull);
458 rollstamp = (rollstamp / (60 * 60 * 1000000000ull)) * (60 * 60 * 1000000000ull);
461 rollstamp = (rollstamp / (24 * 60 * 60 * 1000000000ull)) * (24 * 60 * 60 * 1000000000ull);
469 timestamp = rollstamp;
472 if (_file.IsFileReadOpened())
476 _file = PrepareFilePath(CppCommon::Timestamp(timestamp));
479 CppCommon::Directory::CreateTree(_file.parent());
482 _file.OpenOrCreate(
false,
true, _truncate);
491 _rollstamp = rollstamp;
495 catch (
const CppCommon::FileSystemException&)
498 _retry = CppCommon::Timestamp::utc();
503 CppCommon::Path PrepareFilePath(
const CppCommon::Timestamp& timestamp)
505 thread_local
bool cache_initizlied =
false;
506 thread_local
bool cache_time_required =
false;
507 thread_local
bool cache_utc_required =
false;
508 thread_local
bool cache_local_required =
false;
509 thread_local
bool cache_timezone_required =
false;
510 thread_local uint64_t cache_seconds = 0;
511 thread_local
char cache_utc_datetime_str[] =
"1970-01-01T010101Z";
512 thread_local
char cache_utc_date_str[] =
"1970-01-01";
513 thread_local
char cache_utc_time_str[] =
"010101Z";
514 thread_local
char cache_utc_year_str[] =
"1970";
515 thread_local
char cache_utc_month_str[] =
"01";
516 thread_local
char cache_utc_day_str[] =
"01";
517 thread_local
char cache_utc_hour_str[] =
"00";
518 thread_local
char cache_utc_minute_str[] =
"00";
519 thread_local
char cache_utc_second_str[] =
"00";
520 thread_local
char cache_utc_timezone_str[] =
"Z";
521 thread_local
char cache_local_datetime_str[] =
"1970-01-01T010101+0000";
522 thread_local
char cache_local_date_str[] =
"1970-01-01";
523 thread_local
char cache_local_time_str[] =
"010101+0000";
524 thread_local
char cache_local_year_str[] =
"1970";
525 thread_local
char cache_local_month_str[] =
"01";
526 thread_local
char cache_local_day_str[] =
"01";
527 thread_local
char cache_local_hour_str[] =
"00";
528 thread_local
char cache_local_minute_str[] =
"00";
529 thread_local
char cache_local_second_str[] =
"00";
530 thread_local
char cache_local_timezone_str[] =
"+0000";
531 bool cache_update_datetime =
false;
534 if (cache_time_required || !cache_initizlied)
536 uint64_t seconds = timestamp.seconds();
538 if (seconds != cache_seconds)
540 cache_seconds = seconds;
543 if (cache_timezone_required || !cache_initizlied)
545 CppCommon::Timezone local;
546 ConvertTimezone(cache_local_timezone_str, local.total().minutes(), 5);
547 cache_update_datetime =
true;
551 if (cache_utc_required || !cache_initizlied)
553 CppCommon::UtcTime utc(timestamp);
554 ConvertNumber(cache_utc_year_str, utc.year(), 4);
555 ConvertNumber(cache_utc_month_str, utc.month(), 2);
556 ConvertNumber(cache_utc_day_str, utc.day(), 2);
557 ConvertNumber(cache_utc_hour_str, utc.hour(), 2);
558 ConvertNumber(cache_utc_minute_str, utc.minute(), 2);
559 ConvertNumber(cache_utc_second_str, utc.second(), 2);
560 cache_update_datetime =
true;
564 if (cache_local_required || !cache_initizlied)
566 CppCommon::LocalTime local(timestamp);
567 ConvertNumber(cache_local_year_str, local.year(), 4);
568 ConvertNumber(cache_local_month_str, local.month(), 2);
569 ConvertNumber(cache_local_day_str, local.day(), 2);
570 ConvertNumber(cache_local_hour_str, local.hour(), 2);
571 ConvertNumber(cache_local_minute_str, local.minute(), 2);
572 ConvertNumber(cache_local_second_str, local.second(), 2);
573 cache_update_datetime =
true;
579 if (cache_update_datetime)
581 char* buffer = cache_utc_date_str;
582 std::memcpy(buffer, cache_utc_year_str, CppCommon::countof(cache_utc_year_str) - 1);
583 buffer += CppCommon::countof(cache_utc_year_str) - 1;
585 std::memcpy(buffer, cache_utc_month_str, CppCommon::countof(cache_utc_month_str) - 1);
586 buffer += CppCommon::countof(cache_utc_month_str) - 1;
588 std::memcpy(buffer, cache_utc_day_str, CppCommon::countof(cache_utc_day_str) - 1);
589 buffer += CppCommon::countof(cache_utc_day_str) - 1;
591 buffer = cache_utc_time_str;
592 std::memcpy(buffer, cache_utc_hour_str, CppCommon::countof(cache_utc_hour_str) - 1);
593 buffer += CppCommon::countof(cache_utc_hour_str) - 1;
594 std::memcpy(buffer, cache_utc_minute_str, CppCommon::countof(cache_utc_minute_str) - 1);
595 buffer += CppCommon::countof(cache_utc_minute_str) - 1;
596 std::memcpy(buffer, cache_utc_second_str, CppCommon::countof(cache_utc_second_str) - 1);
597 buffer += CppCommon::countof(cache_utc_second_str) - 1;
598 std::memcpy(buffer, cache_utc_timezone_str, CppCommon::countof(cache_utc_timezone_str) - 1);
599 buffer += CppCommon::countof(cache_utc_timezone_str) - 1;
601 buffer = cache_utc_datetime_str;
602 std::memcpy(buffer, cache_utc_date_str, CppCommon::countof(cache_utc_date_str) - 1);
603 buffer += CppCommon::countof(cache_utc_date_str) - 1;
605 std::memcpy(buffer, cache_utc_time_str, CppCommon::countof(cache_utc_time_str) - 1);
606 buffer += CppCommon::countof(cache_utc_time_str) - 1;
608 buffer = cache_local_date_str;
609 std::memcpy(buffer, cache_local_year_str, CppCommon::countof(cache_local_year_str) - 1);
610 buffer += CppCommon::countof(cache_local_year_str) - 1;
612 std::memcpy(buffer, cache_local_month_str, CppCommon::countof(cache_local_month_str) - 1);
613 buffer += CppCommon::countof(cache_local_month_str) - 1;
615 std::memcpy(buffer, cache_local_day_str, CppCommon::countof(cache_local_day_str) - 1);
616 buffer += CppCommon::countof(cache_local_day_str) - 1;
618 buffer = cache_local_time_str;
619 std::memcpy(buffer, cache_local_hour_str, CppCommon::countof(cache_local_hour_str) - 1);
620 buffer += CppCommon::countof(cache_local_hour_str) - 1;
621 std::memcpy(buffer, cache_local_minute_str, CppCommon::countof(cache_local_minute_str) - 1);
622 buffer += CppCommon::countof(cache_local_minute_str) - 1;
623 std::memcpy(buffer, cache_local_second_str, CppCommon::countof(cache_local_second_str) - 1);
624 buffer += CppCommon::countof(cache_local_second_str) - 1;
625 std::memcpy(buffer, cache_local_timezone_str, CppCommon::countof(cache_local_timezone_str) - 1);
626 buffer += CppCommon::countof(cache_local_timezone_str) - 1;
628 buffer = cache_local_datetime_str;
629 std::memcpy(buffer, cache_local_date_str, CppCommon::countof(cache_local_date_str) - 1);
630 buffer += CppCommon::countof(cache_local_date_str) - 1;
632 std::memcpy(buffer, cache_local_time_str, CppCommon::countof(cache_local_time_str) - 1);
633 buffer += CppCommon::countof(cache_local_time_str) - 1;
635 cache_update_datetime =
false;
638 cache_initizlied =
true;
640 std::string filename;
643 for (
const auto& placeholder : _placeholders)
645 switch (placeholder.type)
647 case PlaceholderType::String:
650 filename.insert(filename.end(), placeholder.value.begin(), placeholder.value.end());
653 case PlaceholderType::UtcDateTime:
656 filename.insert(filename.end(), std::begin(cache_utc_datetime_str), std::end(cache_utc_datetime_str) - 1);
658 cache_time_required =
true;
659 cache_utc_required =
true;
662 case PlaceholderType::UtcDate:
665 filename.insert(filename.end(), std::begin(cache_utc_date_str), std::end(cache_utc_date_str) - 1);
667 cache_time_required =
true;
668 cache_utc_required =
true;
671 case PlaceholderType::UtcTime:
674 filename.insert(filename.end(), std::begin(cache_utc_time_str), std::end(cache_utc_time_str) - 1);
676 cache_time_required =
true;
677 cache_utc_required =
true;
680 case PlaceholderType::UtcYear:
683 filename.insert(filename.end(), std::begin(cache_utc_year_str), std::end(cache_utc_year_str) - 1);
685 cache_time_required =
true;
686 cache_utc_required =
true;
689 case PlaceholderType::UtcMonth:
692 filename.insert(filename.end(), std::begin(cache_utc_month_str), std::end(cache_utc_month_str) - 1);
694 cache_time_required =
true;
695 cache_utc_required =
true;
698 case PlaceholderType::UtcDay:
701 filename.insert(filename.end(), std::begin(cache_utc_day_str), std::end(cache_utc_day_str) - 1);
703 cache_time_required =
true;
704 cache_utc_required =
true;
707 case PlaceholderType::UtcHour:
710 filename.insert(filename.end(), std::begin(cache_utc_hour_str), std::end(cache_utc_hour_str) - 1);
712 cache_time_required =
true;
713 cache_utc_required =
true;
716 case PlaceholderType::UtcMinute:
719 filename.insert(filename.end(), std::begin(cache_utc_minute_str), std::end(cache_utc_minute_str) - 1);
721 cache_time_required =
true;
722 cache_utc_required =
true;
725 case PlaceholderType::UtcSecond:
728 filename.insert(filename.end(), std::begin(cache_utc_second_str), std::end(cache_utc_second_str) - 1);
730 cache_time_required =
true;
731 cache_utc_required =
true;
734 case PlaceholderType::UtcTimezone:
737 filename.insert(filename.end(), std::begin(cache_utc_timezone_str), std::end(cache_utc_timezone_str) - 1);
740 case PlaceholderType::LocalDateTime:
743 filename.insert(filename.end(), std::begin(cache_local_datetime_str), std::end(cache_local_datetime_str) - 1);
745 cache_time_required =
true;
746 cache_local_required =
true;
747 cache_timezone_required =
true;
750 case PlaceholderType::LocalDate:
753 filename.insert(filename.end(), std::begin(cache_local_date_str), std::end(cache_local_date_str) - 1);
755 cache_time_required =
true;
756 cache_local_required =
true;
759 case PlaceholderType::LocalTime:
762 filename.insert(filename.end(), std::begin(cache_local_time_str), std::end(cache_local_time_str) - 1);
764 cache_time_required =
true;
765 cache_local_required =
true;
766 cache_timezone_required =
true;
769 case PlaceholderType::LocalYear:
772 filename.insert(filename.end(), std::begin(cache_local_year_str), std::end(cache_local_year_str) - 1);
774 cache_time_required =
true;
775 cache_local_required =
true;
778 case PlaceholderType::LocalMonth:
781 filename.insert(filename.end(), std::begin(cache_local_month_str), std::end(cache_local_month_str) - 1);
783 cache_time_required =
true;
784 cache_local_required =
true;
787 case PlaceholderType::LocalDay:
790 filename.insert(filename.end(), std::begin(cache_local_day_str), std::end(cache_local_day_str) - 1);
792 cache_time_required =
true;
793 cache_local_required =
true;
796 case PlaceholderType::LocalHour:
799 filename.insert(filename.end(), std::begin(cache_local_hour_str), std::end(cache_local_hour_str) - 1);
801 cache_time_required =
true;
802 cache_local_required =
true;
805 case PlaceholderType::LocalMinute:
808 filename.insert(filename.end(), std::begin(cache_local_minute_str), std::end(cache_local_minute_str) - 1);
810 cache_time_required =
true;
811 cache_local_required =
true;
814 case PlaceholderType::LocalSecond:
817 filename.insert(filename.end(), std::begin(cache_local_second_str), std::end(cache_local_second_str) - 1);
819 cache_time_required =
true;
820 cache_local_required =
true;
823 case PlaceholderType::LocalTimezone:
826 filename.insert(filename.end(), std::begin(cache_local_timezone_str), std::end(cache_local_timezone_str) - 1);
828 cache_time_required =
true;
829 cache_timezone_required =
true;
835 return CppCommon::Path(_path / filename);
838 void AppendPattern(
const std::string& pattern)
845 if (_placeholders.empty() || (_placeholders[_placeholders.size() - 1].type != PlaceholderType::String))
846 _placeholders.emplace_back(PlaceholderType::String, pattern);
848 _placeholders[_placeholders.size() - 1].value += pattern;
851 void AppendPlaceholder(
const std::string& placeholder)
854 if (placeholder.empty())
857 if (placeholder ==
"UtcDateTime")
858 _placeholders.emplace_back(PlaceholderType::UtcDateTime);
859 else if (placeholder ==
"UtcDate")
860 _placeholders.emplace_back(PlaceholderType::UtcDate);
861 else if (placeholder ==
"UtcTime")
862 _placeholders.emplace_back(PlaceholderType::UtcTime);
863 else if (placeholder ==
"UtcYear")
864 _placeholders.emplace_back(PlaceholderType::UtcYear);
865 else if (placeholder ==
"UtcMonth")
866 _placeholders.emplace_back(PlaceholderType::UtcMonth);
867 else if (placeholder ==
"UtcDay")
868 _placeholders.emplace_back(PlaceholderType::UtcDay);
869 else if (placeholder ==
"UtcHour")
870 _placeholders.emplace_back(PlaceholderType::UtcHour);
871 else if (placeholder ==
"UtcMinute")
872 _placeholders.emplace_back(PlaceholderType::UtcMinute);
873 else if (placeholder ==
"UtcSecond")
874 _placeholders.emplace_back(PlaceholderType::UtcSecond);
875 else if (placeholder ==
"UtcTimezone")
876 _placeholders.emplace_back(PlaceholderType::UtcTimezone);
877 else if (placeholder ==
"LocalDateTime")
878 _placeholders.emplace_back(PlaceholderType::LocalDateTime);
879 else if (placeholder ==
"LocalDate")
880 _placeholders.emplace_back(PlaceholderType::LocalDate);
881 else if (placeholder ==
"LocalTime")
882 _placeholders.emplace_back(PlaceholderType::LocalTime);
883 else if (placeholder ==
"LocalYear")
884 _placeholders.emplace_back(PlaceholderType::LocalYear);
885 else if (placeholder ==
"LocalMonth")
886 _placeholders.emplace_back(PlaceholderType::LocalMonth);
887 else if (placeholder ==
"LocalDay")
888 _placeholders.emplace_back(PlaceholderType::LocalDay);
889 else if (placeholder ==
"LocalHour")
890 _placeholders.emplace_back(PlaceholderType::LocalHour);
891 else if (placeholder ==
"LocalMinute")
892 _placeholders.emplace_back(PlaceholderType::LocalMinute);
893 else if (placeholder ==
"LocalSecond")
894 _placeholders.emplace_back(PlaceholderType::LocalSecond);
895 else if (placeholder ==
"LocalTimezone")
896 _placeholders.emplace_back(PlaceholderType::LocalTimezone);
898 AppendPattern(
"{" + placeholder +
"}");
901 static void ConvertNumber(
char* output,
int number,
size_t size)
904 std::memset(output,
'0', size);
907 size_t index = size - 1;
910 while ((number >= 10) && (index != 0))
914 output[index--] =
'0' + (char)b;
919 output[index] =
'0' + (char)number;
922 static void ConvertTimezone(
char* output, int64_t offset,
size_t size)
925 std::memset(output,
'0', size);
928 size_t index = size - 1;
931 int64_t minutes = offset % 60;
934 output[index--] =
'0' + (char)minutes;
939 output[index--] =
'0' + (char)(minutes % 10);
941 output[index--] =
'0' + (char)minutes;
945 int64_t hours = offset / 60;
948 output[index] =
'0' + (char)hours;
952 output[index--] =
'0' + (char)(hours % 10);
954 output[index] =
'0' + (char)hours;
958 output[0] = (offset < 0) ?
'-' :
'+';
962 class SizePolicyImpl :
public RollingFileAppender::Impl
965 SizePolicyImpl(RollingFileAppender& appender,
const CppCommon::Path& path,
const std::string& filename,
const std::string& extension,
size_t size,
size_t backups,
bool archive,
bool truncate,
bool auto_flush,
bool auto_start)
966 : RollingFileAppender::Impl(appender, path, archive, truncate, auto_flush, auto_start),
967 _filename(filename), _extension(extension), _size(size), _backups(backups)
969 assert((size > 0) &&
"Size limit should be greater than zero!");
971 throwex CppCommon::ArgumentException(
"Size limit should be greater than zero!");
973 assert((backups > 0) &&
"Backups count should be greater than zero!");
975 throwex CppCommon::ArgumentException(
"Backups count should be greater than zero!");
978 virtual ~SizePolicyImpl()
985 void AppendRecord(Record& record)
override
988 if (record.raw.empty())
991 size_t size = record.raw.size() - 1;
993 if (PrepareFile(size))
998 _file.Write(record.raw.data(), size);
1005 catch (
const CppCommon::FileSystemException&)
1012 catch (
const CppCommon::FileSystemException&) {}
1017 void Flush()
override
1026 catch (
const CppCommon::FileSystemException&)
1033 catch (
const CppCommon::FileSystemException&) {}
1039 std::string _filename;
1040 std::string _extension;
1044 bool FlushFile(
size_t size)
1049 if (_file.IsFileWriteOpened())
1052 if ((_written + size) <= _size)
1061 ArchiveQueue(_file);
1066 catch (
const CppCommon::FileSystemException&)
1069 _retry = CppCommon::Timestamp::utc();
1075 bool PrepareFile(
size_t size)
1080 if (FlushFile(size))
1084 if ((CppCommon::Timestamp::utc() - _retry).milliseconds() < 100)
1088 if (_file.IsFileReadOpened())
1092 _file = PrepareFilePath();
1095 CppCommon::Directory::CreateTree(_file.parent());
1098 _file.OpenOrCreate(
false,
true, _truncate);
1108 catch (
const CppCommon::FileSystemException&)
1111 _retry = CppCommon::Timestamp::utc();
1116 void ArchiveQueue(
const CppCommon::Path& path)
override
1119 CppCommon::File unique = CppCommon::File(path).ReplaceFilename(CppCommon::File::unique());
1120 CppCommon::File::Rename(path, unique);
1122 _archive_queue.Enqueue(unique);
1125 void ArchiveFile(
const CppCommon::Path& path,
const CppCommon::Path& filename)
override
1128 CppCommon::File backup = RollBackup(path);
1131 Impl::ArchiveFile(backup, PrepareFilePath());
1134 CppCommon::File RollBackup(
const CppCommon::Path& path)
1137 CppCommon::File backup = PrepareFilePath(_backups);
1138 if (backup.IsFileExists())
1139 CppCommon::File::Remove(backup);
1140 backup +=
"." + ARCHIVE_EXTENSION;
1141 if (backup.IsFileExists())
1142 CppCommon::File::Remove(backup);
1145 for (
size_t i = _backups - 1; i > 0; --i)
1147 CppCommon::File src = PrepareFilePath(i);
1148 CppCommon::File dst = PrepareFilePath(i + 1);
1149 if (src.IsFileExists())
1150 CppCommon::File::Rename(src, dst);
1151 src +=
"." + ARCHIVE_EXTENSION;
1152 dst +=
"." + ARCHIVE_EXTENSION;
1153 if (src.IsFileExists())
1154 CppCommon::File::Rename(src, dst);
1158 backup = PrepareFilePath(1);
1159 CppCommon::File::Rename(path, backup);
1163 CppCommon::Path PrepareFilePath()
1165 return CppCommon::Path(_path / CppCommon::format(
"{}.{}", _filename, _extension));
1168 CppCommon::Path PrepareFilePath(
size_t backup)
1170 return CppCommon::Path(_path / CppCommon::format(
"{}.{}.{}", _filename, backup, _extension));
1179 [[maybe_unused]] CppCommon::ValidateAlignedStorage<
sizeof(Impl),
alignof(Impl), StorageSize, StorageAlign> _;
1180 static_assert((StorageSize >=
sizeof(Impl)),
"RollingFileAppender::StorageSize must be increased!");
1181 static_assert(((StorageAlign %
alignof(Impl)) == 0),
"RollingFileAppender::StorageAlign must be adjusted!");
1184 new(&_storage)
TimePolicyImpl(*
this, path, policy, pattern, archive, truncate, auto_flush, auto_start);
1187 RollingFileAppender::RollingFileAppender(
const CppCommon::Path& path,
const std::string& filename,
const std::string& extension,
size_t size,
size_t backups,
bool archive,
bool truncate,
bool auto_flush,
bool auto_start)
1190 [[maybe_unused]] CppCommon::ValidateAlignedStorage<
sizeof(Impl),
alignof(Impl), StorageSize, StorageAlign> _;
1191 static_assert((StorageSize >=
sizeof(Impl)),
"RollingFileAppender::StorageSize must be increased!");
1192 static_assert(((StorageAlign %
alignof(Impl)) == 0),
"RollingFileAppender::StorageAlign must be adjusted!");
1195 new(&_storage)
SizePolicyImpl(*
this, path, filename, extension, size, backups, archive, truncate, auto_flush, auto_start);
1201 reinterpret_cast<Impl*
>(&_storage)->~Impl();
friend class SizePolicyImpl
void AppendRecord(Record &record) override
Append the given logging record.
bool IsStarted() const noexcept override
Is the logging element started?
bool Start() override
Start the logging element.
friend class TimePolicyImpl
bool Stop() override
Stop the logging element.
virtual ~RollingFileAppender()
void Flush() override
Flush the logging appender.
RollingFileAppender(const CppCommon::Path &path, TimeRollingPolicy policy=TimeRollingPolicy::DAY, const std::string &pattern="{UtcDateTime}.log", bool archive=false, bool truncate=false, bool auto_flush=false, bool auto_start=true)
Initialize the rolling file appender with a time-based policy.
C++ Logging project definitions.
TimeRollingPolicy
Time rolling policy.
@ SECOND
Second rolling policy.
@ MINUTE
Minute rolling policy.
@ HOUR
Hour rolling policy.
Rolling file appender definition.