Data Structures | Defines | Functions | Variables

Logger.h File Reference

Logger is a general purpose logging system for events, simulation, errors, etc. More...

#include <stdio.h>
#include <stdarg.h>

Go to the source code of this file.

Data Structures

struct  LoggerVersion
 Struct that contains the version information of this library. More...
class  Logger
 The Logger struct should be considered as your typical opaque datatype. More...

Defines

#define LOGGER_GET_COMPILED_VERSION(X)
 This macro fills in a Logger_Version structure with the version of the library you compiled against.

Functions

void Logger_GetLinkedVersion (LoggerVersion *ver)
 Gets the library version of Logger you are using.
int Logger_IsCompiledWithLocking ()
 Returns true if the library version of logger you are using was compiled with locking enabled.
LoggerLogger_Create ()
 This creates a new logger instance.
LoggerLogger_CreateWithName (const char *base_name)
 This creates a new logger instance connected to a file with the specified basename.
LoggerLogger_CreateWithHandle (FILE *file_handle, const char *base_name)
 This creates a new logger instance connected to a preopened file handle.
void Logger_Free (Logger *logger)
 This frees a logger instance.
int Logger_SetHandle (Logger *logger, FILE *file_handle, const char *base_name)
 This sets the file handle in an already created Logger instance.
int Logger_LogEvent (Logger *logger, unsigned int priority, const char *keyword, const char *subkeyword, const char *text,...)
 This is the function that actually does the logging.
int Logger_LogEventv (Logger *logger, unsigned int priority, const char *keyword, const char *subkeyword, const char *text, va_list argp)
 This is the va_list version of Logger_LogEvent.
int Logger_LogEventNoFormat (Logger *logger, unsigned int priority, const char *keyword, const char *subkeyword, const char *text)
 This is a "No Format Strings Allowed" version of LogEvent.
void Logger_Enable (Logger *logger)
 Enables logging output.
void Logger_Disable (Logger *logger)
 Disables logging output.
int Logger_IsEnabled (Logger *logger)
 Returns true if logger is enabled.
void Logger_Flush (Logger *logger)
 Flushes the file stream buffer.
void Logger_EnableAutoFlush (Logger *logger)
 Enables flushing of the buffers after every LogEvent.
void Logger_DisableAutoFlush (Logger *logger)
 Disables flushing of the buffers after every LogEvent.
int Logger_IsAutoFlushEnabled (Logger *logger)
 Returns true if autoflush is enabled.
void Logger_SetThresholdPriority (Logger *logger, unsigned int thresh_val)
 Sets the threshold priority.
unsigned int Logger_GetThresholdPriority (Logger *logger)
 Gets the currently set threshold value.
void Logger_SetDefaultPriority (Logger *logger, unsigned int pri_level)
 Sets the level that Priority=0 gets mapped to.
unsigned int Logger_GetDefaultPriority (Logger *logger)
 Gets the currently set default priority.
void Logger_SetMinSegmentSize (Logger *logger, unsigned int num_bytes)
 Set the target size for how large a file may be before segmenting.
unsigned int Logger_GetMinSegmentSize (Logger *logger)
 Gets the minimum segment size.
void Logger_EchoOn (Logger *logger)
 Enables echoing (to terminal).
void Logger_EchoOff (Logger *logger)
 Disables echoing.
int Logger_IsEchoOn (Logger *logger)
 Returns true if Echo On is enabled.
void Logger_SetEchoToStdout (Logger *logger)
 If echo is on, this will echo the output to be written to stdout.
void Logger_SetEchoToStderr (Logger *logger)
 If echo is on, this will echo the output to be written to stderr.
void Logger_SetPreLines (Logger *logger, unsigned int pre_lines)
 This sets the number of blank lines preceding a log entry.
void Logger_SetPostLines (Logger *logger, unsigned int post_lines)
 This sets the number of blank lines succeeding a log entry.
void Logger_SetNewLines (Logger *logger, unsigned int pre_lines, unsigned int post_lines)
 Sets the number of blank lines preceding a log entry and after a log entry.
unsigned int Logger_GetPreLines (Logger *logger)
 Gets the number of prelines.
unsigned int Logger_GetPostLines (Logger *logger)
 Gets the number of postlines.
int Logger_WillLog (Logger *logger, unsigned int which_priority)
 Returns true if logger will print with the specified priority.
void Logger_SetSegmentFormatString (Logger *logger, const char *format_string)
 Sets the format string that is used to create the segment file extensions.

Variables

Loggerg_logger
 A global instance pointer of logger.

Detailed Description

Logger is a general purpose logging system for events, simulation, errors, etc.

It provides a standard formated output to allow for easy parsing (for automation). It also allows the for the filtering of log entries (by priority) and the easy redirection of where the output goes (file, stdout, stderr). Logger also provides a segmentation feature which will auto-split the logs if the files grow beyond a specified size.

The output format is:

 YYYY-MM-DD_HH:MM:SS.mmm    Keyword:    Subkeyword:    PRI=n
 User text goes here.
 Could be multiple lines.
 END:

Sample Usage:

 Logger* logger = Logger_Create("myoutput.log");
 Logger_LogEvent(logger, 5, "Error", "SDL_image::SDL_glLoadImage",
                "Error found: %s", SDL_GetError());
 Logger_Free(logger);

Sample Output:

 2002-10-29_19:59:32.321    Error:    SDL_image::SDL_glLoadImage():    PRI=5
 Error found: Error in SDL_GLhelper. Unsupported bit depth(=2)
 END:
Note:
This is a C adaptation of a version of my logging system written in C++ which was an adaptation from one I wrote in Perl. This version attempts to provide (very) basic thread safety if the define's are enabled. It will lock logger member variables when accessed and lock the output file when writing to. The user must still ensure that the strings and other data passed into logger are properly locked. There is also currently no safety for creating and/or destroying instances of Logger while trying to use it, so don't create or destroy when there is possible contention. Further optimization probably could be achieved by providing finer grain locks and smarter locking procedures.
Warning:
Logger internal error reporting sucks (which is somewhat ironic). I currently either silently fail or print directly to stderr. I might want to do a string based method, but would need to make it thread safe. This means I would need to create a map that placed a different error message in a different thread. Of course, that requires more work as the thread APIs are not universal. Perhaps returning an error number with a system that converts the error number would be easier, but gets hard to deal with when return values are already being used.
Author:
Eric Wing

Define Documentation

#define LOGGER_GET_COMPILED_VERSION (   X )
Value:
{                                                                                       \
        if(NULL != (X))                                                 \
        {                                                                               \
                (X)->major = LOGGER_MAJOR_VERSION;      \
                (X)->minor = LOGGER_MINOR_VERSION;      \
                (X)->patch = LOGGER_PATCH_VERSION;      \
        }                                                                               \
}

This macro fills in a Logger_Version structure with the version of the library you compiled against.

This is determined by what header the compiler uses. Note that if you dynamically linked the library, you might have a slightly newer or older version at runtime. That version can be determined with Logger_GetLinkedVersion(), which, unlike LOGGER_GET_COMPILED_VERSION, is not a macro.

Parameters:
XA pointer to a Logger_Version struct to initialize.
See also:
LoggerVersion, Logger_GetLinkedVersion

Function Documentation

Logger* Logger_Create (  )

This creates a new logger instance.

This will create a new logger instance. All the logger values will be set to the defaults. Currently the defaults are:

  • fileHandle = stdout
  • echoOn = false
  • echoHandle = NULL
  • minSegmentBytes = 0
  • thresholdPriority = 1
  • defaultPriority = 5
  • preNewLines = 0
  • postNewLines = 1
  • loggingEnabled = 1
  • autoFlushEnabled = 0

If you want to log to an actual file, you may be better off calling Logger_CreateWithName or Logger_CreateWithHandle.

Returns:
Returns a pointer to a Logger struct which is the instance variable (if successful) or NULL on failure.
See also:
Logger_CreateWithName, Logger_CreateWithHandle
Logger* Logger_CreateWithHandle ( FILE *  file_handle,
const char *  base_name 
)

This creates a new logger instance connected to a preopened file handle.

This creates a new logger instance connected to a preopened file handle. In general, you should not use the file handle for anything else after you pass it to Logger. Logger will attempt to manage the file handle and will close the file when segmentation or destruction occurs.

Parameters:
file_handleA preopened file handle you want logger to log to. This may alse be stdout or stderr.
base_nameThe file name associated with the file handle you supply. This information is needed by logger so it can determine what to name the segmented parts if segmentation occurs. Passing a base_name like MyLog.log would result in the system in creating a MyLog.log.0001 if segmentation occured. Do not pass in NULL unless you are using stdout or stderr. (Use Logger_Create() instead.) If you must use this function and if you don't have a file name for some reason, just put in a fake name and make sure segmentation is off.

The logger instance will get make its own copy of the string so you are free to do what you will with your string.

Returns:
Returns a pointer to a Logger struct which is the instance variable (if successful) or NULL on failure.
See also:
Logger_Create, Logger_CreateWithName, Logger_Free
Logger* Logger_CreateWithName ( const char *  base_name )

This creates a new logger instance connected to a file with the specified basename.

This creates a new logger instance with a log file by the specified basename. The basename would be something like "Mylog.log". The system will segment the logs if you specify a segment size. The segments will take the name "Mylog.log.0001", etc. If the file already exists, this function will try to overwrite it.

Parameters:
base_nameThe file name you want for the starting log file. Do not pass in NULL. (Use Logger_Create() instead.) The logger instance will get make its own copy of the string so you are free to do what you will with your string.
Returns:
Returns a pointer to a Logger struct which is the instance variable (if successful) or NULL on failure.
See also:
Logger_Create, Logger_CreateWithHandle, Logger_Free
void Logger_Disable ( Logger logger )

Disables logging output.

This will disable logging output so events not are reported.

Parameters:
loggerThe pointer to the logger instance.
void Logger_DisableAutoFlush ( Logger logger )

Disables flushing of the buffers after every LogEvent.

This will allow the system to decide when a stream gets written. This will generally give better performance, but if there is a system crash, the last events to be recorded may not get written. By default, autoflush is disabled.

Parameters:
loggerThe pointer to the logger instance.
void Logger_EchoOff ( Logger logger )

Disables echoing.

This will disable echoing to the echo handle. By default, echo is off.

Parameters:
loggerThe pointer to the logger instance.
void Logger_EchoOn ( Logger logger )

Enables echoing (to terminal).

This will enable echoing to the echo handle. Typically when you use this feature, you will want the file handle to be reporting to a file, and you would echo to stdout or stderr. By default, echo is off.

Parameters:
loggerThe pointer to the logger instance.
void Logger_Enable ( Logger logger )

Enables logging output.

This will enable logging output so events are reported. By default this is on.

Parameters:
loggerThe pointer to the logger instance.
void Logger_EnableAutoFlush ( Logger logger )

Enables flushing of the buffers after every LogEvent.

This will call fflush() on the file handle after every LogEvent. This will make sure that data is recorded immediately, with all the usual side effects associated with calling fflush(). By default, autoflush is disabled.

Parameters:
loggerThe pointer to the logger instance.
void Logger_Flush ( Logger logger )

Flushes the file stream buffer.

This will call fflush on the current stream buffers.

Parameters:
loggerThe pointer to the logger instance.
void Logger_Free ( Logger logger )

This frees a logger instance.

This properly frees the memory of a logger instance created by the Logger_Create*() family of functions. Whenever you create a Logger instance, you should always remember to balance it with a Logger_Free() call.

Parameters:
loggerA pointer to the logger instance you want to free.
See also:
Logger_Create, Logger_CreateWithName, Logger_CreateWithHandle, Logger_Free
unsigned int Logger_GetDefaultPriority ( Logger logger )

Gets the currently set default priority.

This returns the current default priority.

Parameters:
loggerThe pointer to the logger instance.
Returns:
Returns the current default priority.
See also:
Logger_SetDefaultPriority
void Logger_GetLinkedVersion ( LoggerVersion ver )

Gets the library version of Logger you are using.

This gets the version of Logger that is linked against your program. If you are using a shared library (DLL) version of Logger, then it is possible that it will be different than the version you compiled against.

This is a real function; the macro LOGGER_GET_COMPILED_VERSION tells you what version of Logger you compiled against:

 LoggerVersion compiled;
 LoggerVersion linked;

 LOGGER_GET_COMPILED_VERSION(&compiled);
 Logger_GetLinkedVersion(&linked);
 printf("We compiled against Logger version %d.%d.%d ...\n",
           compiled.major, compiled.minor, compiled.patch);
 printf("But we linked against Logger version %d.%d.%d.\n",
           linked.major, linked.minor, linked.patch);
See also:
LoggerVersion, LOGGER_GET_COMPILED_VERSION
unsigned int Logger_GetMinSegmentSize ( Logger logger )

Gets the minimum segment size.

This returns the minimum size (in bytes) that is needed before a log will be segmented.

Parameters:
loggerThe pointer to the logger instance.
Returns:
Returns the minimum size (in bytes) that is needed before a log will be segmented.
See also:
Logger_SetMinSegmentSize
unsigned int Logger_GetPostLines ( Logger logger )

Gets the number of postlines.

This returns the currently set number of postlines.

Parameters:
loggerThe pointer to the logger instance.
Returns:
Returns the currently set number of postlines.
See also:
Logger_SetPostLines, Logger_SetNewLines
unsigned int Logger_GetPreLines ( Logger logger )

Gets the number of prelines.

This returns the currently set number of prelines.

Parameters:
loggerThe pointer to the logger instance.
Returns:
Returns the currently set number of prelines.
See also:
Logger_SetPreLines, Logger_SetNewLines
unsigned int Logger_GetThresholdPriority ( Logger logger )

Gets the currently set threshold value.

This returns the current threshold value.

Parameters:
loggerThe pointer to the logger instance.
Returns:
Returns the current threshold priority.
See also:
Logger_SetThresholdPriority
int Logger_IsAutoFlushEnabled ( Logger logger )

Returns true if autoflush is enabled.

Returns 1 or 0 if autoflush is enabled or disabled.

Parameters:
loggerThe pointer to the logger instance.
Returns:
Returns 1 if enabled, 0 if disabled.
See also:
Logger_EnableAutoFlush, Logger_DisableAutoFlush
int Logger_IsCompiledWithLocking (  )

Returns true if the library version of logger you are using was compiled with locking enabled.

If the library is compiled with locking enabled, then most functions will lock the logger instances while in use and lock the file handles when appriopriate to provide some basic thread safety. This currently does not lock files for multiple processes.

Returns:
Returns 1 if compiled with locking enabled. 0 if not.
int Logger_IsEchoOn ( Logger logger )

Returns true if Echo On is enabled.

Returns 1 if echo is on or 0 if echo is off.

Parameters:
loggerThe pointer to the logger instance.
Returns:
Returns 1 if enabled, 0 if disabled.
See also:
Logger_EchoOn, Logger_EchoOff
int Logger_IsEnabled ( Logger logger )

Returns true if logger is enabled.

Returns 1 or 0 if logger is enabled or disabled.

Parameters:
loggerThe pointer to the logger instance.
Returns:
Returns 1 if enabled, 0 if disabled.
See also:
Logger_Enable, Logger_Disable
int Logger_LogEvent ( Logger logger,
unsigned int  priority,
const char *  keyword,
const char *  subkeyword,
const char *  text,
  ... 
)

This is the function that actually does the logging.

This function writes the actual log entries. The function usage is similar to fprintf (it actually calls fprintf), but you have a few extra arguments to pass.

