/*---------------------------------------------------------------------------*
* plog.h *
* *
* Copyright 2007, 2008 Nuance Communciations, Inc. *
* *
* Licensed under the Apache License, Version 2.0 (the 'License'); *
* you may not use this file except in compliance with the License. *
* *
* You may obtain a copy of the License at *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an 'AS IS' BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* *
*---------------------------------------------------------------------------*/
#ifndef PLOG_H
#define PLOG_H
#include "ESR_ReturnCode.h"
#include "PortPrefix.h"
#ifdef USE_STACKTRACE
#include "PStackTrace.h"
#endif
#include "passert.h"
#include "PFileSystem.h"
#include "ptypes.h"
/**
* @addtogroup PLogModule PLogger API functions
* Logging API.
*
* Must call pmemInit() before using this module.
*
* The logging API is composed of a Logger.
* A Logger is an object who implements an API to actually write log messages.
* The logging API uses the logger when logging is to be performed but does
* not depend on an actual implementation of this API.
*
* When a request for logging is performed, the current level of the logging
* API is compared with the current stack-trace level. If the logger's log
* level is greater than or equal to the stack-trace level, then the
* message is being logged through the use of the Logger. Otherwise, the
* message is not logged. Setting the log level of the API to UINT_MAX is
* equivalent to unconditionally log all messages from all modules. Conversely,
* setting the log level of the API to 0 is equivalent to disabling logging globally.
*
* @{
*/
/**
* Portable logging framework.
*/
typedef struct PLogger_t
{
/**
* Prints and formats a message to the log.
*
* @param self the Logger.
*
* @param format the format string specifying the next arguments (a la
* printf).
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error.
*/
ESR_ReturnCode(*printf)(struct PLogger_t *self,
const LCHAR *format, ...);
/**
* Flushes internal buffer. This function can be left unimplemented if no
* buffering is performed by the logger.
* @param self the Logger
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the nature of the error.
*/
ESR_ReturnCode(*flush)(struct PLogger_t *self);
/**
* Destroys the logger. This function is responsible to deallocate any
* resources used by the logger. In particular, if buffering is internally
* used, it needs to flush the buffer.
*/
void(*destroy)(struct PLogger_t *self);
}
PLogger;
/**
* Type used to control output format.
*/
typedef asr_uint16_t LOG_OUTPUT_FORMAT;
/**
* Specifies that no extra information is to be output.
*/
#define LOG_OUTPUT_FORMAT_NONE 0x0000
/**
* Specifies that the date and time is to be output.
*/
#define LOG_OUTPUT_FORMAT_DATE_TIME 0x0001
/**
* Specifies that thread id of thread generating the message is to be output.
*/
#define LOG_OUTPUT_FORMAT_THREAD_ID 0x0002
/**
* Specifies that the module name of the module generating the message is to
* be output.
*/
#define LOG_OUTPUT_FORMAT_MODULE_NAME 0x0004
/**
* Initializes the LOG library. This function must be called before any
* logging can take place. PtrdInit() must be called before this function on
* platforms that support threads.
*
* @param logger The logger to be used to output the messages. If NULL, then
* logging goes to PSTDERR.
*
* @param logLevel The level of logging requested.
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error. In particular, it returns ESR_INVALID_STATE if already
* initialized.
*/
PORTABLE_API ESR_ReturnCode PLogInit(PLogger *logger, unsigned int logLevel);
/**
* Indicates if PLog module is initialized.
*
* @param isInit True if module is initialized
* @return ESR_INVALID_ARGUMENT if isLocked is null
*/
PORTABLE_API ESR_ReturnCode PLogIsInitialized(ESR_BOOL* isInit);
/**
* Indicates if PLog module is locked inside a critical section. This is for internal use only.
*
* @param isLocked True if module is locked
* @return ESR_INVALID_ARGUMENT if isLocked is null
*/
PORTABLE_API ESR_ReturnCode PLogIsLocked(ESR_BOOL* isLocked);
/**
* Shutdowns the LOG library. Once this function is called, no logging
* activity can be performed.
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error. In particular, it returns ESR_INVALID_STATE if not
* initialized or already shutted down.
*/
PORTABLE_API ESR_ReturnCode PLogShutdown(void);
/**
* Sets the format of the logging messages. If this function is never called,
* the default format is
*
* <code>LOG_OUTPUT_FORMAT_MODULE_NAME | LOG_OUTPUT_FORMAT_DATE_TIME</code>.
*
* @param format the format specification for new messages.
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error.
*/
PORTABLE_API ESR_ReturnCode PLogSetFormat(LOG_OUTPUT_FORMAT format);
/**
* Gets the current log level of the LOG API.
*
* @param logLevel A pointer to where the log level is to be stored. If NULL,
* the function returns ESR_INVALID_ARGUMENT.
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error. In particular, it returns ESR_INVALID_STATE if the
* API is not initialized.
*/
PORTABLE_API ESR_ReturnCode PLogGetLevel(unsigned int *logLevel);
/**
* Sets the current log level of the LOG API.
*
* @param logLevel The new log level.
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error. In particular, it returns ESR_INVALID_STATE if the
* API is not initialized.
*/
PORTABLE_API ESR_ReturnCode PLogSetLevel(unsigned int logLevel);
/**
* Conditionally Logs a message. The message is logged only if module is enabled.
*
* @param msg The message format specification (ala printf).
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error. In particular, it returns ESR_INVALID_STATE if
* the API is not initialized.
*/
PORTABLE_API ESR_ReturnCode PLogMessage(const LCHAR* msg, ...);
/**
* Unconditionally logs an error message.
*
* @param msg The message format specification (ala printf).
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error. In particular, it returns ESR_INVALID_STATE if
* the API is not initialized.
*/
PORTABLE_API ESR_ReturnCode PLogError(const LCHAR* msg, ...);
/**
*
* Creates a logger that logs to a file.
*
* @param file The file to log to.
* @param logger logger handle receiving the created logger.
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error.
*/
PORTABLE_API ESR_ReturnCode PLogCreateFileLogger(PFile* file,
PLogger** logger);
/**
* Creates a logger that logs to a circular file.
*
* @param filename The name of the file to be created.
* @param maxsize The maximum number of bytes that the file may have.
* @param logger logger handle receiving the created logger.
*
* @return ESR_SUCCESS if success, otherwise a status code indicating the
* nature of the error.
*/
PORTABLE_API ESR_ReturnCode PLogCreateCircularFileLogger(const LCHAR* filename,
unsigned int maxsize,
PLogger** logger);
/**
* Runs a function, checks its return-code. In case of an error, logs it and jumps to
* the CLEANUP label.
*/
/* show more information for vxworks due to lack of stack trace */
#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)
/**
* Invokes the function with args and if it is not ESR_SUCCESS, logs and
* returns it.
*
* @param rc Used to store the function return value
* @param function Function name
* @param args Function arguments
*/
#define PLOG_CHKRC_ARGS(rc, function, args) do { if((rc = (function args)) != ESR_SUCCESS) { PLogError(ESR_rc2str(rc)); return rc; } } while (0)
/**
* Checks the function return-code and if it is not ESR_SUCCESS, logs and
* returns it.
*/
#define PLOG_CHKRC(rc, function) do { rc = (function); if (rc != ESR_SUCCESS) { PLogError(rc); return rc; } } while (0)
#if defined(_DEBUG) && !defined(ENABLE_PLOG_TRACE) && ENABLE_STACKTRACE
#define ENABLE_PLOG_TRACE
#endif
/**
* Macro used to have logging enabled on debug build only.
*/
#ifdef ENABLE_PLOG_TRACE
#define PLOG_DBG_ERROR(msg) ((void) (PLogError msg))
/**
* Usage: PLOG_DBG_TRACE((printf-arguments))
*
* The reason we require double brackets is to allow the use of printf-style variable
* argument listings in a macro.
*/
#define PLOG_DBG_TRACE(args) ((void) (PLogMessage args))
#define PLOG_DBG_BLOCK(block) block
#define PLOG_DBG_API_ENTER() \
do \
{ \
LCHAR text[P_MAX_FUNCTION_NAME]; \
size_t len = P_MAX_FUNCTION_NAME; \
ESR_ReturnCode rc; \
\
rc = PStackTraceGetFunctionName(text, &len); \
if (rc==ESR_SUCCESS) \
PLogMessage(L("%s entered."), text); \
else if (rc!=ESR_NOT_SUPPORTED) \
pfprintf(PSTDERR, L("[%s:%d] PStackTraceGetValue failed with %s\n"), __FILE__, __LINE__, ESR_rc2str(rc)); \
} while (0)
#define PLOG_DBG_API_EXIT(rc) \
\
do \
{ \
LCHAR text[P_MAX_FUNCTION_NAME]; \
size_t len = P_MAX_FUNCTION_NAME; \
ESR_ReturnCode rc2; \
\
rc2 = PStackTraceGetFunctionName(text, &len); \
if (rc2==ESR_SUCCESS) \
PLogMessage(L("%s returned %s"), text, ESR_rc2str(rc)); \
else if (rc!=ESR_NOT_SUPPORTED) \
pfprintf(PSTDERR, "[%s:%d] PStackTraceGetValue failed with %s\n", __FILE__, __LINE__, ESR_rc2str(rc2)); \
} while (0)
#else
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#define PLOG_DBG_ERROR(msg) ((void) 0)
#define PLOG_DBG_MODULE(name, logLevel)
#define PLOG_DBG_TRACE(args) ((void) 0)
#define PLOG_DBG_BLOCK(block)
#define PLOG_DBG_API_ENTER() ((void) 0)
#define PLOG_DBG_API_EXIT(rc) ((void) 0)
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
#endif /* ENABLE_PLOG_TRACE */
/**
* @}
*/
#endif