file helper
This commit is contained in:
		
							parent
							
								
									8fb32dcb65
								
							
						
					
					
						commit
						b94ca27ce4
					
				| @ -88,8 +88,8 @@ | ||||
|     <ClInclude Include="..\..\include\c11log\common.h" /> | ||||
|     <ClInclude Include="..\..\include\c11log\details\blocking_queue.h" /> | ||||
|     <ClInclude Include="..\..\include\c11log\details\fast_oss.h" /> | ||||
|     <ClInclude Include="..\..\include\c11log\details\flush_helper.h" /> | ||||
|     <ClInclude Include="..\..\include\c11log\details\fast_istostr.h" /> | ||||
|     <ClInclude Include="..\..\include\c11log\details\file_helper.h" /> | ||||
|     <ClInclude Include="..\..\include\c11log\details\line_logger.h" /> | ||||
|     <ClInclude Include="..\..\include\c11log\details\logger_impl.h" /> | ||||
|     <ClInclude Include="..\..\include\c11log\details\log_msg.h" /> | ||||
|  | ||||
| @ -45,9 +45,6 @@ | ||||
|     <ClInclude Include="..\..\include\c11log\details\fast_oss.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\include\c11log\details\flush_helper.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\include\c11log\details\line_logger.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
| @ -99,6 +96,9 @@ | ||||
|     <ClInclude Include="..\..\include\c11log\details\registry.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\include\c11log\details\file_helper.h"> | ||||
|       <Filter>Header Files\c11log\details</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="stdafx.cpp"> | ||||
|  | ||||
| @ -15,29 +15,37 @@ using namespace utils; | ||||
| 
 | ||||