Parameters:
loggerThe logger instance you want to log with.
priorityThe priority allows the entry to be filtered by threshold. Higher numbers are higher priority. If the priority is higher than the logger's current threshold, the message will be printed 1 = lowest (least important) Highest will be determined by your team's conventions. For SClone, 5 = highest. Priority 0 is a special value. 0 will automatically get remapped to the logger's current Default Priorty. This gives you a little flexibilty if you want to be able to reassign a priority level later.
keywordThe keyword is the first identifying string to help classification. The keyword is intended to help automated tools in their parsing of logs. Your team should decide on a good convention for keywords. Logger will always append a colon after the keyword. My recommendation (though not required) is that keywords are always exactly one word with no spaces. Alpha-numeric is the best thing you can do. This helps make logs easy to parse.
subkeywordLike the keyword, the subkeyword is another identifier string to help you classify events. Once again, it is up to your team to decide on a good set of subkeywords. Single word, alphanumeric format is recommended. A colon will always be appended to the keyword.
textThis is where your message text goes. It is compatible with printf style format strings. There is no imposed limit on how long the strings can be or what the format of your message should be. The only constraint is that you should never have an END: on it's own line as this is the marker that Logger uses to denote the end of a log event. (Parsing tools and people could get confused.)
...This is the variable argument list used to accomodate printf style format strings.
Returns:
Returns the number of bytes written to the log. This conforms with fprintf.
See also:
Logger_SetThresholdPriority, Logger_SetDefaultPriority, Logger_LogEventv, Logger_LogEventNoFormat
int Logger_LogEventNoFormat ( Logger logger,
unsigned int  priority,
const char *  keyword,
const char *  subkeyword,
const char *  text 
)

This is a "No Format Strings Allowed" version of LogEvent.

This version of LogEvent disallows the use of format strings. This was written if you needed to expose the LogEvent function to an untrusted source because it is quite easy to crash a system (or worse) with an invalid format string. An untrusted source might include arguments passed through the command line, any user input that gets fed to Logger, or strings taken from runtime generated sources like scripts. I was probably being overly paranoid when I created this function, and there may be ways to achive this level of safety without this function, but here it is anyway. This function has nothing to do with format strings related to segmentation.

See also:
Logger_LogEvent
int Logger_LogEventv ( Logger logger,
unsigned int  priority,
const char *  keyword,
const char *  subkeyword,
const char *  text,
va_list  argp 
)

This is the va_list version of Logger_LogEvent.

This is the va_list version of Logger_LogEvent in the case that you need it. The same rules apply to this as with Logger_LogEvent.

See also:
Logger_LogEvent
void Logger_SetDefaultPriority ( Logger logger,
unsigned int  pri_level 
)

Sets the level that Priority=0 gets mapped to.

This will treat any entries in LogEvent called with Priority 0, as whatever you enter for this value (Default = 5) So by default, if you enter 0 as the priority to LogEvent, the message will be treated as if you had entered priority=5.

Parameters:
loggerThe pointer to the logger instance.
pri_levelThe priority level you want 0-values to be mapped to. If you set it to 0, it will reset the priorty to the default value.
void Logger_SetEchoToStderr ( Logger logger )

If echo is on, this will echo the output to be written to stderr.

If the file handle is also set to stderr, you will see the message appear twice in the stdout stream.

Parameters:
loggerThe pointer to the logger instance.
See also:
Logger_EchoOn, Logger_EchoOff, Logger_SetEchoToStdout
void Logger_SetEchoToStdout ( Logger logger )

If echo is on, this will echo the output to be written to stdout.

If the file handle is also set to stdout, you will see the message appear twice in the stdout stream. This is the default echo handle.

Parameters:
loggerThe pointer to the logger instance.
See also:
Logger_EchoOn, Logger_EchoOff, Logger_SetEchoToStderr
int Logger_SetHandle ( Logger logger,
FILE *  file_handle,
const char *  base_name 
)

This sets the file handle in an already created Logger instance.

This will set the file handle for logging in a precreated Logger instance. This is provided as a convenience in case for some reason that you needed to allocate a logger first without a file, and later need to set the file. You may also use this to set the handle to stdout or stderr. Changing a file handle after the first logging message has been sent is not encouraged. It may or may not work. You need to be careful about the old file. Logger will attempt to close the old file before switching. You need to be careful, particularly with threads.

Parameters:
loggerThe pointer to the logger instance.
file_handleA preopened file handle you want logger to log to. This may also be stdout or stderr.
base_nameThe file name associated with the file handle you supply. This information is needed by logger so it can determine what to name the segmented parts if segmentation occurs. Passing a base_name like MyLog.log would result in the system in creating a MyLog.log.0001 if segmentation occured. Do not pass in NULL unless you are using stdout or stderr. If you don't have a file name for some reason, put in a fake name and make sure segmentation is off. The logger instance will get make its own copy of the string so you are free to do what you will with your string.
Returns:
Returns 1 on success or 0 on error (e.g. memory allocation failure).
See also:
Logger_Create, Logger_CreateWithName, Logger_CreateWithHandle
void Logger_SetMinSegmentSize ( Logger logger,
unsigned int  num_bytes 
)

