It took me a few hours to write this log system, and its functions are not complete yet. I will continue to improve it in the future and strive to achieve commercial level.
Unicode is not supported currently, but I have already tested how to support Unicode.
The Code is as follows:
# Pragma once </P> <p> # include "Common. H "<br/> # include <time. h> <br/> # include <windows. h> </P> <p> /****************************** * *********** <br/> * a small log system, file splitting is not supported <br/> * Non-log mode is not supported (and optimized in this mode) <br/> * debugview not supported <br/> * format not supported <br/> * multi-instance not supported <br/> * redirection not supported <br/> * not supported multithreading <br/> * trap: log ** has multi-line statements <br/> ***************************** * ************/<br/> template <typename lock> <br/> class guard <br/> {<br /> Lock _ Lock; <br/> Public: <br/> guard (lock) <br/>{< br/> _ Lock = lock; <br/> _ Lock. acquire (); <br/>}< br/> ~ Guard () <br/>{< br/> _ Lock. release (); <br/>}< br/>}; </P> <p> class critical_section <br/>{< br/> public: <br/> critical_section () <br/>{< br/>;< br/>}< br/> ~ Critical_section () <br/>{< br/>;< br/>}</P> <p> void acquire () <br/>{< br/>; <br/>}</P> <p> void release () <br/>{< br/>;< br/>}< br/> }; </P> <p> class mutex <br/> {<br/> Public: <br/> void acquire () <br/>{< br/>; <br/>}</P> <p> void release () <br/>{< br/>;< br/>}< br/> }; </P> <p> template <typename T> <br/> class Singleton <br/> {<br/> protected: <br/> Singleton () <br/>{< br/>}</P> <p> Public: <br/> static T * create_in Stance () <br/>{< br/> If (_ instance = NULL) <br/>{< br/>__ instance = new T; <br/>}</P> <p> return _ instance; <br/>}</P> <p> static T * instance () <br/>{< br/> return _ instance; <br/>}</P> <p> protected: <br/> static T * _ instance; <br/>}; </P> <p> template <typename T> <br/> T * Singleton <t >:__ instance = NULL; </P> <p> Enum e_log_level <br/> {<br/> log_level_trace, <br/> log_level_debug, <br/> log_level_info, <br/> Log_level_warn, <br/> log_level_error, <br/> log_level_fatal <br/>}; </P> <p> class log_system: public Singleton <log_system> <br/>{< br/> friend class Singleton <log_system >;< br/> PRIVATE: <br/> log_system () <br/>{< br/> _ initialized = false; <br/>}< br/> Public: <br/> bool Init (const string LOG_FILE, e_log_level log_level) <br/>{< br/> // string file_name = "C:/axaz.log.txt"; <br/> _ OUTFILE. open (log_file.c_s TR (); </P> <p> set_level (log_level); </P> <p> return _ initialized = (_ OUTFILE! = 0); <br/>}</P> <p> void finilly () <br/>{< br/> If (_ initialized & _ OUTFILE) <br/>{< br/> _ OUTFILE. close (); <br/>}</P> <p> void set_level (e_log_level log_level) <br/>{< br/> _ log_evel = log_level; <br/>}</P> <p> void set_cur_level (e_log_level cur_level) <br/>{< br/> _ cur_evel = cur_level; <br/>}</P> <p> template <typename T> <br/> log_system & operator <(const t OBJ) <br/>{< br/> If (_ cur_evel >=_ log_evel & _ initialized) <br/>{< br/> _ OUTFILE <OBJ; <br/>}</P> <p> return * this; <br/>}</P> <p> template <> <br/> log_system & operator <(const char * OBJ) <br/>{< br/> If (_ cur_evel >=_ log_evel & _ initialized) <br/>{< br/> _ OUTFILE <OBJ; <br/>}</P> <p> return * this; <br/>}</P> <p> template <> <br/> log_system & operator <(const string & OBJ) <br/>{< br/> If (_ cur_evel >=_ log_evel & _ initialized) <br/>{< br/> _ OUTFILE <OBJ; <br/>}</P> <p> return * This; <br/>}</P> <p> log_system & log_cur_time () <br/>{< br/> If (_ cur_evel >=_ log_evel & _ initialized) <br/>{< br/> char OBJ [30] = {0}; <br/> static systemtime nowtime = {0 }; <br/> getlocaltime (& nowtime); <br/> sprintf (OBJ, "% 02d: % 02d: % 02d. % 03d/T ", <br/> nowtime. whour, nowtime. wminute, nowtime. wsecond, nowtime. wmilliseconds); </P> <p> _ OUTFILE <OBJ; <br/>}</P> <p> return * this; <br/>}</P> <p> log_system & operator <(basic_ostream <char, char_traits <char> & (* OBJ) (basic_ostream <char, char_traits <char >>&) <br/>{< br/> If (_ cur_evel >=_ log_evel & _ initialized) <br/>{< br/> _ OUTFILE <OBJ; <br/>}</P> <p> return * this; <br/>}</P> <p> Public: </P> <p> PRIVATE: <br/> ofstream _ OUTFILE; <br/> bool _ initialized; </P> <p> e_log_level _ log_evel; <br/> e_log_level _ cur_evel; <br/>}; </P> <p> # DEFINE _ log log_system :: instance ()-> log_cur_time () <"(" <_ line _ <")/t" <br/> # define log_trace log_system: instance () -> set_cur_level (log_level_trace); _ log <"TRACE/t" <br/> # define log_debug log_system: instance ()-> set_cur_level (log_level_debug ); _ log <"Debug/t" <br/> # define log_info log_system: instance ()-> set_cur_level (log_level_info ); _ log <"info/t" <br/> # define log_warn log_system: instance ()-> set_cur_level (log_level_warn ); _ log <"Warn/t" <br/> # define log_error log_system: instance ()-> set_cur_level (log_level_error ); _ log <"error/t" <br/> # define log_fatal log_system: instance ()-> set_cur_level (log_level_fatal ); _ log <"Fatal/t" <br/> # define log log_debug </P> <p> # ifdef test_log <br/> int _ tmain (INT argc, _ tchar * argv []) <br/>{< br/> log_system * log = log_system: create_instance (); // judge by the short pointer <br/> log_system & log = * (log_system: instance (); <br/> log. init ("C:/log.txt", log_level_debug); </P> <p> log <"Hello, world" <Endl; <br/> log <"yes, please" <Endl; </P> <p> log. finilly (); </P> <p> return 0; <br/>}</P> <p> int _ tmain (INT argc, _ tchar * argv []) <br/>{< br/> log_system: create_instance (); <br/> log_system: instance ()-> Init ("C:/log.txt", log_level_debug ); </P> <p> log <"Hello, world" <Endl; <br/> log_trace <"hi" <Endl; <br/> log_fatal <"OK" <Endl; </P> <p> log_system: instance ()-> finilly (); <br/> return 0; <br/>}< br/> # endif
During the implementation of this log, I finally understood why ace should use double brackets for logging. The next step is to add multi-threaded support. After all, this function is the most important.