aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-01-13 20:00:25 +0100
committerDavid Robillard <d@drobilla.net>2023-12-02 18:49:08 -0500
commit456bdeef35ffbfbdad7609e8b8a4ef71372786fd (patch)
tree25fabaa4f361f66a2bac860f06722e7f51776cbc /include
parentfc2114a10769349d38b3215bc95ded855a2be5b6 (diff)
downloadserd-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.h45
-rw-r--r--include/serd/log.h209
-rw-r--r--include/serd/serd.h2
-rw-r--r--include/serd/world.h12
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);
-
-/**
@}
*/