logging.c File Reference

Implementation of logging routines. More...

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <ctype.h>
#include <sys/param.h>
#include "config.h"
#include "util.h"
#include "logging.h"
#include "path_utils.h"

Go to the source code of this file.

Defines

#define DEFAULT_LOG_FILEPATH   PKGLOGDIR "/" PACKAGE_NAME ".log"
 The default path name for our log file.

Functions

int log_init ()
 Initialize the logging subsystem.
int log_fini ()
 Close the logging subsystem, release resources.
int log_close ()
 Close the logging subsystem, release resources.
int log_close_file ()
 Close the log file, further log file write will be disabled.
int log_set_filepath (const char *path)
 Close existing log file, set the current path of the log file, potentially reopen.
int log_set_level (int level)
 Set the current logging level.
int log_to_console (bool flag)
 Set boolean flag indicating log messages should appear on the console.
int log_to_file (bool flag)
 Set boolean flag indicating log messages should be written to log file.
int log_set_show_level (bool show)
 Set boolean flag indicating if the logging level should appear in log messages.
int log_set_show_file (bool show)
 Set boolean flag indicating if the file name should appear in log messages.
int log_set_show_line (bool show)
 Set boolean flag indicating if the line number should appear in log messages.
int log_set_show_function (bool show)
 Set boolean flag indicating if the function name should appear in log messages.
int log_set_show_time (bool show)
 Set boolean flag indicating if a timestamp should appear in log messages.
int log_set_time_format (const char *format)
 Set the time format (as per strftime()) for log message timestamps.
void log_msg1 (int level, const char *file, int line, const char *function, const char *fmt,...)
 If not filtered by the log level format a log message and emit it on each enabled output stream.
int log_level_from_string (const char *level_str, int *level)
 Parse a log level in case insensitive manner, set variable to log level enumeration.

Variables

static char log_filepath [PATH_MAX] = DEFAULT_LOG_FILEPATH
 path name of log file
static int log_level = LOG_WARN
 current logging level
static bool log_to_console_flag = false
 boolean flag if log messages should be written to the console
static int log_console_fd = 1
 the file descriptor for console logging
static bool log_to_file_flag = true
 boolean flag if log messages should be written to the log file
static int log_file_fd = -1
 the file descriptor for log file logging
static char log_time_format [128] = ""
 strftime style format for timestamps
Flags for optional components in a log message
static bool show_level = false
 true if the log level appears in messages
static bool show_file = false
 true if the file name appears in messages
static bool show_line = false
 true if the line number appears in messages
static bool show_function = false
 true if the function name appears in messages
static bool show_time = false
 true if a timestamp appears in messages


Detailed Description

Implementation of logging routines.

Definition in file logging.c.


Define Documentation

#define DEFAULT_LOG_FILEPATH   PKGLOGDIR "/" PACKAGE_NAME ".log"

The default path name for our log file.

On the assumption the package name is "lwatch" this typically expands to: /var/log/lwatch/lwatch.log

Definition at line 42 of file logging.c.

Referenced by log_set_filepath().


Function Documentation

int log_close ( void   ) 

Close the logging subsystem, release resources.

Returns:
SUCCESS (0) or non-zero error code otherwise
Finalization consists of:
  • closing the log file
  • closing console output (if enabled)

Definition at line 140 of file logging.c.

Referenced by log_fini().

00141 {
00142     int error = SUCCESS;
00143 
00144     error = log_close_file();
00145     log_to_console(false);
00146     return error;
00147 }

int log_close_file ( void   ) 

Close the log file, further log file write will be disabled.

Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 154 of file logging.c.

Referenced by log_close().

00155 {
00156     int error = SUCCESS;
00157 
00158     if (log_file_fd >= 0) {
00159         if (close(log_file_fd) < 0) {
00160             error = errno;
00161         }
00162         log_file_fd = -1;
00163     }
00164     return error;
00165 }

int log_fini ( void   ) 

Close the logging subsystem, release resources.

Returns:
SUCCESS (0) or non-zero error code otherwise
Finalization consists of:
  • closing the log file
  • closing console output (if enabled)

See also:
log_close()

Definition at line 126 of file logging.c.

Referenced by main().

00127 {
00128     return log_close();
00129 }

int log_init ( void   ) 

Initialize the logging subsystem.

Returns:
SUCCESS (0) or non-zero error code otherwise
Initialization consists of:
  • set the default log file path and open that file

Definition at line 107 of file logging.c.

Referenced by main().

00108 {
00109     int error = SUCCESS;
00110 
00111     error = log_set_filepath(NULL);
00112     return error;
00113 }

int log_level_from_string ( const char *  level_str,
int *  level 
)

Parse a log level in case insensitive manner, set variable to log level enumeration.

Parameters:
[in] level_str Pointer to string containing log level, leading white space ignored
[out] level Pointer to variable to receive log level enumeration
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 451 of file logging.c.

Referenced by main().

00452 {
00453     const char *p;
00454 
00455     for (p = level_str; *p && isspace(*p); p++); /* skip white space */
00456     if (!*p) return EINVAL;
00457 
00458     if (strcasecmp("error", p) == 0) {
00459         *level = LOG_ERROR;
00460         return SUCCESS;
00461     }
00462 
00463     if ((strcasecmp("warn",    p) == 0) ||
00464         (strcasecmp("warning", p) == 0)) {
00465         *level = LOG_WARN;
00466         return SUCCESS;
00467     }
00468 
00469     if (strcasecmp("info", p) == 0) {
00470         *level = LOG_INFO;
00471         return SUCCESS;
00472     }
00473 
00474     if (strcasecmp("debug", p) == 0) {
00475         *level = LOG_DEBUG;
00476         return SUCCESS;
00477     }
00478 
00479     if (strcasecmp("verbose_debug", p) == 0) {
00480         *level = LOG_VERBOSE_DEBUG;
00481         return SUCCESS;
00482     }
00483 
00484     return EINVAL;
00485 }

void log_msg1 ( int  level,
const char *  file,
int  line,
const char *  function,
const char *  fmt,
  ... 
)

If not filtered by the log level format a log message and emit it on each enabled output stream.

Parameters:
[in] level The log level associated with this message
[in] file The source code file name
[in] line The line number in the source code file
[in] function The name of the containing function
[in] fmt The printf style format string
[in] ... Optional printf style arguments
Returns:
void
The sequence of operations is:
  1. Verify if the message would be emitted according the current logging level
  2. If any optional information will be emitted insert an opening bracket ("[") for it
  3. If displaying the log level is enabled insert the log level
  4. If displaying the file name is enabled insert the file name
  5. If displaying the line number is enabled insert the line number
  6. If displaying the function name is enabled insert the function name
  7. If displaying a timestamp is enabled insert the timestamp
  8. If any optional information was emitted insert a closing bracket ("]") for it
  9. Format the printf style arguments
  10. For each enabled output stream write the message

See also:
log_msg()

Definition at line 368 of file logging.c.

