stumpless: one logging interface in C for journald, sqlite, syslog and the Windows Event Log
a fast and feature-rich logging library for C
At a glance
- What is it?
- stumpless is a C logging library whose selling point is target variety: the same call can land in a file, a unix socket, journald, a sqlite database, the Windows Event Log or a network collector. The trade-off is a dependency with its own cmake build, its own configure-time switches, and a release history that trails its most recent commits.
- Who is it for?
- stumpless is worth adopting in a C or C++ service that has to satisfy several logging requirements at once, such as a local file for diagnostics and a network collector for aggregation, without adding a daemon or a second SDK. It is the wrong choice for a small utility that only needs one syslog line, and it is a poor fit for a team that wants a stable tag to pin, because the newest published release is v2.2.0 from 2024-05-26 while the last push was on 2026-06-07.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 138 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A logging library whose real product is the target list
The repository describes stumpless as "a fast and feature-rich logging library for C", and the README spends most of its space on where logs can go rather than on how to format them. The stated primary goal is to provide a consistent logging interface to a wide variety of log targets, so you can focus on defining events and where they should go without hunting for other SDKs or adding daemons and plugins.
The list of targets is concrete. Stumpless can write to simple character buffers, to files and streams, to unix sockets such as a local syslog daemon, to network servers over IPv4 or IPv6 using TCP or UDP, to the systemd Journald service, to sqlite3 databases, to the Windows Event Log, and to custom functions for anything else.
That list explains who the library is for. A C service that must write a local file for a support bundle and simultaneously forward the same event to a network collector would otherwise juggle the syslog API, an SQLite client and a socket. Stumpless collapses that into one call with one configuration model. The cost is that the library becomes a dependency of your build, and a dependency with a cmake-driven, feature-switched configuration is not a small thing to take on.
The topics list confirms the shape of the audience: structured-logging, journald, sqlite, syslog and event-log all appear as tags, alongside contributions-welcome and good-first-issue.
The most recently opened target wins, and there is a platform default
The target model is where the design shows its C heritage and its simplicity. You do not pass a target to every call. You open a target, and subsequent calls use the most recently opened one.
target = stumpless_open_file_target( "example.log" );
// uses the last opened target by default
stump( "Login attempt failure #%d for user %s", count, username );If no target has been opened at all, the library falls back to a per platform default. On Linux that is /dev/log, on a Mac system it is /var/run/syslog, and on a Windows machine it is the Windows Event Log. That fallback is what makes the shortest possible entry point work.
// if you're used to doing this:
syslog( LOG_INFO | LOG_USER, "My message #%d", count );
// then you can start by changing to this:
stumplog( LOG_INFO | LOG_USER, "My message #%d", count );The stumplog function is documented as a direct replacement for the standard library syslog function, keeping the same LOG_INFO and LOG_USER style flags. The stump function is the shorter form for the current target and accepts printf style format specifiers.
When you need to be explicit rather than relying on the most recent target, there is a call that takes the target as its first argument.
stumpless_add_message( target,
"Login attempt failure #%d for user %s",
count,
username );One consequence worth planning for: because the current target is global state, two threads or two subsystems that open different targets will interfere with each other. The library is described as thread safe, which protects the data structures, not the semantics of which target is current.
Compile-time level switches remove logging calls entirely
Stumpless offers a family of severity shorthand macros, and the interesting part is not the macros themselves but how they are compiled away.
stump_i( "this gets logged as an info message" );stump_t( "this includes source info" );The trailing character marks the level, and the _t variant adds source file, line number and function name to each message. The library states that these functions can be removed at compile time by defining the STUMPLESS_ENABLE_UPTO or STUMPLESS_DISABLE_DOWNTO symbols, which makes it easy to change logging levels between builds, for example to have production and debug versions without differences in their source code.
This is the feature that changes the calculus for a performance sensitive service. The README also says the library can be adjusted or removed during compilation for zero runtime cost. A logging call that is compiled out costs nothing at all, which is different from a call that is made and then filtered.
There is one ordering constraint that the README calls out directly: the symbols have to be defined before stumpless.h is included. That is a build configuration detail, but it is the kind of detail that produces a confusing half-working build if it is missed.
Building it takes cmake and a cmake supported toolchain
The build requirements are modest on paper: the README says stumpless only requires cmake and a cmake-supported build toolchain such as GCC or Visual Studio. The documented sequence is short.
# cloning the latest version of the source tree
git clone [email protected]:goatshriek/stumpless.git
# creating a new build directory
mkdir build
cd build
# configuring the new build
cmake ../stumpless
# building stumpless (with 4 threads - adjust as desired)
cmake --build . --parallel 4
# install the library (you probably need sudo to do this)
sudo cmake --install .Two observations. The clone line uses the SSH form of the GitHub URL, so a CI runner needs a key or a substituted HTTPS address. And the install step is a plain cmake --install . into the system prefix, which is the point where a distribution packager usually wants to change the prefix rather than use sudo.
For anything beyond the default, the README points to INSTALL.md for building and installing in different environments or with other toolchains. The repository layout supports that: INSTALL.md sits at the root next to CMakeLists.txt, with src/, include/, test/, tools/, scripts/ and docs/ as the other directories.
Continuous integration is visible in the README through build badges for Linux, Windows and Mac workflows, along with a coverage report badge, a SonarCloud status badge and a Contributor Covenant badge. The README also lists supported platforms as Linux, Windows, Mac, FreeBSD, MinGW, MSYS2, Cygwin and DOS, which is a wide surface for a library that must stay portable.
Network targets are the reason to reach for it, and also its sharpest edge
Sending an event to a network collector such as Splunk or rsyslog takes one call, using the same target mechanism.
target = stumpless_open_udp4_target( "send-to-splunk-example",
"mylogserver.com" ); // or use an IP
stump( "Login attempt failure #%d for user %s", count, username );The target name is the first argument and the host or address is the second, and the address can be a name or an IP. The example uses UDP, which is the natural choice for syslog style traffic that tolerates loss, and the README lists TCP and UDP over IPv4 and IPv6 among the supported transports.
Here is the honest limitation. A library that offers a network target is a library that can lose data, block on a slow collector, or send events to the wrong place, and the README does not document retry behaviour, buffering, backpressure or delivery guarantees for network targets. It also does not document what happens when the collector is unreachable. If your logging must be durable, treat the network target as a fast path rather than a system of record and keep a file or database target alongside it.
The same restraint applies to the sqlite3 target. A database target inside an application is convenient until two processes write to the same file, and the README does not describe the locking or concurrency behaviour of that target.
Structured logging and the _str variants that skip formatting
The feature list puts structured and unstructured logging side by side, and the README notes that both are supported to suit different needs. The examples in the Basic Usage section are unstructured, format string based, and the text points to structured data for the detail it does not carry.
stump_str( "Login failure! See structured data for info." );That is the _str variant, and the README makes a claim about it that is worth taking seriously: if you do not need format specifiers, the _str variants are both faster and safer. Faster because no printf style parsing happens, and safer because there is no way for a user supplied string to be interpreted as a format directive. In a logging library, format string injection is a real class of bug, and a family of calls that removes it by construction is a reasonable thing to design around.
The trade-off is that the message text is fixed. The details have to travel as structured data attached to the event, which means the target has to support it. That is a design decision, not an oversight, and it points in the same direction as the rest of the library: one interface, many destinations, with the structure carried alongside the text.
Apache 2.0, a quiet release history, and a busy commit line
The licence is Apache 2.0, with the COPYING file present at the repository root and the badge set in the README pointing at the standard Apache 2.0 text. For a library that a company might link into a commercial product, that is a permissive grant with the standard obligations, including the requirement to keep the licence and copyright notices intact when redistributing. This is a description of the terms and not a legal opinion.
On maintenance, two dates matter and they point in different directions. The last push was on 2026-06-07, so commits are still landing on the default branch, which is named latest. The newest published release, however, is v2.2.0 from 2024-05-26, preceded by v2.1.0 in 2022 and v2.0.0 in 2021. The gap between an active commit line and a two and a half year old tag is the practical upgrade story for anyone who wants to pin a version.
The project is organised for contributors. The README links documentation, examples and a Gitter support room, and the repository carries a ChangeLog.md, a CITATION.cff file, a Gemfile and a scripts/ directory. The l10n/ directory holds translated READMEs, with French, Korean and Simplified Chinese versions linked from the main file, and the README invites further translations. That is a sign of a project with an international contributor base rather than a single maintainer with a stale tree.
Where the standard library is the better answer
The alternative worth naming is not another logging library but the platform's own syslog call, which the README itself uses as the starting point for its example. Calling syslog directly gives you the local unix socket, no dependency, no cmake step, no target bookkeeping and no extra library in your build.
The difference in approach is straightforward. A direct syslog call writes to one destination, the local daemon, and leaves the routing decision to rsyslog or journald configuration on the machine. Stumpless moves the destination choice into the application, so the same binary can write to a file, to sqlite and to a collector at once, and so it can work on a Windows box where the Windows Event Log replaces syslog entirely.
That is a genuine advantage when you have several destinations or a platform without a syslog daemon, and a genuine liability when you have one destination on Linux. A small utility that wants one line in the system log should keep calling syslog. A long running service with a local diagnostic file, a database of structured events and a network feed is exactly the case stumpless was written for.
One more boundary: the library needs a build integration and a shared or static library artifact in your distribution. If your project must stay dependency free to be audited, that decision ends the discussion before any feature comparison.
Editorial conclusion
stumpless is worth adopting in a C or C++ service that has to satisfy several logging requirements at once, such as a local file for diagnostics and a network collector for aggregation, without adding a daemon or a second SDK. It is the wrong choice for a small utility that only needs one syslog line, and it is a poor fit for a team that wants a stable tag to pin, because the newest published release is v2.2.0 from 2024-05-26 while the last push was on 2026-06-07. Verify first that the target you need is compiled in by default, that STUMPLESS_ENABLE_UPTO or STUMPLESS_DISABLE_DOWNTO are set before stumpless.h is included, and that the cmake install step places the headers and library where your build expects them.
Frequently asked questions
Which log targets does stumpless support?
The README lists simple character buffers, files and streams, unix sockets such as a local syslog daemon, network servers over IPv4 or IPv6 with TCP or UDP, the systemd Journald service, sqlite3 databases, the Windows Event Log, and custom functions.
How do I build and install stumpless?
The README states that stumpless only requires cmake and a cmake-supported build toolchain such as GCC or Visual Studio: clone the repository, create a build directory, run cmake ../stumpless, then cmake --build . and sudo cmake --install .. INSTALL.md covers other environments and toolchains.
How do I log to a file with stumpless?
Open a file target with stumpless_open_file_target( "example.log" ), then call stump. The most recently opened target is used by default, and with no target opened the library falls back to /dev/log on Linux, /var/run/syslog on Mac and the Windows Event Log on Windows.
How do I disable logging calls at compile time in stumpless?
Define the STUMPLESS_ENABLE_UPTO or STUMPLESS_DISABLE_DOWNTO symbols before stumpless.h is included. The README says this removes the severity shorthand calls at compile time, which allows production and debug builds from the same source.
What is the difference between stump and stump_str in stumpless?
stump accepts printf style format specifiers, while the _str variant takes a fixed message. The README states that the _str variants are both faster and safer when you do not need format specifiers.
Is stumpless actively maintained and under what licence?
The last push was on 2026-06-07, though the newest published release is v2.2.0 from 2024-05-26. The project is licensed under Apache 2.0, with the COPYING file at the repository root.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/goatshriek-stumpless)Was this useful?