Set the target size for how large a file may be before segmenting.

Logger will close the current file and create a new one after the number of bytes written for the file exceeds this number of bytes. This is a soft limit. A log entry will not be divided between logs. So any segmentation will occur after a log entry is complete.

Parameters:
loggerThe pointer to the logger instance.
num_bytesThe number of bytes a file needs before segmenting. The number 0 will disable the segmentation feature. 0 is the default.
void Logger_SetNewLines ( Logger logger,
unsigned int  pre_lines,
unsigned int  post_lines 
)

Sets the number of blank lines preceding a log entry and after a log entry.

This is a convenience function that allows you to set the number of pre_lines and post_lines in the same call.

Parameters:
loggerThe pointer to the logger instance.
pre_linesThe number of newlines to print before each log entry.
post_linesThe number of newlines to print after each log entry.
See also:
Logger_SetPreLines, Logger_SetPostLines
void Logger_SetPostLines ( Logger logger,
unsigned int  post_lines 
)

This sets the number of blank lines succeeding a log entry.

This is the number of newlines that will be printed right after a log entry. The default is 1.

Parameters:
loggerThe pointer to the logger instance.
post_linesThe number of newlines to print after each log entry.
void Logger_SetPreLines ( Logger logger,
unsigned int  pre_lines 
)

This sets the number of blank lines preceding a log entry.

This is the number of newlines that will be printed right before a log entry. The default is 0.

Parameters:
loggerThe pointer to the logger instance.
pre_linesThe number of newlines to print before each log entry.
void Logger_SetSegmentFormatString ( Logger logger,
const char *  format_string 
)

Sets the format string that is used to create the segment file extensions.

When segmentation occurs, a new file must be created. The scheme is to take the base file name and append a numeric value represening the current segment number (starting with 0).

The default format is ".%04d".

This will produce files like Mylog.log, Mylog.log.0000, Mylog.log.0001, etc.

Notice that the period is specified in that format string, so if you want something else in the segment, you may specify it.

You must have a d somewhere in the format string. The underlying implementation uses a snprintf(target, fmtstr, seg_number, maxsize), so an integer will try to be inserted into the string.

You should also never change the format string after LogEvent* has been called, (i.e. don't change the file name schemes after segmentation may have begun). While this may actually work, it's not something that was really thought about and won't be supported.

In general, you should be very careful when using this function.

This function will make it's own internal copy of the string you pass in, so you may do what you want with your string after this call.

Parameters:
loggerThe pointer to the logger instance.
format_stringThe format string (the kind used in the printf family). NULL will reset the logger instance to use the default format.
void Logger_SetThresholdPriority ( Logger logger,
unsigned int  thresh_val 
)

Sets the threshold priority.

This will set the threshold priority which all priority values are compared with to determine what gets printed. Logger only prints entries with Priority >= Threshold Priority The default threshold = 1

Parameters:
loggerThe pointer to the logger instance.
thresh_valThe threshold value you desire. If you set it to 0, it will reset the threshold to the default value.
int Logger_WillLog ( Logger logger,
unsigned int  which_priority 
)

Returns true if logger will print with the specified priority.

This is a convenience function that will tell you if the priorty you submit will pass the threshold test. If the test passes, it means a log event with that priorty would be printed.

Parameters:
loggerThe pointer to the logger instance.
which_priorityThe priorty level you want to know if it will print.
Returns:
Returns 1 if the priority you specified would pass the threshold test and be logged. Returns 0 if it would not be printed.
See also:
Logger_SetThresholdPriority, Logger_GetThresholdPriority

Variable Documentation

A global instance pointer of logger.

Allow for a global instance of Logger so everybody can use simply by including include "Logger.h" and defining in the global scope somewhere (like before main()). Don't forget to call Create to actually create the instance.

 All Data Structures Files Functions Variables Defines