1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #ifndef __LOG_H_INCLUDED_ 27 #define __LOG_H_INCLUDED_ 28 29 #include <windows.h> 30 #include "tstrings.h" 31 32 33 /* Default logger (Logger::defaultLogger()) writes log messages to 34 * the default log file. 35 * Common scenario: 36 * - main() function configures default logger: 37 * FileLogAppender appender(_T("my_log_filename.log")); 38 * Logger::defaultLogger().setAppender(appender); 39 * Logger::defaultLogger().setLogLevel(LOG_INFO); 40 * If the default file name and log level are not set, 41 * _T("jusched.log")/LOG_TRACE are used. 42 * 43 * Logger fileName specifies only file name, 44 * full path for the log file depends on the platform 45 * (usually value of the TMP env. var) 46 */ 47 48 struct LogEvent { 49 SYSTEMTIME ts; 50 long tid; 51 long pid; 52 tstring moduleName; 53 tstring logLevel; 54 tstring fileName; 55 int lineNum; 56 tstring funcName; 57 tstring message; 58 59 LogEvent(); 60 }; 61 62 63 class LogAppender { 64 public: 65 virtual ~LogAppender() { 66 } 67 virtual void append(const LogEvent& v) = 0; 68 }; 69 70 71 class NopLogAppender: public LogAppender { 72 public: 73 virtual void append(const LogEvent& v) {}; 74 }; 75 76 77 class TeeLogAppender: public LogAppender { 78 public: 79 TeeLogAppender(LogAppender* first, LogAppender* second): 80 first(first), second(second) { 81 } 82 virtual ~TeeLogAppender() { 83 } 84 virtual void append(const LogEvent& v) { 85 if (first) { 86 first->append(v); 87 } 88 if (second) { 89 second->append(v); 90 } 91 } 92 private: 93 LogAppender* first; 94 LogAppender* second; 95 }; 96 97 98 /** 99 * Writes log events to stderr. 100 */ 101 class StderrLogAppender: public LogAppender { 102 public: 103 explicit StderrLogAppender(); 104 105 virtual void append(const LogEvent& v); 106 }; 107 108 109 class Logger { 110 public: 111 enum LogLevel { 112 LOG_TRACE, 113 LOG_INFO, 114 LOG_WARNING, 115 LOG_ERROR 116 }; 117 118 static Logger& defaultLogger(); 119 120 explicit Logger(LogAppender& appender, LogLevel logLevel = LOG_TRACE); 121 ~Logger(); 122 123 LogAppender& setAppender(LogAppender& v) { 124 LogAppender& oldAppender = *appender; 125 appender = &v; 126 return oldAppender; 127 } 128 129 LogAppender& getAppender() const { 130 return *appender; 131 } 132 133 void setLogLevel(LogLevel logLevel); 134 135 bool isLoggable(LogLevel logLevel) const ; 136 void log(LogLevel logLevel, LPCTSTR fileName, int lineNum, 137 LPCTSTR funcName, const tstring& message) const; 138 void log(LogLevel logLevel, LPCTSTR fileName, int lineNum, 139 LPCTSTR funcName, const tstrings::any& message) const { 140 return log(logLevel, fileName, lineNum, funcName, message.tstr()); 141 } 142 void log(LogLevel logLevel, LPCTSTR fileName, int lineNum, 143 LPCTSTR funcName, tstring::const_pointer message) const { 144 return log(logLevel, fileName, lineNum, funcName, tstring(message)); 145 } 146 147 // internal class for scope tracing 148 class ScopeTracer { 149 public: 150 ScopeTracer(Logger &logger, LogLevel logLevel, LPCTSTR fileName, 151 int lineNum, LPCTSTR funcName, const tstring& scopeName); 152 ~ScopeTracer(); 153 154 private: 155 const Logger &log; 156 const LogLevel level; 157 const bool needLog; 158 const tstring file; 159 const int line; 160 const tstring func; 161 const tstring scope; 162 }; 163 164 private: 165 LogLevel level; 166 LogAppender* appender; 167 }; 168 169 170 // base logging macro 171 #define LOGGER_LOG(logger, logLevel, message) \ 172 do { \ 173 if (logger.isLoggable(logLevel)) { \ 174 logger.log(logLevel, _T(__FILE__), __LINE__, _T(__FUNCTION__), message); \ 175 } \ 176 } while(false) 177 178 179 // custom logger macros 180 #define LOGGER_TRACE(logger, message) LOGGER_LOG(logger, Logger::LOG_TRACE, message) 181 #define LOGGER_INFO(logger, message) LOGGER_LOG(logger, Logger::LOG_INFO, message) 182 #define LOGGER_WARNING(logger, message) LOGGER_LOG(logger, Logger::LOG_WARNING, message) 183 #define LOGGER_ERROR(logger, message) LOGGER_LOG(logger, Logger::LOG_ERROR, message) 184 // scope tracing macros 185 #define LOGGER_TRACE_SCOPE(logger, scopeName) \ 186 Logger::ScopeTracer tracer__COUNTER__(logger, Logger::LOG_TRACE, _T(__FILE__), __LINE__, _T(__FUNCTION__), scopeName) 187 #define LOGGER_TRACE_FUNCTION(logger) LOGGER_TRACE_SCOPE(logger, _T(__FUNCTION__)) 188 189 190 // default logger macros 191 #define LOG_TRACE(message) LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_TRACE, message) 192 #define LOG_INFO(message) LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_INFO, message) 193 #define LOG_WARNING(message) LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_WARNING, message) 194 #define LOG_ERROR(message) LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_ERROR, message) 195 // scope tracing macros 196 // logs (_T("Entering ") + scopeName) at the beging, (_T("Exiting ") + scopeName) at the end of scope 197 #define LOG_TRACE_SCOPE(scopeName) LOGGER_TRACE_SCOPE(Logger::defaultLogger(), scopeName) 198 // logs (_T("Entering ") + functionName) at the beging, (_T("Exiting ") + __FUNCTION__) at the end of scope 199 #define LOG_TRACE_FUNCTION() LOGGER_TRACE_FUNCTION(Logger::defaultLogger()) 200 201 202 #endif // __LOG_H_INCLUDED_