forked from lda/telodendria
Write man page for Log
This commit is contained in:
parent
70bdf81df7
commit
8045c583ba
3 changed files with 159 additions and 101 deletions
2
TODO.txt
2
TODO.txt
|
@ -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
156
man/man3/Log.3
Normal 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.
|
|
@ -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 *,...);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue