From 0e6bf2b6f8cc76c149a818261d55eb96d4822911 Mon Sep 17 00:00:00 2001 From: huihut Date: Mon, 12 Aug 2019 14:48:53 +0800 Subject: [PATCH 1/4] Modify source @huihut --- .gitignore | 1 + src/logging.cc | 131 ++++++++++++++++++++++++++++++------------------- 2 files changed, 81 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index 76d251f6e..a7ab3bc32 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ config.h *.vcxproj *.filters bazel-* +.vscode/ diff --git a/src/logging.cc b/src/logging.cc index 0c86cf622..2f658b9ae 100644 --- a/src/logging.cc +++ b/src/logging.cc @@ -903,8 +903,10 @@ void LogFileObject::FlushUnlocked(){ } bool LogFileObject::CreateLogfile(const string& time_pid_string) { - string string_filename = base_filename_+filename_extension_+ - time_pid_string; + // string string_filename = base_filename_+filename_extension_+ + // time_pid_string; + // @huihut: path + severity + '_' + file name + ".log" + string string_filename = base_filename_ + filename_extension_ + time_pid_string + ".log"; const char* filename = string_filename.c_str(); int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, FLAGS_logfile_mode); if (fd == -1) return false; @@ -980,6 +982,23 @@ void LogFileObject::Write(bool force_flush, rollover_attempt_ = kRolloverAttemptFrequency-1; } + // @huihut: default module name & length + size_t module_len = 3; + string module_name = "etc"; + + // @huihut: get the module name from the log message + const char *ret_left, *ret_right; + ret_left = strchr(message, '['); + if(ret_left != NULL) + { + ret_right = strchr(ret_left, ' '); + if(ret_right != NULL) + { + module_len = ret_right - (ret_left + 1); + module_name = string((ret_left + 1), module_len); + } + } + // If there's no destination file, make one before outputting if (file_ == NULL) { // Try to rollover the log file every 32 log messages. The only time @@ -988,22 +1007,26 @@ void LogFileObject::Write(bool force_flush, if (++rollover_attempt_ != kRolloverAttemptFrequency) return; rollover_attempt_ = 0; - struct ::tm tm_time; - localtime_r(×tamp, &tm_time); - - // The logfile's filename will have the date/time & pid in it - ostringstream time_pid_stream; - time_pid_stream.fill('0'); - time_pid_stream << 1900+tm_time.tm_year - << setw(2) << 1+tm_time.tm_mon - << setw(2) << tm_time.tm_mday - << '-' - << setw(2) << tm_time.tm_hour - << setw(2) << tm_time.tm_min - << setw(2) << tm_time.tm_sec - << '.' - << GetMainThreadPid(); - const string& time_pid_string = time_pid_stream.str(); + // @huihut Use only the 'module_name' as the log file name + // struct ::tm tm_time; + // localtime_r(×tamp, &tm_time); + + // // The logfile's filename will have the date/time & pid in it + // ostringstream time_pid_stream; + // time_pid_stream.fill('0'); + // time_pid_stream << 1900+tm_time.tm_year + // << setw(2) << 1+tm_time.tm_mon + // << setw(2) << tm_time.tm_mday + // << '-' + // << setw(2) << tm_time.tm_hour + // << setw(2) << tm_time.tm_min + // << setw(2) << tm_time.tm_sec + // << '.' + // << GetMainThreadPid(); + // const string& time_pid_string = time_pid_stream.str(); + + // @huihut: Warning: use the 'time_pid_string' storage 'module_name' + const string& time_pid_string = module_name; if (base_filename_selected_) { if (!CreateLogfile(time_pid_string)) { @@ -1024,21 +1047,25 @@ void LogFileObject::Write(bool force_flush, // // Where does the file get put? Successively try the directories // "/tmp", and "." - string stripped_filename( - glog_internal_namespace_::ProgramInvocationShortName()); - string hostname; - GetHostName(&hostname); - string uidname = MyUserName(); + // @huihut Does not generate unwanted log files + // string stripped_filename( + // glog_internal_namespace_::ProgramInvocationShortName()); + // string hostname; + // GetHostName(&hostname); + + // string uidname = MyUserName(); + // We should not call CHECK() here because this function can be // called after holding on to log_mutex. We don't want to // attempt to hold on to the same mutex, and get into a // deadlock. Simply use a name like invalid-user. - if (uidname.empty()) uidname = "invalid-user"; - stripped_filename = stripped_filename+'.'+hostname+'.' - +uidname+".log." - +LogSeverityNames[severity_]+'.'; + // if (uidname.empty()) uidname = "invalid-user"; + + // stripped_filename = stripped_filename+'.'+hostname+'.' + // +uidname+".log." + // +LogSeverityNames[severity_]+'.'; // We're going to (potentially) try to put logs in several different dirs const vector & log_dirs = GetLoggingDirectories(); @@ -1048,7 +1075,7 @@ void LogFileObject::Write(bool force_flush, for (vector::const_iterator dir = log_dirs.begin(); dir != log_dirs.end(); ++dir) { - base_filename_ = *dir + "/" + stripped_filename; + // base_filename_ = *dir + "/" + stripped_filename; if ( CreateLogfile(time_pid_string) ) { success = true; break; @@ -1063,27 +1090,28 @@ void LogFileObject::Write(bool force_flush, } } - // Write a header message into the log file - ostringstream file_header_stream; - file_header_stream.fill('0'); - file_header_stream << "Log file created at: " - << 1900+tm_time.tm_year << '/' - << setw(2) << 1+tm_time.tm_mon << '/' - << setw(2) << tm_time.tm_mday - << ' ' - << setw(2) << tm_time.tm_hour << ':' - << setw(2) << tm_time.tm_min << ':' - << setw(2) << tm_time.tm_sec << '\n' - << "Running on machine: " - << LogDestination::hostname() << '\n' - << "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu " - << "threadid file:line] msg" << '\n'; - const string& file_header_string = file_header_stream.str(); - - const int header_len = file_header_string.size(); - fwrite(file_header_string.data(), 1, header_len, file_); - file_length_ += header_len; - bytes_since_flush_ += header_len; + // @huihut delete file_header + // // Write a header message into the log file + // ostringstream file_header_stream; + // file_header_stream.fill('0'); + // file_header_stream << "Log file created at: " + // << 1900+tm_time.tm_year << '/' + // << setw(2) << 1+tm_time.tm_mon << '/' + // << setw(2) << tm_time.tm_mday + // << ' ' + // << setw(2) << tm_time.tm_hour << ':' + // << setw(2) << tm_time.tm_min << ':' + // << setw(2) << tm_time.tm_sec << '\n' + // << "Running on machine: " + // << LogDestination::hostname() << '\n' + // << "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu " + // << "threadid file:line] msg" << '\n'; + // const string& file_header_string = file_header_stream.str(); + + // const int header_len = file_header_string.size(); + // fwrite(file_header_string.data(), 1, header_len, file_); + // file_length_ += header_len; + // bytes_since_flush_ += header_len; } // Write to LOG file @@ -1289,8 +1317,9 @@ void LogMessage::Init(const char* file, << ' ' << setfill(' ') << setw(5) << static_cast(GetTID()) << setfill('0') - << ' ' - << data_->basename_ << ':' << data_->line_ << "] "; + << ' '; + // @huihut delete file & line + // << data_->basename_ << ':' << data_->line_ << "] "; } data_->num_prefix_chars_ = data_->stream_.pcount(); From 53796cd632cb8031677894be40bbceb0644797a5 Mon Sep 17 00:00:00 2001 From: huihut Date: Mon, 12 Aug 2019 15:59:36 +0800 Subject: [PATCH 2/4] Update README.md --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/README.md b/README.md index 965766c7c..48bb52245 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,45 @@ See INSTALL for (generic) installation instructions for C++: basically ```sh ./autogen.sh && ./configure && make && make install ``` + +## Build + +1. Build VS project with CMake + * Check `BUILD_SHARED_LIBS` + * Uncheck `WITH_GFLASS` + * `CMAKE_INSTALL_PREFIX` fill in the install path + * Configure + * Generate +2. Compile and install using VS + * Debug: Generate INSTALL project + * Release: Generate INSTALL project + + +
Some dependent libraries that glog projects may need + +``` +kernel32.lib +user32.lib +gdi32.lib +winspool.lib +shell32.lib +ole32.lib +oleaut32.lib +uuid.lib +comdlg32.lib +advapi32.lib +``` + +
+ +## Usage + +1. To add glog's DLL header to your include path +2. To add glog's DLL import library to your project +3. To add `GLOG_NO_ABBREVIATED_SEVERITIES` to Preprocessor Definitions +4. Additional Dependencies add + * Debug:`glogd.lib` + * Release:`glog.lib` +5. To copy the DLL in a post-build event + * Debug:`xcopy /y /d "..\path_to_install\bin\glogd.dll" "$(OutDir)"` + * Release:`xcopy /y /d "..\path_to_install\bin\glog.dll" "$(OutDir)"` \ No newline at end of file From fbb23713334bc2aecf99ac296f47df58e57d7e3a Mon Sep 17 00:00:00 2001 From: huihut Date: Mon, 12 Aug 2019 16:20:23 +0800 Subject: [PATCH 3/4] Add Example --- README.md | 29 +++++- example/example_windows.cpp | 187 ++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 example/example_windows.cpp diff --git a/README.md b/README.md index 48bb52245..93511d222 100644 --- a/README.md +++ b/README.md @@ -49,4 +49,31 @@ advapi32.lib * Release:`glog.lib` 5. To copy the DLL in a post-build event * Debug:`xcopy /y /d "..\path_to_install\bin\glogd.dll" "$(OutDir)"` - * Release:`xcopy /y /d "..\path_to_install\bin\glog.dll" "$(OutDir)"` \ No newline at end of file + * Release:`xcopy /y /d "..\path_to_install\bin\glog.dll" "$(OutDir)"` + +## Example + +```cpp +#include +int main() +{ + FLAGS_log_dir = "/home/$USER"; // Make sure the folder exists + google::InitGoogleLogging(""); + google::SetLogDestination(google::GLOG_INFO, "/home/$USER/INFO"); // Make sure the folder exists + google::SetStderrLogging(google::GLOG_INFO); + google::SetLogFilenameExtension("log_"); + FLAGS_colorlogtostderr = true; // Set log color + FLAGS_logbufsecs = 0; // Set log output speed(s) + FLAGS_max_log_size = 1024; // Set max log file size + FLAGS_stop_logging_if_full_disk = true; // If disk is full + + LOG(INFO) << "[" << "fileName" << " " << "functionName" << "] " << "logContent"; + LOG(WARNING) << "[" << "fileName" << " " << "functionName" << "] " << "logContent"; + LOG(ERROR) << "[" << "fileName" << " " << "functionName" << "] " << "logContent"; + + google::ShutdownGoogleLogging(); + return 0; +} +``` + +* Windows: [example/example_windows.cpp](example/example_windows.cpp) \ No newline at end of file diff --git a/example/example_windows.cpp b/example/example_windows.cpp new file mode 100644 index 000000000..5ed2c138e --- /dev/null +++ b/example/example_windows.cpp @@ -0,0 +1,187 @@ +#include +#include +#include +#pragma comment(lib, "Dbghelp.lib") + +#include + +enum LogLevel +{ + LOG_INFO, + LOG_WARNING, + LOG_ERROR +}; + +class GLogger +{ +public: + GLogger(); + ~GLogger(); + + void Write(const char* function, std::string log, LogLevel level = LOG_INFO); + +private: + inline void Write_Info(const std::string&, const std::string&, const std::string&); + inline void Write_Warning(const std::string&, const std::string&, const std::string&); + inline void Write_Error(const std::string&, const std::string&, const std::string&); + + inline std::string GetModuleNameByStack(unsigned short layer); + inline std::string GetLogDatePath(); + inline std::string GetLogDateINFOPath(std::string); +}; + +// Init glog +GLogger::GLogger() +{ + std::string logDatePath = GetLogDatePath(); + FLAGS_log_dir = logDatePath; + google::InitGoogleLogging(""); + google::SetLogDestination(google::GLOG_INFO, GetLogDateINFOPath(logDatePath).c_str()); + google::SetStderrLogging(google::GLOG_INFO); + google::SetLogFilenameExtension("log_"); + FLAGS_colorlogtostderr = true; // Set log color + FLAGS_logbufsecs = 0; // Set log output speed(s) + FLAGS_max_log_size = 1024; // Set max log file size + FLAGS_stop_logging_if_full_disk = true; // If disk is full +} + +GLogger::~GLogger() +{ + google::ShutdownGoogleLogging(); +} + +// Write log +void GLogger::Write(const char* function, std::string log, LogLevel level) +{ + if (log.empty()) + return; + + std::string fileName(GetModuleNameByStack(1)); + if (fileName.empty()) + fileName = "etc"; + + std::string functionName(function); + + switch (level) + { + case LOG_WARNING: + Write_Warning(fileName, functionName, log); + break; + case LOG_ERROR: + Write_Error(fileName, functionName, log); + break; + default: + Write_Info(fileName, functionName, log); + break; + } +} + +inline void GLogger::Write_Info(const std::string& fileName, const std::string& functionName, const std::string& logContent) +{ + LOG(INFO) << "[" << fileName << " " << functionName << "] " << logContent; +} + +inline void GLogger::Write_Warning(const std::string& fileName, const std::string& functionName, const std::string& logContent) +{ + LOG(WARNING) << "[" << fileName << " " << functionName << "] " << logContent; +} + +inline void GLogger::Write_Error(const std::string& fileName, const std::string& functionName, const std::string& logContent) +{ + LOG(ERROR) << "[" << fileName << " " << functionName << "] " << logContent; +} + +// Get module name (exe/dll) +inline std::string GLogger::GetModuleNameByStack(unsigned short layer) +{ + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); + + void* stack[100]; + unsigned short frames = CaptureStackBackTrace(0, 100, stack, NULL); + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + if (frames >= ++layer) + { + SymFromAddr(process, (DWORD64)(stack[2]), 0, symbol); + + HMODULE hModule = NULL; + GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCTSTR)(stack[layer]), &hModule); + + if (hModule != NULL) + { + char moduleName[256]; + lstrcpyA(moduleName, ""); + GetModuleFileNameA(hModule, moduleName, 256); + + std::string name(moduleName); + if (!name.empty()) + { + size_t nPos = name.rfind("\\"); + name = name.substr(nPos + 1, name.size() - 1); + nPos = name.rfind("."); + name = name.substr(0, nPos); + return name; + } + } + } + return ""; +} + +// Get Log Date path: %appdata%\GLogger\Log\yyyy_mm_dd +inline std::string GLogger::GetLogDatePath() +{ + // Get appdata + char path[MAX_PATH]; + if (::SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, path) != S_OK) + { + return ""; + } + + // date + SYSTEMTIME sys; + GetLocalTime(&sys); + std::string date(std::to_string(sys.wYear) + '_' + + std::to_string(sys.wMonth) + '_' + + std::to_string(sys.wDay)); + + // appdata + log + date + strcat(path, "\\GLogger\\Log\\"); + strcat(path, date.c_str()); + if (SHCreateDirectoryExA(NULL, path, NULL) != ERROR_SUCCESS + && ERROR_FILE_EXISTS != GetLastError() + && ERROR_ALREADY_EXISTS != GetLastError()) + { + return ""; + } + return std::string(path); +} + +// Get INFO path +inline std::string GLogger::GetLogDateINFOPath(std::string logDatePath) +{ + logDatePath += "\\INFO"; + if (SHCreateDirectoryExA(NULL, logDatePath.c_str(), NULL) != ERROR_SUCCESS + && ERROR_FILE_EXISTS != GetLastError() + && ERROR_ALREADY_EXISTS != GetLastError()) + { + return ""; + } + return logDatePath; +} + +int main() +{ + GLogger glogger; + glogger.Write(__FUNCTION__, "Log test!!!!!!!!!!!!!!"); + glogger.Write(__FUNCTION__, "(LOG_INFO) Log test!!!!!!!!!!!!!!", LOG_INFO); + glogger.Write(__FUNCTION__, "(LOG_WARNING) Log test!!!!!!!!!!!!!!", LOG_WARNING); + glogger.Write(__FUNCTION__, "(LOG_ERROR) Log test!!!!!!!!!!!!!!", LOG_ERROR); + getchar(); + + return 0; +} \ No newline at end of file From b526c991638cf9ae3a5c56438cb0693e0bcd2d26 Mon Sep 17 00:00:00 2001 From: huihut Date: Mon, 12 Aug 2019 17:16:07 +0800 Subject: [PATCH 4/4] Update example_windows.cpp --- example/example_windows.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/example/example_windows.cpp b/example/example_windows.cpp index 5ed2c138e..7d36e9426 100644 --- a/example/example_windows.cpp +++ b/example/example_windows.cpp @@ -91,7 +91,10 @@ inline void GLogger::Write_Error(const std::string& fileName, const std::string& LOG(ERROR) << "[" << fileName << " " << functionName << "] " << logContent; } -// Get module name (exe/dll) +// Get module(exe/dll) name +// layer: The number of stack layers for the caller. for example: +// * layer = 0, get the caller's own module name; +// * layer = 1, get the module name of the layer above the caller inline std::string GLogger::GetModuleNameByStack(unsigned short layer) { HANDLE process = GetCurrentProcess();