Write man page for Log

This commit is contained in:
Jordan Bancino 2022-11-25 16:40:47 +00:00
parent 70bdf81df7
commit 8045c583ba
3 changed files with 159 additions and 101 deletions

View file

@ -36,7 +36,7 @@ Due: January 1, 2023
[ ] Http [ ] Http
[ ] HttpServer [ ] HttpServer
[ ] Json [ ] Json
[ ] Log [x] Log
[ ] Matrix [ ] Matrix
[x] Queue [x] Queue
[ ] Routes [ ] Routes

156
man/man3/Log.3 Normal file
View file

@ -0,0 +1,156 @@
.Dd $Mdocdate: November 25 2022 $
.Dt LOG 3
.Os Telodendria Project
.Sh NAME
.Nm Log
.Nd A simple logging framework for logging to files, standard output,
or the system log.
.Sh SYNOPSIS
.In Log.h
.Ft LogConfig *
.Fn LogConfigCreate "void"
.Ft void
.Fn LogConfigFree "LogConfig *"
.Ft void
.Fn LogConfigLevelSet "LogConfig *" "int"
.Ft void
.Fn LogConfigIndent "LogConfig *"
.Ft void
.Fn LogConfigUnindent "LogConfig *"
.Ft void
.Fn LogConfigIndentSet "LogConfig *" "size_t"
.Ft void
.Fn LogConfigOutputSet "LogConfig *" "FILE *"
.Ft void
.Fn LogConfigFlagSet "LogConfig *" "int"
.Ft void
.Fn LogConfigFlagClear "LogConfig *" "int"
.Ft void
.Fn LogConfigTimeStampFormatSet "LogConfig *" "char *"
.Ft void
.Fn Log "LogConfig *" "int" "const char *" "..."
.Sh DESCRIPTION
.Pp
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.
.Pp
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.
.Pp
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.
.Pp
.Fn LogConfigCreate
creates a new log configuration with sane defaults that can be used
immediately. Note that every call to
.Fn Log
requires a valid configuration pointer.
.Fn LogConfigFree
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
.Fn LogConfig*Set
functions manipulate the data pointed to by the pointer returned
by
.Fn LogConfigCreate .
.Pp
.Fn LogConfigLevelSet
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
.Fn Log
function. The passed log level should be one of the log levels
defined by
.Xr 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.
.Pp
.Fn LogConfigIndent
causes the output of
.Fn 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
.Fn LogConfigIndentSet ,
which allows the caller to specify an arbitrary indentation in
spaces.
.Fn LogConfigUnindent
does the exact opposite of
.Fn LogConfigIndent ;
it subtracts two spaces from the indentation level, unless there
is no indent, then it does nothing.
.Pp
.Fn LogConfigOutputSet
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.
.Pp
.Fn LogConfigFlagSet
and
.Fn LogConfigFlagClear
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:
.Bl -tag -width Ds
.It LOG_FLAG_COLOR
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.
.Xr isatty 3
is checked before writing ANSI sequences.
.It LOG_FLAG_SYSLOG
When enabled, log output to the syslog using
.Xr syslog 3 ,
instead of logging to the file set by
.Fn LogConfigOutputSet .
This flag always overrides the file stream set by that function,
regardless of when it was set.
.El
.Pp
.Fn LogConfigTimeStampFormatSet
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
.Xr strftime 3 .
A value of NULL disables outputting a timestamp before messages.
.Pp
The
.Fn Log
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.
.Pp
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
.Xr printf 3 .
.Sh RETURN VALUES
.Pp
.Fn 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
.Fn LogConfig*
functions should be used to manipulate it.
.Pp
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.

View file