00369 {
00370     static __thread char buf[4096]; /* thread local static buffer */
00371     bool do_prefix;
00372     char *p, *buf_end;
00373     int msg_len;
00374     va_list ap;
00375 
00376     if (log_level < level) return;
00377 
00378     p = buf;                     /* current position in buffer */
00379     buf_end = &buf[sizeof(buf)]; /* non-inclusive end of buffer */
00380     *p = 0;
00381 
00382     do_prefix = show_level ||show_file || show_line || show_function || show_time;
00383     if (do_prefix) {
00384         p += snprintf(p, buf_end - p, "[");
00385         if (p >= buf_end) goto fail;
00386     }
00387 
00388     if (show_level) {
00389         switch(level) {
00390         case LOG_ERROR:         p += snprintf(p, buf_end - p, "ERROR ");         if (p >= buf_end) goto fail; break;
00391         case LOG_WARN:          p += snprintf(p, buf_end - p, "WARNING ");       if (p >= buf_end) goto fail; break;
00392         case LOG_INFO:          p += snprintf(p, buf_end - p, "INFO ");          if (p >= buf_end) goto fail; break;
00393         case LOG_DEBUG:         p += snprintf(p, buf_end - p, "DEBUG ");         if (p >= buf_end) goto fail; break;
00394         case LOG_VERBOSE_DEBUG: p += snprintf(p, buf_end - p, "VERBOSE_DEBUG "); if (p >= buf_end) goto fail; break;
00395         }
00396     }
00397 
00398     if (show_file) {
00399         p += snprintf(p, buf_end - p, "%s ", file);
00400         if (p >= buf_end) goto fail;
00401     }
00402 
00403     if (show_line) {
00404         if (show_file) p[-1] = ':';
00405         p += snprintf(p, buf_end - p, "%d ", line);
00406         if (p >= buf_end) goto fail;
00407     }
00408 
00409     if (show_function) {
00410         p += snprintf(p, buf_end - p, "%s() ", function);
00411         if (p >= buf_end) goto fail;
00412     }
00413 
00414     if (show_time) {
00415         p += snprintf(p, buf_end - p, "%s ", time_string(time(NULL), true, log_time_format[0] ? log_time_format : NULL));
00416         if (p >= buf_end) goto fail;
00417     }
00418 
00419     if (do_prefix) {
00420         p--;                    /* remove trailing space in prefix */
00421         p += snprintf(p, buf_end - p, "] ");
00422         if (p >= buf_end) goto fail;
00423     }
00424 
00425     va_start(ap, fmt);
00426     if (fmt) {
00427         p += vsnprintf(p, buf_end - p, fmt, ap);
00428         if (p >= buf_end) goto fail;
00429     }
00430 
00431     msg_len = p - buf;
00432  output:
00433     if (log_to_console_flag && log_console_fd >= 0) write(log_console_fd, buf, msg_len);
00434     if (log_to_file_flag    && log_file_fd    >= 0) write(log_file_fd,    buf, msg_len);
00435     return;
00436 
00437  fail:
00438     /* exhausted the buffer; NULL terminate then output truncated string */
00439     buf_end[-1] = 0;   /* should already be NULL terminated, but be safe */
00440     msg_len = buf_end - buf;
00441     goto output;
00442 }

int log_set_filepath ( const char *  path  ) 

Close existing log file, set the current path of the log file, potentially reopen.

Parameters:
[in] path The new path name of the log file, if NULL use default log file
Returns:
SUCCESS (0) or non-zero error code otherwise
The sequence of operations is:
  1. Close current log file if open
  2. Set new log file path (if path param is NULL use default)
  3. If logging to a file is enabled open newly set file

See also:
DEFAULT_LOG_FILEPATH

Definition at line 180 of file logging.c.

Referenced by log_init(), and main().

00181 {
00182     int error = SUCCESS;
00183 
00184     if (log_file_fd >= 0) {
00185         close(log_file_fd);
00186         log_file_fd = -1;
00187     }
00188 
00189     if (path) {
00190         if ((error = copy_path(log_filepath, path, sizeof(log_filepath))) != SUCCESS) {
00191             log_msg(LOG_ERROR, _("failed to copy path \"%s\" (%s)\n"), path, error_string(error));
00192             return error;
00193         }
00194     } else {
00195         if ((error = copy_path(log_filepath, DEFAULT_LOG_FILEPATH, sizeof(log_filepath))) != SUCCESS) {
00196             log_msg(LOG_ERROR, _("failed to copy path \"%s\" (%s)\n"), DEFAULT_LOG_FILEPATH, error_string(error));
00197             return error;
00198         }
00199     }
00200 
00201     if (log_to_file_flag) {
00202         log_file_fd = open(log_filepath, O_WRONLY | O_CREAT | O_TRUNC, 0664);
00203         error = errno;
00204     }
00205 
00206     return error;
00207 }

