1 /*---------------------------------------------------------------------------* 2 * plog.h * 3 * * 4 * Copyright 2007, 2008 Nuance Communciations, Inc. * 5 * * 6 * Licensed under the Apache License, Version 2.0 (the 'License'); * 7 * you may not use this file except in compliance with the License. * 8 * * 9 * You may obtain a copy of the License at * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, software * 13 * distributed under the License is distributed on an 'AS IS' BASIS, * 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 15 * See the License for the specific language governing permissions and * 16 * limitations under the License. * 17 * * 18 *---------------------------------------------------------------------------*/ 19 20 #ifndef PLOG_H 21 #define PLOG_H 22 23 24 25 #include "ESR_ReturnCode.h" 26 #include "PortPrefix.h" 27 #ifdef USE_STACKTRACE 28 #include "PStackTrace.h" 29 #endif 30 #include "passert.h" 31 #include "PFileSystem.h" 32 #include "ptypes.h" 33 34 /** 35 * @addtogroup PLogModule PLogger API functions 36 * Logging API. 37 * 38 * Must call pmemInit() before using this module. 39 * 40 * The logging API is composed of a Logger. 41 * A Logger is an object who implements an API to actually write log messages. 42 * The logging API uses the logger when logging is to be performed but does 43 * not depend on an actual implementation of this API. 44 * 45 * When a request for logging is performed, the current level of the logging 46 * API is compared with the current stack-trace level. If the logger's log 47 * level is greater than or equal to the stack-trace level, then the 48 * message is being logged through the use of the Logger. Otherwise, the 49 * message is not logged. Setting the log level of the API to UINT_MAX is 50 * equivalent to unconditionally log all messages from all modules. Conversely, 51 * setting the log level of the API to 0 is equivalent to disabling logging globally. 52 * 53 * @{ 54 */ 55 56 57 /** 58 * Portable logging framework. 59 */ 60 typedef struct PLogger_t 61 { 62 /** 63 * Prints and formats a message to the log. 64 * 65 * @param self the Logger. 66 * 67 * @param format the format string specifying the next arguments (a la 68 * printf). 69 * 70 * @return ESR_SUCCESS if success, otherwise a status code indicating the 71 * nature of the error. 72 */ 73 ESR_ReturnCode(*printf)(struct PLogger_t *self, 74 const LCHAR *format, ...); 75 76 /** 77 * Flushes internal buffer. This function can be left unimplemented if no 78 * buffering is performed by the logger. 79 80 * @param self the Logger 81 * 82 * @return ESR_SUCCESS if success, otherwise a status code indicating the nature of the error. 83 */ 84 ESR_ReturnCode(*flush)(struct PLogger_t *self); 85 86 /** 87 * Destroys the logger. This function is responsible to deallocate any 88 * resources used by the logger. In particular, if buffering is internally 89 * used, it needs to flush the buffer. 90 */ 91 void(*destroy)(struct PLogger_t *self); 92 } 93 PLogger; 94 95 /** 96 * Type used to control output format. 97 */ 98 typedef asr_uint16_t LOG_OUTPUT_FORMAT; 99 100 /** 101 * Specifies that no extra information is to be output. 102 */ 103 #define LOG_OUTPUT_FORMAT_NONE 0x0000 104 105 /** 106 * Specifies that the date and time is to be output. 107 */ 108 #define LOG_OUTPUT_FORMAT_DATE_TIME 0x0001 109 110 /** 111 * Specifies that thread id of thread generating the message is to be output. 112 */ 113 #define LOG_OUTPUT_FORMAT_THREAD_ID 0x0002 114 115 /** 116 * Specifies that the module name of the module generating the message is to 117 * be output. 118 */ 119 #define LOG_OUTPUT_FORMAT_MODULE_NAME 0x0004 120 121 /** 122 * Initializes the LOG library. This function must be called before any 123 * logging can take place. PtrdInit() must be called before this function on 124 * platforms that support threads. 125 * 126 * @param logger The logger to be used to output the messages. If NULL, then 127 * logging goes to PSTDERR. 128 * 129 * @param logLevel The level of logging requested. 130 * 131 * @return ESR_SUCCESS if success, otherwise a status code indicating the 132 * nature of the error. In particular, it returns ESR_INVALID_STATE if already 133 * initialized. 134 */ 135 PORTABLE_API ESR_ReturnCode PLogInit(PLogger *logger, unsigned int logLevel); 136 137 /** 138 * Indicates if PLog module is initialized. 139 * 140 * @param isInit True if module is initialized 141 * @return ESR_INVALID_ARGUMENT if isLocked is null 142 */ 143 PORTABLE_API ESR_ReturnCode PLogIsInitialized(ESR_BOOL* isInit); 144 145 /** 146 * Indicates if PLog module is locked inside a critical section. This is for internal use only. 147 * 148 * @param isLocked True if module is locked 149 * @return ESR_INVALID_ARGUMENT if isLocked is null 150 */ 151 PORTABLE_API ESR_ReturnCode PLogIsLocked(ESR_BOOL* isLocked); 152 153 /** 154 * Shutdowns the LOG library. Once this function is called, no logging 155 * activity can be performed. 156 * 157 * @return ESR_SUCCESS if success, otherwise a status code indicating the 158 * nature of the error. In particular, it returns ESR_INVALID_STATE if not 159 * initialized or already shutted down. 160 */ 161 PORTABLE_API ESR_ReturnCode PLogShutdown(void); 162 163 /** 164 * Sets the format of the logging messages. If this function is never called, 165 * the default format is 166 * 167 * <code>LOG_OUTPUT_FORMAT_MODULE_NAME | LOG_OUTPUT_FORMAT_DATE_TIME</code>. 168 * 169 * @param format the format specification for new messages. 170 * 171 * @return ESR_SUCCESS if success, otherwise a status code indicating the 172 * nature of the error. 173 */ 174 PORTABLE_API ESR_ReturnCode PLogSetFormat(LOG_OUTPUT_FORMAT format); 175 176 /** 177 * Gets the current log level of the LOG API. 178 * 179 * @param logLevel A pointer to where the log level is to be stored. If NULL, 180 * the function returns ESR_INVALID_ARGUMENT. 181 * 182 * @return ESR_SUCCESS if success, otherwise a status code indicating the 183 * nature of the error. In particular, it returns ESR_INVALID_STATE if the 184 * API is not initialized. 185 */ 186 PORTABLE_API ESR_ReturnCode PLogGetLevel(unsigned int *logLevel); 187 188 189 /** 190 * Sets the current log level of the LOG API. 191 * 192 * @param logLevel The new log level. 193 * 194 * @return ESR_SUCCESS if success, otherwise a status code indicating the 195 * nature of the error. In particular, it returns ESR_INVALID_STATE if the 196 * API is not initialized. 197 */ 198 PORTABLE_API ESR_ReturnCode PLogSetLevel(unsigned int logLevel); 199 200 /** 201 * Conditionally Logs a message. The message is logged only if module is enabled. 202 * 203 * @param msg The message format specification (ala printf). 204 * 205 * @return ESR_SUCCESS if success, otherwise a status code indicating the 206 * nature of the error. In particular, it returns ESR_INVALID_STATE if 207 * the API is not initialized. 208 */ 209 PORTABLE_API ESR_ReturnCode PLogMessage(const LCHAR* msg, ...); 210 211 /** 212 * Unconditionally logs an error message. 213 * 214 * @param msg The message format specification (ala printf). 215 * 216 * @return ESR_SUCCESS if success, otherwise a status code indicating the 217 * nature of the error. In particular, it returns ESR_INVALID_STATE if 218 * the API is not initialized. 219 */ 220 PORTABLE_API ESR_ReturnCode PLogError(const LCHAR* msg, ...); 221 222 223 /** 224 * 225 * Creates a logger that logs to a file. 226 * 227 * @param file The file to log to. 228 * @param logger logger handle receiving the created logger. 229 * 230 * @return ESR_SUCCESS if success, otherwise a status code indicating the 231 * nature of the error. 232 */ 233 PORTABLE_API ESR_ReturnCode PLogCreateFileLogger(PFile* file, 234 PLogger** logger); 235 236 /** 237 * Creates a logger that logs to a circular file. 238 * 239 * @param filename The name of the file to be created. 240 * @param maxsize The maximum number of bytes that the file may have. 241 * @param logger logger handle receiving the created logger. 242 * 243 * @return ESR_SUCCESS if success, otherwise a status code indicating the 244 * nature of the error. 245 */ 246 PORTABLE_API ESR_ReturnCode PLogCreateCircularFileLogger(const LCHAR* filename, 247 unsigned int maxsize, 248 PLogger** logger); 249 250 251 252 /** 253 * Runs a function, checks its return-code. In case of an error, logs it and jumps to 254 * the CLEANUP label. 255 */ 256 /* show more information for vxworks due to lack of stack trace */ 257 #define CHKLOG(rc, function) do { rc = (function); if (rc != ESR_SUCCESS) { PLogError("%s in %s:%d", ESR_rc2str(rc), __FILE__, __LINE__); goto CLEANUP; } } while (0) 258 /** 259 * Invokes the function with args and if it is not ESR_SUCCESS, logs and 260 * returns it. 261 * 262 * @param rc Used to store the function return value 263 * @param function Function name 264 * @param args Function arguments 265 */ 266 #define PLOG_CHKRC_ARGS(rc, function, args) do { if((rc = (function args)) != ESR_SUCCESS) { PLogError(ESR_rc2str(rc)); return rc; } } while (0) 267 268 /** 269 * Checks the function return-code and if it is not ESR_SUCCESS, logs and 270 * returns it. 271 */ 272 #define PLOG_CHKRC(rc, function) do { rc = (function); if (rc != ESR_SUCCESS) { PLogError(rc); return rc; } } while (0) 273 274 #if defined(_DEBUG) && !defined(ENABLE_PLOG_TRACE) && ENABLE_STACKTRACE 275 #define ENABLE_PLOG_TRACE 276 #endif 277 278 /** 279 * Macro used to have logging enabled on debug build only. 280 */ 281 #ifdef ENABLE_PLOG_TRACE 282 283 #define PLOG_DBG_ERROR(msg) ((void) (PLogError msg)) 284 /** 285 * Usage: PLOG_DBG_TRACE((printf-arguments)) 286 * 287 * The reason we require double brackets is to allow the use of printf-style variable 288 * argument listings in a macro. 289 */ 290 #define PLOG_DBG_TRACE(args) ((void) (PLogMessage args)) 291 #define PLOG_DBG_BLOCK(block) block 292 #define PLOG_DBG_API_ENTER() \ 293 do \ 294 { \ 295 LCHAR text[P_MAX_FUNCTION_NAME]; \ 296 size_t len = P_MAX_FUNCTION_NAME; \ 297 ESR_ReturnCode rc; \ 298 \ 299 rc = PStackTraceGetFunctionName(text, &len); \ 300 if (rc==ESR_SUCCESS) \ 301 PLogMessage(L("%s entered."), text); \ 302 else if (rc!=ESR_NOT_SUPPORTED) \ 303 pfprintf(PSTDERR, L("[%s:%d] PStackTraceGetValue failed with %s\n"), __FILE__, __LINE__, ESR_rc2str(rc)); \ 304 } while (0) 305 306 #define PLOG_DBG_API_EXIT(rc) \ 307 \ 308 do \ 309 { \ 310 LCHAR text[P_MAX_FUNCTION_NAME]; \ 311 size_t len = P_MAX_FUNCTION_NAME; \ 312 ESR_ReturnCode rc2; \ 313 \ 314 rc2 = PStackTraceGetFunctionName(text, &len); \ 315 if (rc2==ESR_SUCCESS) \ 316 PLogMessage(L("%s returned %s"), text, ESR_rc2str(rc)); \ 317 else if (rc!=ESR_NOT_SUPPORTED) \ 318 pfprintf(PSTDERR, "[%s:%d] PStackTraceGetValue failed with %s\n", __FILE__, __LINE__, ESR_rc2str(rc2)); \ 319 } while (0) 320 321 #else 322 323 #ifndef DOXYGEN_SHOULD_SKIP_THIS 324 #define PLOG_DBG_ERROR(msg) ((void) 0) 325 #define PLOG_DBG_MODULE(name, logLevel) 326 #define PLOG_DBG_TRACE(args) ((void) 0) 327 #define PLOG_DBG_BLOCK(block) 328 #define PLOG_DBG_API_ENTER() ((void) 0) 329 #define PLOG_DBG_API_EXIT(rc) ((void) 0) 330 #endif /* DOXYGEN_SHOULD_SKIP_THIS */ 331 #endif /* ENABLE_PLOG_TRACE */ 332 333 /** 334 * @} 335 */ 336 337 338 #endif 339