Home | History | Annotate | Download | only in include
      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