-
Notifications
You must be signed in to change notification settings - Fork 39
How to enable and capture VDB log messages
kdurbrow edited this page May 31, 2016
·
6 revisions
VDB has extensive and detailed logging capabilities that user code can both hook into and capture. This document will demonstrate how a c++ program using VDB might do this.
#include <iostream>
#include <string>
#include <stdexcept>
// _DEBUGGING is needed to turn on debugging messages
#define _DEBUGGING 1
#include <klib/log.h>
#include <klib/debug.h>
class VDBLog
{
void log(std::string const &message) {
std::cerr << message << std::endl;
}
static rc_t receive(void *, char const *, size_t, size_t *);
public:
/* version is XXYYZZZZ in hex; XX is major version, YY is minor version; ZZZZ is revision
* it is only informational
*
* logLevel sets the minimum severity for messages to be logged; it is defined in log.h:
* klogFatal fatal errors
* klogSys errors from the system
* klogInt internal software errors
* klogErr ordinary errors, generally related to inputs and data
* klogWarn non-errors which may indicate an unusual condition
* klogInfo non-errors, like progress or success messages
* klogDebug debugging message which are not removed in release code
*
* debugFlag is for turning on debug messages for a particular module. These messages are removed
* in release builds. This facility is extensive and extensible. The values are structured strings
* `module` or `module-condition`. Each module has its own set of condition codes; I won't document
* them here. See klib/debug.h for the complete of current values. The modules currently defined are:
* ALIGN generally concerning accessing of reference sequences
* KDB low-level database access
* KFG configuration
* KNS low-level network access
* KRYPTO crypto
* REF object lifetimes
* VDB high-level database access
* VFS high-level network and file access
*/
explicit VDBLog(char const program[], int version, int logLevel = klogErr, char const *debugFlag = 0);
~VDBLog();
};
static void doSomeVDBStuff(char const run[]); /// not implemented here; left as an exercise to the reader
int main(int argc, char *argv[])
{
VDBLog log(argv[0], 0x1000000, klogDebug, "VFS");
try {
doSomeVDBStuff("ERR1417836");
}
catch (std::exception const &e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
rc_t VDBLog::receive(void *p, const char *buffer, size_t size, size_t *written) {
VDBLog *const objp = static_cast<VDBLog *>(p);
std::string const &message = std::string(buffer, size - 1);
objp->log(message);
*written = size;
return 0;
}
VDBLog::VDBLog(const char program[], int version, int logLevel, const char *debugFlag)
{
rc_t rc = 0;
count[0] = count[1] = count[2] = count[3] = 0;
rc = KWrtInit(program, version);
if (rc) throw std::runtime_error("KWrtInit failed!");
// to receive log messages from the library
rc = KLogLibHandlerSet(VDBLog::receive, (void *)this);
if (rc) throw std::runtime_error("KLogLibHandlerSet failed!");
// to receive status messages from the library
rc = KStsHandlerSet(VDBLog::receive, (void *)this);
if (rc) throw std::runtime_error("KLogLibHandlerSet failed!");
// to receive log messages from user code; yes you can generate your own log messages!
// is not life grand!
rc = KLogHandlerSet(VDBLog::receive, (void *)this);
if (rc) throw std::runtime_error("KLogHandlerSet failed!");
// log severity level
rc = KLogLevelSet(logLevel);
if (rc) throw std::runtime_error("KLogLevelSet failed!");
if (debugFlag) {
// to receive debugging messages; this doesn't do anything in release code
rc = KDbgHandlerSet(VDBLog::receive, (void *)this);
if (rc) throw std::runtime_error("KDbgHandlerSet failed!");
// to turn on output from a particular module
// this can actually be called many times to turn on multiple modules/conditions
rc = KDbgSetString(debugFlag);
if (rc) throw std::runtime_error("KDbgSetString failed!");
}
}
VDBLog::~VDBLog(void)
{
KDbgHandlerSetStdErr();
KLogHandlerSetStdErr();
KLogLibHandlerSetStdErr();
KDbgHandlerSetStdErr();
}