separate with attrs

This commit is contained in:
tavo 2025-09-30 09:42:31 -06:00
parent a74a5863c7
commit 855d24da67
4 changed files with 90 additions and 63 deletions

View file

@ -8,11 +8,18 @@ Single-header structured logger in C99
... ...
struct SlogLogger logger = SLOG_DEFAULT_TEXT_LOGGER; struct SlogLogger logger = SLOG_DEFAULT_TEXT_LOGGER;
SLOG_DEBUG(&logger, "will not appear");
// Dropped, the default text logger has .Opts.MinLevel = SlogLevelInfo
SLOG_INFO(&logger, "hello from minimal.c");
// The default text logger's output file is stdout:
// time=2025-09-29T17:46:49.409721457-06:00 level=INFO msg=hello from minimal.c
struct SlogAttr attrs[] = { struct SlogAttr attrs[] = {
SlogAttrB("ok", true), SlogAttrB("ok", true),
}; };
SLOG_INFO(&logger, "hello", attrs); // or: SLOG_DEBUG, SLOG_WARN, SLOG_ERROR SLOG_INFO_ATTRS(&logger, "hello", attrs);
// time=2025-09-29T17:46:49.409721457-06:00 level=INFO msg=hello ok=true // time=2025-09-29T17:46:49.409721457-06:00 level=INFO msg=hello ok=true
... ...
``` ```
@ -25,44 +32,44 @@ Single-header structured logger in C99
int main(void) int main(void)
{ {
struct SlogHandlerOpts opts1 = { struct SlogHandlerOpts opts1 = {
.File = stdout, .File = stdout,
.MinLevel = SlogLevelDebug, .MinLevel = SlogLevelDebug,
.Prefix = NULL, .Prefix = NULL,
.AddSource = true, .AddSource = true,
.Json = false, .Json = false,
}; };
struct SlogLogger l1 = { struct SlogLogger l1 = {
SlogTextHandler, SlogTextHandler,
&opts1, opts1,
}; };
struct SlogHandlerOpts opts2 = { struct SlogHandlerOpts opts2 = {
.File = stderr, .File = stderr,
.MinLevel = SlogLevelError, .MinLevel = SlogLevelError,
.Prefix = "scope", .Prefix = "scope",
.AddSource = true, .AddSource = false,
.Json = true, .Json = true,
}; };
struct SlogLogger l2 = { struct SlogLogger l2 = {
SlogTextHandler, SlogTextHandler,
&opts2, opts2,
}; };
struct SlogAttr attrs[] = { struct SlogAttr attrs[] = {
SlogAttrB("ok", true), SlogAttrB("ok", true),
}; };
SLOG_DEBUG(&l1, "hello", attrs); SLOG_INFO_ATTRS(&l1, "hello", attrs);
// Written to stdout: // stdout:
// time=2025-09-29T17:36:08.597673657-06:00 level=INFO msg=hello source=tests/slog.c:36 func=main ok=true // time=2025-09-30T09:38:32.607139416-06:00 level=INFO msg=hello source=tests/slog.c:36 func=main ok=true
SLOG_ERROR(&l2, "hello", attrs); SLOG_ERROR(&l2, "hello");
// Written to stderr: // stderr:
//time=2025-09-29T17:36:08.597771088-06:00 level=ERROR msg=hello scope.source=tests/slog.c:37 scope.func=main scope.ok=true // time=2025-09-30T09:38:32.607139416-06:00 level=INFO msg=hello
return 0; return 0;
} }
``` ```

View file