@ -29,101 +29,26 @@
#include <stddef.h> #include <stddef.h>
#include <syslog.h> #include <syslog.h>
/* #define LOG_FLAG_COLOR (1 << 0)
* The possible flags that can be applied to alter the behavior of #define LOG_FLAG_SYSLOG (1 << 1)
* the logger.
*/
typedef enum LogFlag
{
LOG_FLAG_COLOR = (1 << 0), /* Enable color output on TTYs */
LOG_FLAG_SYSLOG = (1 << 1) /* Log to the syslog instead of a
* file */
} LogFlag;
/*
* The log configurations structure in which all settings exist.
* It's not super elegant to pass around a pointer to the logging
* configuration, but this really is the best way without having a
* global variable. It allows multiple loggers to exist if necessary,
* and makes things more thread safe.
*/
typedef struct LogConfig LogConfig; typedef struct LogConfig LogConfig;
/*
* Create a new log configuration on the heap. This will be passed to
* every Log() call after it is configured.
*
* Return: A pointer to a new LogConfig that can be configured and used
* for logging. It should have sane defaults; in other words, you should
* be able to immediately start logging with it.
*/
extern LogConfig * extern LogConfig *
LogConfigCreate(void); LogConfigCreate(void);
/*
* Free a log configuration. Future attempts to log with the passed
* configuration will fail in an undefined way, such as by hanging the
* process or segfaulting.
*
* Params:
*
* (LogConfig *) The configuration to free. All memory associated with
* configuring the logging mechanism will be
* invalidated.
*/
extern void extern void
LogConfigFree(LogConfig *); LogConfigFree(LogConfig *);
/*
* Set 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 ignored by the Log() function.
*
* Params:
*
* (LogConfig *) The log configuration to set the log level on.
* (int) The log level to set.
*/
extern void extern void
LogConfigLevelSet(LogConfig *, int); LogConfigLevelSet(LogConfig *, int);
/*
* Indent the log output by two spaces. This can be helpful in
* generating stack traces, or otherwise producing hierarchical output.
* After calling this function, all future log messages using this
* configuration will be indented.
*
* Params:
*
* (LogConfig *) The log configuration to indent.
*/
extern void extern void
LogConfigIndent(LogConfig *); LogConfigIndent(LogConfig *);
/*
* Decrease the log output indent by two spaces. This can be helpful in
* generating stack traces, or otherwise producing hierarchical output.
* After calling this function, all future log messages using this
* configuration will be unindented, unless there was no indentation
* to begin with; in that case, this function will do nothing.
*
* Params:
*
* (LogConfig *) The log configuration to unindent.
*/
extern void extern void
LogConfigUnindent(LogConfig *); LogConfigUnindent(LogConfig *);
/*
* Set the log output indent to an arbitrary amount. This can be helpful
* in generating stack traces, or otherwise producing hierarchical
* output. After calling this function, all future log messages using
* this configuration will be indented by the given amount.
*
* Params:
*
* (LogConfig *) The log configuration to apply the indent to.
*/
extern void extern void
LogConfigIndentSet(LogConfig *, size_t); LogConfigIndentSet(LogConfig *, size_t);
@ -139,29 +64,6 @@ extern void
extern void extern void
LogConfigTimeStampFormatSet(LogConfig *, char *); LogConfigTimeStampFormatSet(LogConfig *, char *);
/*
* Actually log a message to a console, file, or other output device,
* using the given log configuration. This function is thread-safe; it
* locks a mutex before writing a message, and then unlocks it after
* the message was written. It should therefore work well in
* multithreaded environments, and with multiple different log
* configurations, as each one has its own mutex.
*
* This function only logs messages if they are above the currently
* configured log level. In this way, it is easy to turn some messages
* on and off.
*
* This function is a printf() style function; it takes a format
* string and any number of parameters to format.
*
* Params:
*
* (LogConfig *) The logging configuration.
* (int) The level of the message to log.
* (const char *) The format string, or a plain message string.
* (...) Any items to map into the format string, printf()
* style.
*/
extern void extern void
Log(LogConfig *, int, const char *,...); Log(LogConfig *, int, const char *,...);