| int main(int argc, char* argv[]) | ||||
| { | ||||
|     const unsigned int howmany = argc <= 1 ? 600000 : atoi(argv[1]); | ||||
|     try { | ||||
|         const unsigned int howmany = argc <= 1 ? 500000 : atoi(argv[1]); | ||||
| 
 | ||||
|     //c11log::set_format("%t");
 | ||||
|     auto console = c11log::create<sinks::stdout_sink_st>("reporter"); | ||||
|     //console->set_format("[%n %l] %t");
 | ||||
|     console->set_level(c11log::level::INFO); | ||||
|     console->info("Starting bench with", howmany, "iterations.."); | ||||
|         //c11log::set_format("%t");
 | ||||
|         auto console = c11log::create<sinks::stdout_sink_st>("reporter"); | ||||
|         //console->set_format("[%n %l] %t");
 | ||||
|         console->set_level(c11log::level::INFO); | ||||
|         console->info("Starting bench with", howmany, "iterations.."); | ||||
| 
 | ||||
|         //auto bench = c11log::create<sinks::rotating_file_sink_st>("bench", "myrotating", "txt", 1024 * 1024 * 5, 3, 0);
 | ||||
|         auto bench = c11log::create<sinks::daily_file_sink_mt>("bench", "sdfsfddaily", "txt", 0); | ||||
|         //auto bench = c11log::create<sinks::simple_file_sink_st>("bench", "simplelog.txt", 1);
 | ||||
|         //auto bench = c11log::create<sinks::null_sink_st>("bench");
 | ||||
|         auto start = system_clock::now(); | ||||
|         for (unsigned int i = 1; i <= howmany; ++i) | ||||
|         { | ||||
|             c11log::get("bench")->info("Hello logger: msg number", i); | ||||
|         } | ||||
| 
 | ||||
|         auto delta = system_clock::now() - start; | ||||
|         auto delta_d = duration_cast<duration<double>> (delta).count(); | ||||
| 
 | ||||
|         console->info("Total:") << format(howmany); | ||||
|         console->info("Delta:") << format(delta_d); | ||||
|         console->info("Rate:") << format(howmany / delta_d) << "/sec"; | ||||
| 
 | ||||
|     //auto bench = c11log::create<sinks::rotating_file_sink_st>("bench", "myrotating", "txt", 1024 * 1024 * 5, 3, 100);
 | ||||
|     auto bench = c11log::create<sinks::null_sink_st>("bench"); | ||||
|     auto start = system_clock::now(); | ||||
|     for (unsigned int i = 1; i <= howmany; ++i) | ||||
|     { | ||||
|         c11log::get("bench")->info("Hello logger: msg number", i); | ||||
|     } | ||||
| 
 | ||||
|     auto delta = system_clock::now() - start; | ||||
|     auto delta_d = duration_cast<duration<double>> (delta).count(); | ||||
| 
 | ||||
|     console->info("Total:") << format(howmany); | ||||
|     console->info("Delta:") << format(delta_d); | ||||
|     console->info("Rate:") << format(howmany / delta_d) << "/sec"; | ||||
| 
 | ||||
|     catch (std::exception &ex) | ||||
|     { | ||||
|         std::cerr << "Exception: " << ex.what() << std::endl; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -16,7 +16,7 @@ details::fast_oss f(const std::string& what) | ||||
|     oss << what; | ||||
|     return oss; | ||||
| } | ||||
| int main(int, char* []) | ||||
| int main_(int, char* []) | ||||
| { | ||||
| 
 | ||||
|     auto foss = f("test2"); | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include<initializer_list> | ||||
| #include<memory> | ||||
| #include<chrono> | ||||
| 
 | ||||
| namespace c11log | ||||
| @ -37,4 +36,20 @@ inline const char* to_str(c11log::level::level_enum l) | ||||
|     return level_names[l]; | ||||
| } | ||||
| } //level
 | ||||
| 
 | ||||
| //
 | ||||
| // Log exception
 | ||||
| //
 | ||||
| class fflog_exception : public std::exception | ||||
| { | ||||
| public: | ||||
|     fflog_exception(const std::string& msg) :_msg(msg) {}; | ||||
|     const char* what() const throw() override { | ||||
|         return _msg.c_str(); | ||||
|     } | ||||
| private: | ||||
|     std::string _msg; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| } //c11log
 | ||||
|  | ||||
							
								
								
									
										90
									
								
								include/c11log/details/file_helper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								include/c11log/details/file_helper.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| // Helper class for file sink
 | ||||
| // When failing to open a file, retry several times(5) with small delay between the tries(10 ms)
 | ||||
| // Flush to file every X writes (or never if X==0)
 | ||||
| // Throw fflog_ exception on errors
 | ||||
| 
 | ||||
| 
 | ||||
| #include <cstdio> | ||||
| #include <string> | ||||
| #include <thread> | ||||
| #include <chrono> | ||||
| #include "../common.h" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| namespace details | ||||
| { | ||||
| 
 | ||||
| class file_helper | ||||
| { | ||||
| public: | ||||
|     static const int open_max_tries = 5; | ||||
|     static const int sleep_ms_bewteen_tries = 10; | ||||
| 
 | ||||
|     explicit file_helper(const std::size_t flush_inverval): | ||||
|         _fd(nullptr), | ||||
|         _flush_inverval(flush_inverval), | ||||
|         _flush_countdown(flush_inverval) {}; | ||||
| 
 | ||||
|     file_helper(const file_helper&) = delete; | ||||
| 
 | ||||
|     ~file_helper() | ||||
|     { | ||||
|         if (_fd) | ||||
|             std::fclose(_fd); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void open(const std::string& filename) | ||||
|     { | ||||
| 
 | ||||
|         if (_fd) | ||||
|             std::fclose(_fd); | ||||
| 
 | ||||
|         _filename = filename; | ||||
|         for (int tries = 0; tries < open_max_tries; ++tries) | ||||
|         { | ||||
|             if(!os::fopen_s(&_fd, filename, "wb")) | ||||
|                 return; | ||||
| 
 | ||||
|             std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms_bewteen_tries)); | ||||
|         } | ||||
| 
 | ||||
|         throw fflog_exception("Failed opening file " + filename + " for writing"); | ||||
|     } | ||||
| 
 | ||||
|     void close() | ||||
|     { | ||||
|         std::fclose(_fd); | ||||
|     } | ||||
| 
 | ||||
|     void write(const log_msg& msg) | ||||
|     { | ||||
|         auto& buf = msg.formatted.buf(); | ||||
|         size_t size = buf.size(); | ||||
|         if(std::fwrite(buf.data(), sizeof(char), size, _fd) != size) | ||||
|             throw fflog_exception("Failed writing to  file " + _filename); | ||||
| 
 | ||||
|         if(--_flush_countdown == 0) | ||||
|         { | ||||
|             std::fflush(_fd); | ||||
|             _flush_countdown = _flush_inverval; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     FILE* _fd; | ||||
|     std::string _filename; | ||||
|     const std::size_t _flush_inverval; | ||||
|     std::size_t _flush_countdown; | ||||
| 
 | ||||
| }; | ||||
| } | ||||
| } | ||||
| 
 | ||||
| @ -1,36 +0,0 @@ | ||||
| #pragma once | ||||
| // Flush to file every X writes..
 | ||||
| // If X is zero than never flush..
 | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| namespace details | ||||
| { | ||||
| 
 | ||||
| class file_flush_helper | ||||
| { | ||||
| public: | ||||
|     explicit file_flush_helper(const std::size_t flush_every): | ||||
|         _flush_every(flush_every), | ||||
|         _flush_countdown(flush_every) {}; | ||||
| 
 | ||||
|     file_flush_helper(const file_flush_helper&) = delete; | ||||
| 
 | ||||
|     void write(const log_msg& msg, std::ofstream& ofs) | ||||
|     { | ||||
|         auto& buf = msg.formatted.buf(); | ||||
|         ofs.write(buf.data(), buf.size()); | ||||
|         if(--_flush_countdown == 0) | ||||
|         { | ||||
|             ofs.flush(); | ||||
|             _flush_countdown = _flush_every; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const std::size_t _flush_every; | ||||
|     std::size_t _flush_countdown; | ||||
| }; | ||||
| } | ||||
| } | ||||
| 
 | ||||
| @ -96,11 +96,13 @@ constexpr inline unsigned short eol_size() | ||||
| inline bool fopen_s(FILE** fp, const std::string& filename, const char* mode) | ||||
| { | ||||
| #ifdef _WIN32 | ||||
|     return fopen_s(fp, filename, mode); | ||||
|     return ::fopen_s(fp, filename.c_str(), mode); | ||||
| #else | ||||
|     *fp = fopen((filename.c_str()), mode); | ||||
|     return fp == nullptr; | ||||
|     return *fp == nullptr; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| //Return utc offset in minutes or -1 on failure
 | ||||
|  | ||||
| @ -66,17 +66,6 @@ private: | ||||
|     void _log_msg(details::log_msg& msg); | ||||
| }; | ||||
| 
 | ||||
| class fflog_exception : public std::exception | ||||
| { | ||||
| public: | ||||
|     fflog_exception(const std::string& msg) :_msg(msg) {}; | ||||
|     const char* what() const throw() override { | ||||
|         return _msg.c_str(); | ||||
|     } | ||||
| private: | ||||
|     std::string _msg; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| //
 | ||||
| // Registry functions for easy loggers creation and retrieval
 | ||||
|  | ||||
| @ -1,13 +1,11 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include  <iomanip> | ||||
| #include "./base_sink.h" | ||||
| #include <mutex> | ||||
| #include "./base_sink.h" | ||||
| 
 | ||||
| #include "../details/null_mutex.h" | ||||
| #include "../details/flush_helper.h" | ||||
| #include "../details/blocking_queue.h" | ||||
| #include "../details/file_helper.h" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -24,19 +22,18 @@ class simple_file_sink : public base_sink<Mutex> | ||||
| { | ||||
| public: | ||||
|     explicit simple_file_sink(const std::string &filename, | ||||
|                               const std::size_t flush_every=0): | ||||
|         _ofstream(filename, std::ofstream::binary|std::ofstream::app), | ||||
|         _flush_helper(flush_every) | ||||
|                               const std::size_t flush_inverval=0): | ||||
|         _file_helper(flush_inverval) | ||||
|     { | ||||
|         _file_helper.open(filename); | ||||
|     } | ||||
| protected: | ||||
|     void _sink_it(const details::log_msg& msg) override | ||||
|     { | ||||
|         _flush_helper.write(msg, _ofstream); | ||||
|         _file_helper.write(msg); | ||||
|     } | ||||
| private: | ||||
|     std::ofstream _ofstream; | ||||
|     details::file_flush_helper _flush_helper; | ||||
|     details::file_helper _file_helper; | ||||
| }; | ||||
| 
 | ||||
| typedef simple_file_sink<std::mutex> simple_file_sink_mt; | ||||
| @ -51,15 +48,15 @@ class rotating_file_sink : public base_sink<Mutex> | ||||
| public: | ||||
|     rotating_file_sink(const std::string &base_filename, const std::string &extension, | ||||
|                        const std::size_t max_size, const std::size_t max_files, | ||||
|                        const std::size_t flush_every=0): | ||||
|                        const std::size_t flush_inverval=0): | ||||
|         _base_filename(base_filename), | ||||
|         _extension(extension), | ||||
|         _max_size(max_size), | ||||
|         _max_files(max_files), | ||||
|         _current_size(0), | ||||
|         _ofstream(_calc_filename(_base_filename, 0, _extension), std::ofstream::binary), | ||||
|         _flush_helper(flush_every) | ||||
|         _file_helper(flush_inverval) | ||||
|     { | ||||
|         _file_helper.open(_calc_filename(_base_filename, 0, _extension)); | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
| @ -71,7 +68,7 @@ protected: | ||||
|             _rotate(); | ||||
|             _current_size = msg.formatted.size(); | ||||
|         } | ||||
|         _flush_helper.write(msg, _ofstream); | ||||
|         _file_helper.write(msg); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| @ -95,25 +92,24 @@ private: | ||||
| 
 | ||||
|     void _rotate() | ||||
|     { | ||||
|         _ofstream.close(); | ||||
|         _file_helper.close(); | ||||
|         //Remove oldest file
 | ||||
|         for (auto i = _max_files; i > 0; --i) | ||||
|         { | ||||
|             auto src = _calc_filename(_base_filename, i - 1, _extension); | ||||
|             auto target = _calc_filename(_base_filename, i, _extension); | ||||
|             std::string src = _calc_filename(_base_filename, i - 1, _extension); | ||||
|             std::string target = _calc_filename(_base_filename, i, _extension); | ||||
|             if (i == _max_files) | ||||
|                 std::remove(target.c_str()); | ||||
|             std::rename(src.c_str(), target.c_str()); | ||||
|         } | ||||
|         _ofstream.open(_calc_filename(_base_filename, 0, _extension), std::ofstream::binary); | ||||
|         _file_helper.open(_calc_filename(_base_filename, 0, _extension)); | ||||
|     } | ||||
|     std::string _base_filename; | ||||
|     std::string _extension; | ||||
|     std::size_t _max_size; | ||||
|     std::size_t _max_files; | ||||
|     std::size_t _current_size; | ||||
|     std::ofstream _ofstream; | ||||
|     details::file_flush_helper _flush_helper; | ||||
|     details::file_helper _file_helper; | ||||
| }; | ||||
| 
 | ||||
| typedef rotating_file_sink<std::mutex> rotating_file_sink_mt; | ||||
| @ -128,13 +124,13 @@ class daily_file_sink:public base_sink<Mutex> | ||||
| public: | ||||
|     explicit daily_file_sink(const std::string& base_filename, | ||||
|                              const std::string& extension, | ||||
|                              const std::size_t flush_every=0): | ||||
|                              const std::size_t flush_inverval=0): | ||||
|         _base_filename(base_filename), | ||||
|         _extension(extension), | ||||
|         _midnight_tp (_calc_midnight_tp() ), | ||||
|         _ofstream(_calc_filename(_base_filename, _extension), std::ofstream::binary|std::ofstream::app), | ||||
|         _flush_helper(flush_every) | ||||
|         _file_helper(flush_inverval) | ||||
|     { | ||||
|         _file_helper.open(_calc_filename(_base_filename, _extension)); | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
| @ -142,11 +138,11 @@ protected: | ||||
|     { | ||||
|         if (std::chrono::system_clock::now() >= _midnight_tp) | ||||
|         { | ||||
|             _ofstream.close(); | ||||
|             _ofstream.open(_calc_filename(_base_filename, _extension)); | ||||
|             _file_helper.close(); | ||||
|             _file_helper.open(_calc_filename(_base_filename, _extension)); | ||||
|             _midnight_tp = _calc_midnight_tp(); | ||||
|         } | ||||
|         _flush_helper.write(msg, _ofstream); | ||||
|         _file_helper.write(msg); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
| @ -176,8 +172,7 @@ private: | ||||
|     std::string _base_filename; | ||||
|     std::string _extension; | ||||
|     std::chrono::system_clock::time_point _midnight_tp; | ||||
|     std::ofstream _ofstream; | ||||
|     details::file_flush_helper _flush_helper; | ||||
|     details::file_helper _file_helper; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user