int log_set_level ( int  level  ) 

Set the current logging level.

Parameters:
[in] level The new logging level
Returns:
SUCCESS (0) or non-zero error code otherwise
See also:
LOG_ERROR

LOG_WARN

LOG_INFO

LOG_DEBUG

LOG_VERBOSE_DEBUG

Definition at line 221 of file logging.c.

Referenced by main().

00222 {
00223     switch(level) {
00224     case LOG_ERROR:
00225     case LOG_WARN:
00226     case LOG_INFO:
00227         log_level = level;
00228         return SUCCESS;
00229     case LOG_DEBUG:
00230     case LOG_VERBOSE_DEBUG:
00231         log_level = level;
00232         debug = 1;
00233         return SUCCESS;
00234    default:
00235         return EINVAL;
00236     }
00237 }

int log_set_show_file ( bool  show  ) 

Set boolean flag indicating if the file name should appear in log messages.

Parameters:
[in] show True if the the file name should appear in log messages, false otherwise
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 281 of file logging.c.

Referenced by main().

00282 {
00283     show_file = show;
00284     return SUCCESS;
00285 }

int log_set_show_function ( bool  show  ) 

Set boolean flag indicating if the function name should appear in log messages.

Parameters:
[in] show True if the function name should appear in log messages, false otherwise
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 305 of file logging.c.

Referenced by main().

00306 {
00307     show_function = show;
00308     return SUCCESS;
00309 }

int log_set_show_level ( bool  show  ) 

Set boolean flag indicating if the logging level should appear in log messages.

Parameters:
[in] show True if the logging level should appear in log messages, false otherwise
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 269 of file logging.c.

Referenced by main().

00270 {
00271     show_level = show;
00272     return SUCCESS;
00273 }

int log_set_show_line ( bool  show  ) 

Set boolean flag indicating if the line number should appear in log messages.

Parameters:
[in] show True if the line number should appear in log messages, false otherwise
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 293 of file logging.c.

Referenced by main().

00294 {
00295     show_line = show;
00296     return SUCCESS;
00297 }

int log_set_show_time ( bool  show  ) 

Set boolean flag indicating if a timestamp should appear in log messages.

Parameters:
[in] show True if a timestamp should appear in log messages, false otherwise
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 317 of file logging.c.

Referenced by main().

00318 {
00319     show_time = show;
00320     return SUCCESS;
00321 }

int log_set_time_format ( const char *  format  ) 

Set the time format (as per strftime()) for log message timestamps.

Parameters:
[in] format The strftime() style time format string
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 329 of file logging.c.

00330 {
00331     int error;
00332 
00333     error = SUCCESS;
00334     strncpy(log_time_format, format, sizeof(log_time_format));
00335     if (format[sizeof(log_time_format) - 1] != 0) {
00336         error = ENOBUFS;
00337         log_msg(LOG_ERROR, _("failed to fully copy time format \"%s\" (%s)\n"), format, error_string(error));
00338     }
00339     return error;
00340 }

int log_to_console ( bool  flag  ) 

Set boolean flag indicating log messages should appear on the console.

Parameters:
[in] flag True if log messages should appear on the console, false otherwise.
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 245 of file logging.c.

Referenced by log_close(), and main().

00246 {
00247     log_to_console_flag = flag;
00248     return SUCCESS;
00249 }

int log_to_file ( bool  flag  ) 

Set boolean flag indicating log messages should be written to log file.

Parameters:
[in] flag True if log messages should be written to log file, false otherwise.
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 257 of file logging.c.

Referenced by main().

00258 {
00259     log_to_file_flag = flag;
00260     return SUCCESS;
00261 }


Generated on Mon Aug 31 10:06:21 2009 by  doxygen 1.5.8