Your application can include logging of important Toolkit activity. The ability to provide activity logs in an external file is helpful for debugging, troubleshooting, performance-tuning and as a history-maintenance tool for Toolkit users. Logging functions record specific Toolkit actions and any errors that are encountered.
By default, logging information is stored in an ASCII text file that can be viewed with any text editor.
You can also customize logging to take advantage of any existing logging capabilities in your application, for example you may want to write log messages to a database or to the system log facilities.
Toolkit stores several types of log records which are also use indicate logging levels. Toolkit functions store these types of log records:
Error logs--display any encountered error or warning.
Information logs--provide description and status of key Toolkit activities.
Debug logs--provides information which usually accompanies an error message for example the value of some variables when an error occurred or information about each successfully called function.
Validation logs--provide data that is either request data sent to a VA or response data received from a VA.
Specifying a level of logging turns on the levels below it, for example if you specify Debug logs, Debug, Information, and Error logs will be recorded.
Code Samples For Adding Logging
The following code sample demonstrates how to use the default Toolkit logging functionality in your application
/* * InitLog * * Initializing and starting logging activity in application */ Vtk_uint32 InitLog(Vtk_Ctxt *pCtxt) { Vtk_LogOptions logOpts; Vtk_uint32 ret; /* * Default Toolkit Logging * Initialize logging options structure: * Log Level - log all error, info, debug and validation messages * Log Mode - overwrite old log file, no flushing after each message * Log File Name - use default log file name (vc_toolkit.log) */ logOpts.logLevel = LOG_VaData; logOpts.logMode = VTK_LOG_MODE_DEFAULT | VTK_LOG_MODE_OVERWRITE; logOpts.logFileName.type = VTK_DF_STRING; logOpts.logFileName.dPtr = NULL; logOpts.logFileName.len = 0; logOpts.openLogCB = NULL; logOpts.closeLogCB = NULL; logOpts.writeLogCB = NULL; /* * Open Log */ if ((ret = Vtk_OpenLog(pCtxt, &logOpts)) != VTK_OK) showError("InitLog", ret); /* * IMPORTANT * * From now on until the function Vtk_CloseLog is called, all * Toolkit messages (error, info, debug, validation) will be logged * into text file vc_toolkit.log * * Application should call Vtk_CloseLog function to stop logging * */ return ret; }
The following code sample demonstrates how an application can provide an alternate way to process logging messages. In this example error, info and debug messages are written in the file messages.log, while validation data (VA requests and responses) are written in the file va_data.log.
/* * Logging structure */ typedef struct { FILE *pMsgFile; /* file stream for error, info and debug messages */ FILE *pVaDataFile; /* file stream for validation data */ } MyLogInfo; /* * InitLog * * Initializing and starting logging activity in application */ Vtk_uint32 InitLog(Vtk_Ctxt *pCtxt) { Vtk_LogOptions logOpts; Vtk_uint32 ret; /* * Alternative Toolkit Logging * Initialize logging options structure: * Log Level - log all error, info, debug and validation messages * Set callback functions */ logOpts.logLevel = LOG_VaData; logOpts.logMode = VTK_LOG_MODE_DEFAULT; logOpts.logFileName.type = VTK_DF_STRING; logOpts.logFileName.dPtr = NULL; logOpts.logFileName.len = 0; logOpts.openLogCB = MyOpenLog; logOpts.closeLogCB = MyCloseLog; logOpts.writeLogCB = MyWriteLog; /* Open Log */ if ((ret = Vtk_OpenLog(pCtxt, &logOpts)) != VTK_OK) showError("InitLog", ret); /* * IMPORTANT * * From now on until the function Vtk_CloseLog is called, all * Toolkit messages (error, info, debug, validation) will be logged * in log files ( as defined in MyWriteLog callback function ) * * Application must call Vtk_CloseLog function to stop logging and * release alocated resources * */ return ret; } /* * MyOpenLog * * Callback function for initializing the alternative logging */ Vtk_uint32 VTK_CALLBACK MyOpenLog(const Vtk_Ctxt *pCtxt, void **userHdl) { MyLogInfo *pLogInfo; *userHdl = NULL; /* * Allocate memory for alternative logging structure */ if ((pLogInfo = (MyLogInfo *) malloc(sizeof(MyLogInfo))) == NULL) return VTK_ERR_OUT_OF_MEMORY; /* * Init MyLogInfo structure with pointers to file streams */ if ((pLogInfo->pMsgFile = (FILE *)fopen("messages.log", "w")) == NULL) { free(pLogInfo); return VTK_ERR_OPEN_LOG_FILE; } if ((pLogInfo->pVaDataFile = (FILE *)fopen("va_data.log", "w")) == NULL) { fclose(pLogInfo->pMsgFile); free(pLogInfo); return VTK_ERR_OPEN_LOG_FILE; } /* * Pass pointer to application's logging structure in userHdl variable */ *userHdl = pLogInfo; return VTK_OK; } /* * MyCloseLog * * Callback function for closing the alternative logging */ void VTK_CALLBACK MyCloseLog(const Vtk_Ctxt *pCtxt, void* userHdl) { MyLogInfo *pLogInfo; if (!userHdl) return; /* * Write final logging message */ Vtk_WriteLog(pCtxt, LOG_Info, "Closing log files ..."); /* * Close both log file streams */ pLogInfo = (MyLogInfo *) userHdl; fclose(pLogInfo->pMsgFile); fclose(pLogInfo->pVaDataFile); /* * Release memory allocated for MyLogInfo structure */ free(pLogInfo); return; } /* * MyWriteLog * * Callback function for alternative processing (storing) of logging messages */ void VTK_CALLBACK MyWriteLog(const Vtk_Ctxt *pCtxt, enum Vtk_CtxtLogType type, const char *pMsg, void* userHdl) { struct tm *tmptr; struct timeb timebuffer; MyLogInfo *pLogInfo; char typeStr[5] = " "; if (!userHdl) return; pLogInfo = (MyLogInfo *) userHdl; /* * Set mesage type prefix */ if (type == LOG_Error) strcpy(typeStr, "ERR"); else if (type == LOG_Info) strcpy(typeStr, "INF"); else if (type == LOG_Debug) strcpy(typeStr, "DBG"); else if (type == LOG_VaData) strcpy(typeStr, "VAD"); /* * Get current time */ ftime( &timebuffer ); tmptr = localtime(&(timebuffer.time)); if (type == LOG_Error || type == LOG_Info || type == LOG_Debug) fprintf(pLogInfo->pMsgFile, "%04d/%02d/%02d %02d:%02d:%02d.%03hu %s: %s\n", tmptr->tm_year+1900, tmptr->tm_mon+1, tmptr->tm_mday, tmptr->tm_hour, tmptr->tm_min, tmptr->tm_sec, timebuffer.millitm, typeStr, pMsg); else fprintf(pLogInfo->pVaDataFile, "%04d/%02d/%02d %02d:%02d:%02d.%03hu %s: %s\n", tmptr->tm_year+1900, tmptr->tm_mon+1, tmptr->tm_mday, tmptr->tm_hour, tmptr->tm_min, tmptr->tm_sec, timebuffer.millitm, typeStr, pMsg); return; }