LIBLOGGING-STDLOG(3)
π LIBLOGGING-STDLOG β the standard logging library bestie π
okay so this is liblogging-stdlog(3), the standard logging library from the standard logging library fam. she's giving C API, she's giving syslog-but-make-it-modern, and she's genuinely so useful once you get to know her. let's go π«Ά
β¨ NAME β¨
liblogging-stdlog β the standard logging library, periodt π
πΈ SYNOPSIS πΈ
#include <liblogging/stdlog.h>
const char* stdlog_version(void);
int stdlog_init(int options);
void stdlog_deinit();
stdlog_channel_t stdlog_open(const char *ident,
const int options, const int facility,
const char *channelspec);
int stdlog_log(stdlog_channel_t channel, const int severity,
const char *fmt, ...);
int stdlog_log_b(stdlog_channel_t channel, const int severity,
char *buf, const size_t lenbuf,
const char *fmt, ...);
int stdlog_vlog(stdlog_channel_t channel, const int severity,
const char *fmt, va_list ap);
int stdlog_vlog_b(stdlog_channel_t channel, const int severity,
char *buf, const size_t lenbuf,
const char *fmt, va_list ap);
void stdlog_close(stdlog_channel_t channel);
size_t stdlog_get_msgbuf_size(void);
const char *stdlog_get_dflt_chanspec(void);
π¦ DESCRIPTION π¦
stdlog_version() hands you the version string of the library you're actually running, like "1.0.2". you can call it literally whenever, no rules. and if you need a specific (minimal) version of the library? bestie, the move is to do runtime checks with stdlog_version() before you call stdlog_init(). protect yourself. π
stdlog_init() is the glow-up moment where the logging system gets initialized. it must only be called once during the lifetime of a process β one and done, no takebacks. if you don't want any special options, calling stdlog_init() is optional. if you don't call it, the first call to any of the other calls will just initiate it for you. this feature is primarily for backward compatibility with how the legacy syslog(3) API worked. but ngl, it does not play well with multi-threaded applications. with those, call stdlog_init() explicitly from the startup thread. the options parameter holds one or more of the library options specified in their own section below. β¨
stdlog_deinit(void) is the cleanup era β it cleans up resources including closing file handles at library exit. no library calls are permitted after it has been called. its usage is optional if no cleanup is required, but just know that this will leave resource leaks, which will be reported by tools like valgrind. π
stdlog_open() opens a log channel, which you can then use in consecutive calls to stdlog_log(). the string you give to ident identifies the message source. how it's handled is depending on the output driver. for example, the file: and syslog: drivers prepend it to the message, while the journal: driver ignores it (as the journal automatically identifies messages based on the application who submits them). in general, you can think of it as being equivalent to the ident specified in the traditional openlog(3) call. the value given in options controls handling of the channel β it can be used to override options set during stdlog_init(). note that for signal-safeness you need to specify STDLOG_SIGSAFE. the facility field contains a facility similar to the traditional syslog facility. again, it is driver-dependent on how this field is actually used. the channelspec field is a channel specification string, which allows you to control the destination of this channel. to use the default output channel specification, provide NULL to channelspec. doing so is highly suggested if there is no pressing need to do otherwise. π
stdlog_close() closes the associated channel. the channel specifier must not be used after stdlog_close() has been called. if you do it anyway, unpredictable behavior will happen, as the memory it points to has been free'ed. so like, don't. π
stdlog_log() is the equivalent to the syslog(3) call. it offers a similar interface, but there are notable differences. the channel parameter specifies the log channel to use. use NULL to select the default channel β this is sufficient for most applications. the severity field contains a syslog-like severity. the remaining arguments are a format, as in printf(3), and any arguments required by the format. note that some restrictions apply to the format in signal-safe mode (described below). stdlog_log() supports log message sizes of slightly less than 4KiB. the exact size depends on the log driver and parameters specified in stdlog_open(). the reason is that the log drivers may need to add headers and trailers to the message text, and this is done inside the same 4KiB buffer that is also used for the actual message text. for example, the "syslog:" driver adds a traditional syslog header, which among others contains the ident string provided by stdlog_open(). if the complete log message does not fit into the buffer, it is silently truncated. the formatting buffer is allocated on the stack. π₯
β οΈ note that the 4Kib buffer size is a build time default. as such, distributions may change it. to obtain the size limit that the linked in instance oflibloggin-stdlogwas build with, usestdlog_get_msgbuf_size(). you may also use thestdlogctl(1)utility to find out the build time settings for the installed version ofliblogging-stdlog.
stdlog_log_b() is almost equivalent to stdlog_log(), except that the caller can provide a formatting work buffer. this is done via the buf and buflen parameters. this permits you to use both smaller and larger buffer sizes. for embedded systems (or signal handlers), this may be convenient to reduce the amount of stack space required. also, it is useful if very large messages are to be logged. note that while there is no upper limit on the buffer size per se, the log drivers may have some limits. in general, up to 64KiB of buffer should work with all drivers. π
stdlog_vlog() and stdlog_vlog_b() are equivalent to stdlog_log() and stdlog_log_b() except that they take a va_list argument. besties who know, know. iykyk π
stdlog_get_dflt_chanspec() gives you the default channel specification. this must be called only after stdlog_init() has been called. no skipping steps, girlie. π
β OPTIONS β
options modify library behavior. they can be specified in stdlog_init() and stdlog_open() calls. the stdlog_init() call is used to set default options. these are applied if channels are automatically created or the STDLOG_USE_DFLT_OPTS option is used in stdlog_open(). otherwise, options provided to stdlog_open() are not affected by the global option set. πΈ
the following options can be given:
STDLOG_USE_DFLT_OPTSβ says that thestdlog_open()call shall use the default global options. if this option is given, no other options can be set. trying to do so results in an error. note that this option is not valid for thestdlog_init()call.STDLOG_SIGSAFEβ requests signal-safe mode. if and only if this is specified, library calls are signal-safe. some restrictions apply in signal-safe mode. see description below for details. π₯STDLOG_PIDβ logs the process identifier (PID) of the originator with each message. π«Ά
π FACILITIES π
the following facilities are supported. please note that they are mimicked after the traditional syslog facilities, but liblogging-stdlog uses different numerical values. this is necessary to provide future enhancements. so do not use the LOG_xxx #defines from syslog.h β use the following STDLOG_xxx defines instead:
STDLOG_KERNβ kernel messagesSTDLOG_USERβ random user-level messagesSTDLOG_MAILβ mail systemSTDLOG_DAEMONβ system daemonsSTDLOG_AUTHβ security/authorization messagesSTDLOG_SYSLOGβ messages generated internally by syslogdSTDLOG_LPRβ line printer subsystemSTDLOG_NEWSβ network news subsystemSTDLOG_UUCPβ UUCP subsystemSTDLOG_CRONβ clock daemonSTDLOG_AUTHPRIVβ security/authorization messages (private)STDLOG_FTPβ ftp daemonSTDLOG_LOCAL0β reserved for application useSTDLOG_LOCAL1β reserved for application useSTDLOG_LOCAL2β reserved for application useSTDLOG_LOCAL3β reserved for application useSTDLOG_LOCAL4β reserved for application useSTDLOG_LOCAL5β reserved for application useSTDLOG_LOCAL6β reserved for application useSTDLOG_LOCAL7β reserved for application use
regular applications should use facilities in the STDLOG_LOCALx range. non-privileged applications may not be able to use all of the system-defined facilities. note that it is also safe to refer to application specific facilities via
STDLOG_LOCAL0 + offset
if offset is in the range of 0 to 7. π
π SEVERITY π
the following severities are supported:
STDLOG_EMERGβ system is unusableSTDLOG_ALERTβ action must be taken immediatelySTDLOG_CRITβ critical conditionsSTDLOG_ERRβ error conditionsSTDLOG_WARNINGβ warning conditionsSTDLOG_NOTICEβ normal but significant conditionSTDLOG_INFOβ informationalSTDLOG_DEBUGβ debug-level messages
these reflect the traditional syslog severity mappings. note that different output drivers may have different needs and may map severities into a smaller set. π
π§΅ THREAD- AND SIGNAL-SAFENESS π§΅
okay bestie this is the part where we find out who's actually safe to call from wherever π
These calls are thread- and signal-safe:
stdlog_version()stdlog_get_msgbuf_size()stdlog_get_dflt_chanspec()
These calls are not thread- or signal-safe:
stdlog_init()stdlog_deinit()stdlog_open()stdlog_close()
For stdlog_log(), stdlog_vlog(), stdlog_log_b(), and stdlog_vlog_b(), it depends:
- if the channel has been opened with the
STDLOG_SIGSAFEoption, the call is both thread-safe and signal-safe. - if the library has been initialized by
stdlog_init()or the channel has been opened bystdlog_open(), the call is thread-safe but not signal-safe. - if the library has not been initialized and the default (
NULL) channel is used, the call is neither thread- nor signal-safe. π
For stdlog_log_b() and stdlog_vlog_b() the caller must also ensure that the provided formatting buffer supports the desired thread- and signal-safeness. For example, if a static buffer is used, thread-safeness is not given. For signal-safeness, typically a buffer allocated on the signal handler's stack is needed. π«Ά
For multi-threaded applications, it is highly recommended to initialize the library via stdlog_init() on the main thread before any other threads are started. do it first, bestie, it's giving main character energy π
Thread- and signal-safeness, if given, does not require different channels. It is perfectly fine to use the same channel in multiple threads. Note however that interrupted system calls will not be retried. An error will be returned instead. This may happen if a thread is inside a stdlog_log() call while an async signal handler using that same call is activated. Depending on timing, the first call may or may not complete successfully. It is the caller's chore to check return status and do retries if necessary. π yes, chore. you gotta.
Finally, thread- and signal-safeness depend on the log driver. At the time of this writing, the "syslog:" and "file:" drivers are thread- and signal-safe while the current "journal:" driver is thread- but not signal-safe. To the best of our knowledge, the systemd team is working on making the API we depend on signal-safe. If this is done, the driver itself is also signal-safe (the restriction results from the journal API).
π« RESRICTIONS IN SIGNAL-SAFE MODE π«
When signal-safeness is requested, the set of supported printf formats is restricted. This is due to the fact that the standard printf routines cannot be called and so a smaller signal-safe printf implementation that is part of liblogging-stdlog is used instead.
It has the following restrictions:
- flag characters are not supported
- field width and precision fields are accepted but silently ignored π
- the following length modifiers are supported:
l,ll,h,hh,z - the following conversion specifiers are supported:
s,i,d,u,x,X,p,c,f(wherefis always formatted as"%.2f") - only the following control character escapes are supported:
\n,\r,\t,\\. Please note that it is not advisable to include control characters in log records. Log drivers and log back-end systems may remove them.
π‘ CHANNEL SPECIFICATIONS π‘
The channel is described via a single-line string. Currently, the following channels can be selected:
"syslog:", which is the traditional syslog output to/dev/log"uxsock:<name>", which writes messages to the local unix socket name. The message is formatted in traditional syslog-format."journal:", which emits messages via the native systemd journal API"file:<name>", which writes messages in a syslog-like format to the file specified as name
If no channel specification is given, the default is "syslog:". The default channel can be set via the LIBLOGGING_STDLOG_DFLT_LOG_CHANNEL environment variable. β¨
Not all output channel drivers are available on all platforms. For example, the "journal:" driver is not available on BSD. It is highly suggested that application developers never hard-code any channel specifiers inside their code but rather permit the administrator to configure these. If there is no pressing need to select different channel drivers, it is suggested to rely on the default channel spec, which always can be set by the system administrator. let the admin cook π
π« RETURN VALUE π«
When successful stdlog_init() and stdlog_log() return zero and something else otherwise. stdlog_open() returns a channel descriptor on success and NULL otherwise. In case of failure errno is set appropriately.
Note that the traditional syslog(3) API does not return any success state, so any failures are silently ignored. In most cases, this works sufficiently reliably. If this level of reliability is sufficient, the return code of stdlog_log() does not need to be checked. This is probably the case for most applications. lowkey chill about it π
If finding out about the success of the logging operation is vital to the application, the return code can be checked. Note that you must not try to find out the exact failure cause. If the return is non-zero, something in the log system did not work correctly. It is suggested that the logging operation is re-tried in this case, and if it fails again it is suggested that the channel is closed and re-opened and then the operation re-tried. During failures, partial records may be logged. This is the same what could happen with syslog(3). Again, in general it should not be necessary to check the return code of stdlog_log().
The stdlog_deinit() and stdlog_close() calls do not return any status.
π EXAMPLES π
A typical single-threaded application just needs to know about the stdlog_log() call:
stdlog_log(NULL, STDLOG_NOTICE, "New session %d of user %s",
sessid, username);
Being thread- and signal-safe requires a little bit more of setup:
/* on main thread */
status = stdlog_init(STDLOG_SIGSAFE);
/* here comes the rest of the code, including worker
* thread startup.
*/
/* And do this in threads, signal handlers, etc: */
stdlog_log(NULL, STDLOG_NOTICE, "New session %d of user %s",
sessid, username);
If you need just a small formatting buffer (or a large one), you can provide the memory yourself:
char buf[512];
stdlog_log_b(NULL, STDLOG_NOTICE, buf, sizeof(buf),
"New session %d of user %s", sessid, username);
π SEE ALSO π
π COPYRIGHT π
This page is part of the liblogging project, and is available under the same BSD 2-clause license as the rest of the project.
π AUTHOR π
Rainer Gerhards <rgerhards@adiscon.com>
and that's a wrap bestie π this page is dated 2014-02-22 and it lives in the LIBLOGGING-STDLOG(3) section β go forth and log responsibly, no cap π β¨
π¦ where this page comes from
- alpine 3.23: liblogging-doc 1.0.7-r0 Β· BSD-2-Clause
- alpine 3.24: liblogging-doc 1.0.8-r0 Β· BSD-2-Clause
- fedora 43: liblogging-stdlog-devel 1.0.8-1.fc43 Β· BSD-2-Clause
- fedora 43: liblogging-stdlog-devel 1.0.8-1.fc43 Β· BSD-2-Clause
- fedora 44: liblogging-stdlog-devel 1.0.8-1.fc44 Β· BSD-2-Clause
- fedora 44: liblogging-stdlog-devel 1.0.8-1.fc44 Β· BSD-2-Clause
- nixos 26.05: liblogging 1.0.8
- nixpkgs unstable: liblogging 1.0.8
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms