diff options
author | David Robillard <d@drobilla.net> | 2021-01-13 20:00:25 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-12-02 18:49:08 -0500 |
commit | 456bdeef35ffbfbdad7609e8b8a4ef71372786fd (patch) | |
tree | 25fabaa4f361f66a2bac860f06722e7f51776cbc /include | |
parent | fc2114a10769349d38b3215bc95ded855a2be5b6 (diff) | |
download | serd-456bdeef35ffbfbdad7609e8b8a4ef71372786fd.tar.gz serd-456bdeef35ffbfbdad7609e8b8a4ef71372786fd.tar.bz2 serd-456bdeef35ffbfbdad7609e8b8a4ef71372786fd.zip |
[WIP] Add extensible logging API
Diffstat (limited to 'include')
-rw-r--r-- | include/serd/error.h | 45 | ||||
-rw-r--r-- | include/serd/log.h | 209 | ||||
-rw-r--r-- | include/serd/serd.h | 2 | ||||
-rw-r--r-- | include/serd/world.h | 12 |
4 files changed, 210 insertions, 58 deletions
diff --git a/include/serd/error.h b/include/serd/error.h deleted file mode 100644 index 7051bd4f..00000000 --- a/include/serd/error.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2011-2022 David Robillard <d@drobilla.net> -// SPDX-License-Identifier: ISC - -#ifndef SERD_ERROR_H -#define SERD_ERROR_H - -#include "serd/attributes.h" -#include "serd/caret.h" -#include "serd/status.h" -#include "zix/attributes.h" - -#include <stdarg.h> - -SERD_BEGIN_DECLS - -/** - @defgroup serd_error Error reporting - @ingroup serd_errors - @{ -*/ - -/// An error description -typedef struct { - SerdStatus status; ///< Error code - const SerdCaret* ZIX_NULLABLE caret; ///< File origin of error - const char* ZIX_NONNULL fmt; ///< Printf-style format string - va_list* ZIX_NONNULL args; ///< Arguments for fmt -} SerdError; - -/** - Callback function to log errors. - - @param handle Handle for user data. - @param error Error description. -*/ -typedef SerdStatus (*SerdLogFunc)(void* ZIX_NULLABLE handle, - const SerdError* ZIX_NONNULL error); - -/** - @} -*/ - -SERD_END_DECLS - -#endif // SERD_ERROR_H diff --git a/include/serd/log.h b/include/serd/log.h new file mode 100644 index 00000000..a9261131 --- /dev/null +++ b/include/serd/log.h @@ -0,0 +1,209 @@ +// Copyright 2011-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#ifndef SERD_LOG_H +#define SERD_LOG_H + +#include "serd/attributes.h" +#include "serd/caret.h" +#include "serd/status.h" +#include "serd/string_view.h" +#include "serd/world.h" +#include "zix/attributes.h" + +#include <stdarg.h> +#include <stddef.h> + +SERD_BEGIN_DECLS + +/** + @defgroup serd_logging Logging + @ingroup serd_errors + @{ +*/ + +/// Log entry level, compatible with syslog +typedef enum { + SERD_LOG_LEVEL_EMERGENCY, ///< Emergency, system is unusable + SERD_LOG_LEVEL_ALERT, ///< Action must be taken immediately + SERD_LOG_LEVEL_CRITICAL, ///< Critical condition + SERD_LOG_LEVEL_ERROR, ///< Error + SERD_LOG_LEVEL_WARNING, ///< Warning + SERD_LOG_LEVEL_NOTICE, ///< Normal but significant condition + SERD_LOG_LEVEL_INFO, ///< Informational message + SERD_LOG_LEVEL_DEBUG, ///< Debug message +} SerdLogLevel; + +/** + A structured log field. + + Fields are used to add metadata to log messages. Syslog-compatible keys + should be used where possible, otherwise, keys should be namespaced to + prevent clashes. + + Serd itself uses the following keys: + + - ERRNO - The `errno` of the original system error if any (decimal string) + - SERD_COL - The 1-based column number in the file (decimal string) + - SERD_FILE - The file which caused this message (string) + - SERD_LINE - The 1-based line number in the file (decimal string) + - SERD_CHECK - The check/warning/etc that triggered this message (string) +*/ +typedef struct { + const char* ZIX_NONNULL key; ///< Field name + const char* ZIX_NONNULL value; ///< Field value +} SerdLogField; + +/** + Function for handling log messages. + + By default, the log is printed to `stderr`, but this can be overridden to + instead send log messages to a user function of this type. + + @param handle Pointer to opaque user data. + @param level Log level. + @param n_fields Number of entries in `fields`. + @param fields An array of `n_fields` extra log fields. + @param message Log message. +*/ +typedef SerdStatus (*SerdLogFunc)(void* ZIX_NULLABLE handle, + SerdLogLevel level, + size_t n_fields, + const SerdLogField* ZIX_NULLABLE fields, + SerdStringView message); + +/// A #SerdLogFunc that does nothing (for suppressing log output) +SERD_CONST_API SerdStatus +serd_quiet_log_func(void* ZIX_NULLABLE handle, + SerdLogLevel level, + size_t n_fields, + const SerdLogField* ZIX_NULLABLE fields, + SerdStringView message); + +/** + Set a function to be called with log messages (typically errors). + + If no custom logging function is set, then messages are printed to stderr. + + @param world World that will send log entries to the given function. + + @param log_func Log function to call for every log message. Each call to + this function represents a complete log message with an implicit trailing + newline. + + @param handle Opaque handle that will be passed to every invocation of + `log_func`. +*/ +SERD_API void +serd_set_log_func(SerdWorld* ZIX_NONNULL world, + SerdLogFunc ZIX_NULLABLE log_func, + void* ZIX_NULLABLE handle); + +/** + Write a message to the log with a `va_list`. + + This is the fundamental and most powerful function for writing entries to + the log, the others are convenience wrappers that ultimately call this. + + This writes a single complete entry to the log, and so may not be used to + print parts of a line like a more general printf-like function. There + should be no trailing newline in `fmt`. Arguments following `fmt` should + correspond to conversion specifiers in the format string as in printf from + the standard C library. + + @param world World to log to. + @param level Log level. + @param n_fields Number of entries in `fields`. + @param fields An array of `n_fields` extra log fields. + @param fmt Format string. + @param args Arguments for `fmt`. + + @return A status code, which is always #SERD_SUCCESS with the default log + function. If a custom log function is set with serd_set_log_func() and it + returns an error, then that error is returned here. +*/ +SERD_LOG_FUNC(5, 0) +SERD_API SerdStatus +serd_vxlogf(const SerdWorld* ZIX_NONNULL world, + SerdLogLevel level, + size_t n_fields, + const SerdLogField* ZIX_NULLABLE fields, + const char* ZIX_NONNULL fmt, + va_list args); + +/** + Write a message to the log with extra fields. + + This is a convenience wrapper for serd_vxlogf() that takes the format + arguments directly. +*/ +SERD_LOG_FUNC(5, 6) +SERD_API SerdStatus +serd_xlogf(const SerdWorld* ZIX_NONNULL world, + SerdLogLevel level, + size_t n_fields, + const SerdLogField* ZIX_NULLABLE fields, + const char* ZIX_NONNULL fmt, + ...); + +/** + Write a simple message to the log. + + This is a convenience wrapper for serd_vxlogf() which sets no extra fields. +*/ +SERD_LOG_FUNC(3, 0) +SERD_API SerdStatus +serd_vlogf(const SerdWorld* ZIX_NONNULL world, + SerdLogLevel level, + const char* ZIX_NONNULL fmt, + va_list args); + +/** + Write a simple message to the log. + + This is a convenience wrapper for serd_vlogf() that takes the format + arguments directly. +*/ +SERD_LOG_FUNC(3, 4) +SERD_API SerdStatus +serd_logf(const SerdWorld* ZIX_NONNULL world, + SerdLogLevel level, + const char* ZIX_NONNULL fmt, + ...); + +/** + Write a message to the log with a caret position. + + This is a convenience wrapper for serd_vxlogf() which sets `SERD_FILE`, + `SERD_LINE`, and `SERD_COL` to the position of the given caret. Entries are + typically printed with a GCC-style prefix like "file.ttl:16:4". +*/ +SERD_LOG_FUNC(4, 0) +SERD_API SerdStatus +serd_vlogf_at(const SerdWorld* ZIX_NONNULL world, + SerdLogLevel level, + const SerdCaret* ZIX_NULLABLE caret, + const char* ZIX_NONNULL fmt, + va_list args); + +/** + Write a message to the log with a caret position. + + This is a convenience wrapper for serd_vlogf_at() that takes the format + arguments directly. +*/ +SERD_LOG_FUNC(4, 5) +SERD_API SerdStatus +serd_logf_at(const SerdWorld* ZIX_NONNULL world, + SerdLogLevel level, + const SerdCaret* ZIX_NULLABLE caret, + const char* ZIX_NONNULL fmt, + ...); + +/** + @} +*/ + +SERD_END_DECLS + +#endif // SERD_LOG_H diff --git a/include/serd/serd.h b/include/serd/serd.h index 2b09eff2..6103c543 100644 --- a/include/serd/serd.h +++ b/include/serd/serd.h @@ -28,7 +28,7 @@ @{ */ -#include "serd/error.h" +#include "serd/log.h" #include "serd/status.h" /** diff --git a/include/serd/world.h b/include/serd/world.h index a950a1aa..9440e6eb 100644 --- a/include/serd/world.h +++ b/include/serd/world.h @@ -5,7 +5,6 @@ #define SERD_WORLD_H #include "serd/attributes.h" -#include "serd/error.h" #include "serd/node.h" #include "serd/status.h" #include "zix/attributes.h" @@ -73,17 +72,6 @@ SERD_API const SerdNode* ZIX_NONNULL serd_world_get_blank(SerdWorld* ZIX_NONNULL world); /** - Set a function to be called when errors occur. - - The `error_func` will be called with `handle` as its first argument. If - no error function is set, errors are printed to stderr. -*/ -SERD_API void -serd_world_set_error_func(SerdWorld* ZIX_NONNULL world, - SerdLogFunc ZIX_NULLABLE error_func, - void* ZIX_NULLABLE handle); - -/** @} */ |