@ -458,40 +458,52 @@ static inline void SlogTextHandler(struct SlogLogger *self, SlogLevel level,
#define SLOG_ATTR_COUNT(ATTRS) \ #define SLOG_ATTR_COUNT(ATTRS) \
((ATTRS) == NULL ? 0 : sizeof(ATTRS) / sizeof((ATTRS)[0])) ((ATTRS) == NULL ? 0 : sizeof(ATTRS) / sizeof((ATTRS)[0]))
#define SLOG_DEBUG(LOGGER_PTR, MSG, ATTRS) \ #define SLOG_DEBUG(LOGGER_PTR, MSG) \
SLOG_CALL((LOGGER_PTR), SlogLevelDebug, (MSG), NULL, 0, (&SLOG_SOURCE))
#define SLOG_INFO(LOGGER_PTR, MSG) \
SLOG_CALL((LOGGER_PTR), SlogLevelInfo, (MSG), NULL, 0, (&SLOG_SOURCE))
#define SLOG_WARN(LOGGER_PTR, MSG) \
SLOG_CALL((LOGGER_PTR), SlogLevelWarn, (MSG), NULL, 0, (&SLOG_SOURCE))
#define SLOG_ERROR(LOGGER_PTR, MSG) \
SLOG_CALL((LOGGER_PTR), SlogLevelError, (MSG), NULL, 0, (&SLOG_SOURCE))
#define SLOG_DEBUG_ATTRS(LOGGER_PTR, MSG, ATTRS) \
SLOG_CALL((LOGGER_PTR), SlogLevelDebug, (MSG), (ATTRS), \ SLOG_CALL((LOGGER_PTR), SlogLevelDebug, (MSG), (ATTRS), \
(SLOG_ATTR_COUNT(ATTRS)), (&SLOG_SOURCE)) (SLOG_ATTR_COUNT(ATTRS)), (&SLOG_SOURCE))
#define SLOG_INFO(LOGGER_PTR, MSG, ATTRS) \ #define SLOG_INFO_ATTRS(LOGGER_PTR, MSG, ATTRS) \
SLOG_CALL((LOGGER_PTR), SlogLevelInfo, (MSG), (ATTRS), \ SLOG_CALL((LOGGER_PTR), SlogLevelInfo, (MSG), (ATTRS), \
(SLOG_ATTR_COUNT(ATTRS)), (&SLOG_SOURCE)) (SLOG_ATTR_COUNT(ATTRS)), (&SLOG_SOURCE))
#define SLOG_WARN(LOGGER_PTR, MSG, ATTRS) \ #define SLOG_WARN_ATTRS(LOGGER_PTR, MSG, ATTRS) \
SLOG_CALL((LOGGER_PTR), SlogLevelWarn, (MSG), (ATTRS), \ SLOG_CALL((LOGGER_PTR), SlogLevelWarn, (MSG), (ATTRS), \
(SLOG_ATTR_COUNT(ATTRS)), (&SLOG_SOURCE)) (SLOG_ATTR_COUNT(ATTRS)), (&SLOG_SOURCE))
#define SLOG_ERROR(LOGGER_PTR, MSG, ATTRS) \ #define SLOG_ERROR_ATTRS(LOGGER_PTR, MSG, ATTRS) \
SLOG_CALL((LOGGER_PTR), SlogLevelError, (MSG), (ATTRS), \ SLOG_CALL((LOGGER_PTR), SlogLevelError, (MSG), (ATTRS), \
(SLOG_ATTR_COUNT(ATTRS)), (&SLOG_SOURCE)) (SLOG_ATTR_COUNT(ATTRS)), (&SLOG_SOURCE))
#define SLOG_DEFAULT_TEXT_LOGGER \ #define SLOG_DEFAULT_TEXT_LOGGER \
(SlogLogger) \ (SlogLogger) \
{ \ { \
.Handler = SlogTextHandler, .Opts = (SlogHandlerOpts) \ .Handler = SlogTextHandler, .Opts = (SlogHandlerOpts) \
{ \ { \
.File = stdout, .Prefix = NULL, .AddSource = false, \ .File = stdout, .MinLevel = SlogLevelInfo, \
.Json = false \ .Prefix = NULL, .AddSource = false, .Json = false \
} \ } \
} }
#define SLOG_DEFAULT_JSON_LOGGER \ #define SLOG_DEFAULT_JSON_LOGGER \
(SlogLogger) \ (SlogLogger) \
{ \ { \
.Handler = SlogTextHandler, .Opts = (SlogHandlerOpts) \ .Handler = SlogTextHandler, .Opts = (SlogHandlerOpts) \
{ \ { \
.File = stdout, .Prefix = NULL, .AddSource = true, \ .File = stdout, .MinLevel = SlogLevelWarn, \
.Json = true \ .Prefix = NULL, .AddSource = true, .Json = true \
} \ } \
} }
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -5,16 +5,19 @@ int main(void)
{ {
struct SlogLogger logger = SLOG_DEFAULT_TEXT_LOGGER; struct SlogLogger logger = SLOG_DEFAULT_TEXT_LOGGER;
SLOG_DEBUG(&logger, "will not appear");
// Dropped, the default text logger has .Opts.MinLevel = SlogLevelInfo
SLOG_INFO(&logger, "hello from minimal.c");
// The default text logger's output file is stdout:
// time=2025-09-29T17:46:49.409721457-06:00 level=INFO msg=hello from minimal.c
struct SlogAttr attrs[] = { struct SlogAttr attrs[] = {
SlogAttrB("ok", true), SlogAttrB("ok", true),
}; };
SLOG_INFO(&logger, "hello", attrs); SLOG_INFO_ATTRS(&logger, "hello", attrs);
// time=2025-09-29T17:46:49.409721457-06:00 level=INFO msg=hello ok=true // time=2025-09-29T17:46:49.409721457-06:00 level=INFO msg=hello ok=true
// SLOG_INFO(&logger, "hello", NULL);
// Warning: size of pointer is divided by size of pointed type
// but still could be used.
return 0; return 0;
} }

View file

@ -13,28 +13,33 @@ int main(void)
struct SlogLogger l1 = { struct SlogLogger l1 = {
SlogTextHandler, SlogTextHandler,
&opts1, opts1,
}; };
struct SlogHandlerOpts opts2 = { struct SlogHandlerOpts opts2 = {
.File = stderr, .File = stderr,
.MinLevel = SlogLevelError, .MinLevel = SlogLevelError,
.Prefix = "scope", .Prefix = "scope",
.AddSource = true, .AddSource = false,
.Json = true, .Json = true,
}; };
struct SlogLogger l2 = { struct SlogLogger l2 = {
SlogTextHandler, SlogTextHandler,
&opts2, opts2,
}; };
struct SlogAttr attrs[] = { struct SlogAttr attrs[] = {
SlogAttrB("ok", true), SlogAttrB("ok", true),
}; };
SLOG_INFO(&l1, "hello", attrs); SLOG_INFO_ATTRS(&l1, "hello", attrs);
SLOG_ERROR(&l2, "hello", attrs); // stdout:
// time=2025-09-30T09:38:32.607139416-06:00 level=INFO msg=hello source=tests/slog.c:36 func=main ok=true
SLOG_ERROR(&l2, "hello");
// stderr:
// time=2025-09-30T09:38:32.607139416-06:00 level=INFO msg=hello
return 0; return 0;
} }