edelib logging

This tutorial will show you how to log common values and how to write custom loging backend.

Introduction

edelib use logging facility similar to Qt and glib implementations, but simplified a little bit. However, this doesn't make it less flexible.

Three macros are provided for this task:

  • E_DEBUG - should be used for debug messages
  • E_WARNING - is for warnings user should be aware of
  • E_FATAL - fatal errors where program will probably end up in inconsistent state

:!: E_FATAL will also call abort() which will quit your program.

All macros provide printf-like functionality, so you are able to use custom placeholders. Also, internal buffer where message is stored is limited on 1024 bytes, so any message larger than this will be discarded to this size.

If the program was compiled with 'E_LOG_DOMAIN' flag set, output will have domain name so you can easily deduce from which application the message is coming. Here is the small demo program that will show usage of given features; we will call it logger.cpp:

/* logger.cpp */
 
#include <edelib/Debug.h>  /* all logging facility is here */
 
int main() {
  int n = 1;
  E_DEBUG("This is %i time you are calling this program.\n", n);
 
  return 0;
}

and you compile it and run it:

> g++ logger.cpp -o logger `pkg-config edelib --cflags --libs`
> ./logger
This is 1 time you are calling this program.
>

By adding log domain, you can see from which place you are receiving the message:

> g++ -DE_LOG_DOMAIN=\"logger\" logger.cpp -o logger `pkg-config edelib --cflags --libs`
> ./logger
[logger] This is 1 time you are calling this program.
>

:!: When you setup E_LOG_DOMAIN value, you must add escaped quotes; this value is used as C string.

If you use E_WARNING instead of E_DEBUG you will get the same output. By default, edelib shows warnings and debug messages in the same way. However, if your program wants to show it differently, or you are going to store output in some file (or syslog) read bellow.

Locating log lines

Sometimes you want to see from which file (and line) log string came. edelib provides convinient macro for this, named E_STRLOC, which expands to __FILE__ and __LINE__ hints. Here is example how it can be used (including program name set with E_LOG_DOMAIN):

  // ...
  E_DEBUG(E_STRLOC ": this is debug output with line and file where is written\n");
  // ...

and the output will look like:

> ./your-program
[your-program] somepath/Source.cpp:10: this is debug output with line and file where is written

Custom output

With 'edelib_error_message_handler_install()' you install custom handler (or callback): all output will be redirected to given function with message type, domain and content.

(!) All debug functionality is compiled as C code so this can be used from C programs too. This is why above function starts with edelib_ and is not part of edelib:: C++ namespace.

Here is small example how this feature can be used to log messages via syslog:

#include <edelib/Debug.h>
#include <syslog.h>
 
static void syslog_logger(int type, const char *domain, const char *msg) {
  int pr;
  const char *str;
 
  switch(type) {
    case EDELIB_ERROR_MESSAGE_WARNING:
      pr = LOG_WARNING;
      str = "warning";
      break;
    case EDELIB_ERROR_MESSAGE_FATAL:
      pr = LOG_CRIT;
      str = "fatal";
      break;
    case EDELIB_ERROR_MESSAGE_DEBUG:
    default:
      pr = LOG_INFO;
      str = "debug";
      break;
  }
 
  if(domain)
    syslog(pr, "[%s] (%s) %s", domain, str, msg);
  else
    syslog(pr, "(%s) %s", str, msg);
}
 
int main(int argc, char **argv) {
  /* open the log first */
  setlogmask(LOG_UPTO (LOG_INFO));
  openlog("sample-app", LOG_CONS | LOG_PID, LOG_USER);
  edelib_error_message_handler_install(syslog_logger);
 
  /* ... your application code ... */
 
  /* close the log when is done */
  closelog();
  return 0;
}

Now all messages, warning and errors will be logged in /var/log/messages, or whatever syslog output file is configured on your system.

Print/export