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;
|
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;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
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) \
|
#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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
tests/slog.c
15
tests/slog.c
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue