From 8045c583ba08b5dac3a191fc0eb595583dd8a8ab Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Fri, 25 Nov 2022 16:40:47 +0000 Subject: [PATCH] Write man page for Log --- TODO.txt | 2 +- man/man3/Log.3 | 156 ++++++++++++++++++++++++++++++++++++++++++++++ src/include/Log.h | 102 +----------------------------- 3 files changed, 159 insertions(+), 101 deletions(-) create mode 100644 man/man3/Log.3 diff --git a/TODO.txt b/TODO.txt index 9e13b54..e87788e 100644 --- a/TODO.txt +++ b/TODO.txt @@ -36,7 +36,7 @@ Due: January 1, 2023 [ ] Http [ ] HttpServer [ ] Json - [ ] Log + [x] Log [ ] Matrix [x] Queue [ ] Routes diff --git a/man/man3/Log.3 b/man/man3/Log.3 new file mode 100644 index 0000000..2740e3d --- /dev/null +++ b/man/man3/Log.3 @@ -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. diff --git a/src/include/Log.h b/src/include/Log.h index d99540e..42874e2 100644 --- a/src/include/Log.h +++ b/src/include/Log.h @@ -29,101 +29,26 @@ #include #include -/* - * The possible flags that can be applied to alter the behavior of - * 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; +#define LOG_FLAG_COLOR (1 << 0) +#define LOG_FLAG_SYSLOG (1 << 1) -/* - * 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; -/* - * 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 * 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 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 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 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 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 LogConfigIndentSet(LogConfig *, size_t); @@ -139,29 +64,6 @@ extern void extern void 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 Log(LogConfig *, int, const char *,...);