LOG(3) Library Functions Manual LOG(3)

LogA simple logging framework for logging to files, standard output, or the system log.

#include <Log.h>

LogConfig *

LogConfigFree(LogConfig *);

LogConfigLevelSet(LogConfig *, int);

LogConfigIndent(LogConfig *);

LogConfigUnindent(LogConfig *);

LogConfigIndentSet(LogConfig *, size_t);

LogConfigOutputSet(LogConfig *, FILE *);

LogConfigFlagSet(LogConfig *, int);

LogConfigFlagClear(LogConfig *, int);

LogConfigTimeStampFormatSet(LogConfig *, char *);

Log(LogConfig *, int, const char *, ...);

A heavily-modifed version of Shlog, a simple C logging library facility that allows for colorful outputs, timestamps, and custom log levels. This library differs from Shlog in that the naming conventions have been updated to be consistent with Telodendria, and system log support has been added.

Shlog was originally a learning project. It worked well and produced elegant logging output, so it was chosen to be the main logging mechanism of Telodendria. The original Shlog project is now dead; Shlog lives on now only as Telodendria's logging mechanism.

One of the design choices made in this library, which unfortunately makes code using it a little more verbose, is that multiple logging configurations can exist in a program. No global variables are used, and all functions are thread-safe.

() creates a new log configuration with sane defaults that can be used immediately. Note that every call to Log() requires a valid configuration pointer. () frees all memory associated with that configuration, invalidating it. Passing an invalid configuration pointer into any of the functions defined here result in undefined behavior. The () functions manipulate the data pointed to by the pointer returned by LogConfigCreate().

() sets the current log level on the specified log configuration. This indicates that only messages at or above this level should be logged; all other messages are silently discarded by the Log() function. The passed log level should be one of the log levels defined by syslog(3). Refer to that page for a complete list of acceptable log levels, and note that passing in an invalid or unknown log level will result in undefined behavior.

() causes the output of Log() to be indented two more spaces than it was previously. This can be helpful when generating stack traces, or otherwise producing hierarchical output. After calling this function, all future messages using the given config will be indented two more spaces than they were before. This is just a wrapper function around (), which allows the caller to specify an arbitrary indentation in spaces. () does the exact opposite of LogConfigIndent(); it subtracts two spaces from the indentation level, unless there is no indent, then it does nothing.

() sets the file stream that logging output should be written to. This defaults to standard output, but it can be standard error, or some other file stream. Passing a NULL value for the file pointer sets the log output to standard output. Note that the output file stream is only used if FLAG_OUTPUT_SYSLOG is not set.

() and () are used for setting a number of boolean options on a log configuration. They utilize bitwise operators, so multiple options can be set or cleared with a single function call using bitwise OR operators. The flags defined as preprocessor macros, and are as follows:

When set, enable color-coded output on TTYs. Note that colors are implemented as ANSI escape sequences, and are not written to file streams that are not actually connected to a TTY, to prevent those sequences from being written to a file. isatty(3) is checked before writing ANSI sequences.
When enabled, log output to the syslog using syslog(3), instead of logging to the file set by LogConfigOutputSet(). This flag always overrides the file stream set by that function, regardless of when it was set.

() allows a custom timestamp to be prepended to each message if the output is not going to the system log. Consult your system's documentation for strftime(3). A value of NULL disables outputting a timestamp before messages.

The () function actually writes a log message to a console, file, system log, or other supported output device using the given configuration. This function is thread-safe; it locks a mutex before writing a message, and then unlocks it after the message was written. Each log configuration has its own mutex, so this function can be used with mutiple active log configurations.

This function only logs messages if their level is above or equal to the currently configured log level, making it easy to turn some messages on or off. The function has the same usage as printf(3).

LogConfigCreate() returns a pointer to a configuration structure on the heap, or NULL if there was an error allocating memory for it. The returned structure is opaque to the caller; the LogConfig*() functions should be used to manipulate it.

All other functions do not return anything. They are simply assumed to always succeed. If any arguments are NULL, then the functions do nothing, unless otherwise specifically noted.

February 15, 2023 Telodendria Project