separate with attrs
This commit is contained in:
parent
a74a5863c7
commit
855d24da67
4 changed files with 90 additions and 63 deletions
73
README.md
73
README.md
|
|
@ -8,11 +8,18 @@ Single-header structured logger in C99
|
|||
...
|
||||
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[] = {
|
||||
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
|
||||
...
|
||||
```
|
||||
|
|
@ -25,44 +32,44 @@ Single-header structured logger in C99
|
|||
|
||||
int main(void)
|
||||
{
|
||||
struct SlogHandlerOpts opts1 = {
|
||||
.File = stdout,
|
||||
.MinLevel = SlogLevelDebug,
|
||||
.Prefix = NULL,
|
||||
.AddSource = true,
|
||||
.Json = false,
|
||||
};
|
||||
struct SlogHandlerOpts opts1 = {
|
||||
.File = stdout,
|
||||
.MinLevel = SlogLevelDebug,
|
||||
.Prefix = NULL,
|
||||
.AddSource = true,
|
||||
.Json = false,
|
||||
};
|
||||
|
||||
struct SlogLogger l1 = {
|
||||
SlogTextHandler,
|
||||
&opts1,
|
||||
};
|
||||
struct SlogLogger l1 = {
|
||||
SlogTextHandler,
|
||||
opts1,
|
||||
};
|
||||
|
||||
struct SlogHandlerOpts opts2 = {
|
||||
.File = stderr,
|
||||
.MinLevel = SlogLevelError,
|
||||
.Prefix = "scope",
|
||||
.AddSource = true,
|
||||
.Json = true,
|
||||
};
|
||||
struct SlogHandlerOpts opts2 = {
|
||||
.File = stderr,
|
||||
.MinLevel = SlogLevelError,
|
||||
.Prefix = "scope",
|
||||
.AddSource = false,
|
||||
.Json = true,
|
||||
};
|
||||
|
||||
struct SlogLogger l2 = {
|
||||
SlogTextHandler,
|
||||
&opts2,
|
||||
};
|
||||
struct SlogLogger l2 = {
|
||||
SlogTextHandler,
|
||||
opts2,
|
||||
};
|
||||
|
||||
struct SlogAttr attrs[] = {
|
||||
SlogAttrB("ok", true),
|
||||
};
|
||||
struct SlogAttr attrs[] = {
|
||||
SlogAttrB("ok", true),
|
||||
};
|
||||
|
||||
SLOG_DEBUG(&l1, "hello", attrs);
|
||||
// Written to stdout:
|
||||
// time=2025-09-29T17:36:08.597673657-06:00 level=INFO msg=hello source=tests/slog.c:36 func=main ok=true
|
||||
SLOG_INFO_ATTRS(&l1, "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", attrs);
|
||||
// Written to 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
|
||||
SLOG_ERROR(&l2, "hello");
|
||||
// stderr:
|
||||
// time=2025-09-30T09:38:32.607139416-06:00 level=INFO msg=hello
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
|
|
|||
52
slog/slog.h
52
slog/slog.h
|
|
@ -458,40 +458,52 @@ static inline void SlogTextHandler(struct SlogLogger *self, SlogLevel level,
|
|||
#define SLOG_ATTR_COUNT(ATTRS) \
|
||||
((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_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_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_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_ATTR_COUNT(ATTRS)), (&SLOG_SOURCE))
|
||||
|
||||
#define SLOG_DEFAULT_TEXT_LOGGER \
|
||||
(SlogLogger) \
|
||||
{ \
|
||||
.Handler = SlogTextHandler, .Opts = (SlogHandlerOpts) \
|
||||
{ \
|
||||
.File = stdout, .Prefix = NULL, .AddSource = false, \
|
||||
.Json = false \
|
||||
} \
|
||||
#define SLOG_DEFAULT_TEXT_LOGGER \
|
||||
(SlogLogger) \
|
||||
{ \
|
||||
.Handler = SlogTextHandler, .Opts = (SlogHandlerOpts) \
|
||||
{ \
|
||||
.File = stdout, .MinLevel = SlogLevelInfo, \
|
||||
.Prefix = NULL, .AddSource = false, .Json = false \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SLOG_DEFAULT_JSON_LOGGER \
|
||||
(SlogLogger) \
|
||||
{ \
|
||||
.Handler = SlogTextHandler, .Opts = (SlogHandlerOpts) \
|
||||
{ \
|
||||
.File = stdout, .Prefix = NULL, .AddSource = true, \
|
||||
.Json = true \
|
||||
} \
|
||||
#define SLOG_DEFAULT_JSON_LOGGER \
|
||||
(SlogLogger) \
|
||||
{ \
|
||||
.Handler = SlogTextHandler, .Opts = (SlogHandlerOpts) \
|
||||
{ \
|
||||
.File = stdout, .MinLevel = SlogLevelWarn, \
|
||||
.Prefix = NULL, .AddSource = true, .Json = true \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -5,16 +5,19 @@ int main(void)
|
|||
{
|
||||
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[] = {
|
||||
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
|
||||
|
||||
// SLOG_INFO(&logger, "hello", NULL);
|
||||
// Warning: size of pointer is divided by size of pointed type
|
||||
// but still could be used.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
15
tests/slog.c
15
tests/slog.c
|
|
@ -13,28 +13,33 @@ int main(void)
|
|||
|
||||
struct SlogLogger l1 = {
|
||||
SlogTextHandler,
|
||||
&opts1,
|
||||
opts1,
|
||||
};
|
||||
|
||||
struct SlogHandlerOpts opts2 = {
|
||||
.File = stderr,
|
||||
.MinLevel = SlogLevelError,
|
||||
.Prefix = "scope",
|
||||
.AddSource = true,
|
||||
.AddSource = false,
|
||||
.Json = true,
|
||||
};
|
||||
|
||||
struct SlogLogger l2 = {
|
||||
SlogTextHandler,
|
||||
&opts2,
|
||||
opts2,
|
||||
};
|
||||
|
||||
struct SlogAttr attrs[] = {
|
||||
SlogAttrB("ok", true),
|
||||
};
|
||||
|
||||
SLOG_INFO(&l1, "hello", attrs);
|
||||
SLOG_ERROR(&l2, "hello", attrs);
|
||||
SLOG_INFO_ATTRS(&l1, "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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue