Repository navigation
Changes
Entries can now be stamped by a clock of your choice instead of always std::chrono::system_clock: a calibrated TSC, a backtest's simulated time, or a fixed clock in tests. Code that calls LOG_* needs no changes, the default output is unchanged, and a 2.3.0 process can share a segment with a 2.2.x one.
- Configurable timestamper. The new
ITimestamperinterface (uint64_t now() noexcept, returning nanoseconds since the Unix epoch) decides the time stored inLogEntry::timestamp.TimestampFormatterand the pattern flags still decide how that time is printed- Three ways to set one: derive from
ITimestamperand pass it toLogger::set_timestamper(); pass any callable, including a lambda with captures; or name a chrono-style clock type withset_timestamper<Clock>().LogConfig::timestampersets it atinit(), before the version banner is logged set_timestamper(nullptr)andreset()go back tosystem_clock. A nullLogConfig::timestamperkeeps the current one, the same rule as an emptyLogConfig::pattern, andshutdown()leaves it alonetimestamper()returns the one in use (null while the default is), andcurrent_timestamp()reads the logger's clock directly
- Three ways to set one: derive from
- Safe to swap while logging. Logging threads read the timestamper through one atomic pointer, so
set_timestamper()takes no lock and blocks no one. A replaced timestamper is kept alive untilreset(), because a thread may still be inside itsnow(). As withset_pattern(), call it from one thread at a time - Cost. The timestamper runs on every log call, on every logging thread, so it must be cheap and thread-safe, and it must not throw:
now()isnoexcept, so a throwing callable terminates the program. Measured on Windows/MSVC/O2(minimum of 40 rounds), the default path adds under 1 ns to the ~52 nssystem_clockread it wraps, and a timestamper returning a stored value costs about 3.5 ns LogStats::timestamp_nsfollows the timestamper, so statistics rows keep lining up with the log lines they describe.DailyFileSinkstill takes the date in its file name from the wall clock- Compatibility.
LogEntryis unchanged, so 2.3.0 and 2.2.x processes can share a segment; each producer stamps its entries with its own timestamper.Loggeritself gained members, so a plugin that routes itsLOG_*calls to the host throughset_instance()must be rebuilt against the same version as the hosttimestamperis the last member ofLogConfig, so positional (aggregate) initializers written for 2.2.x keep compiling and keep their meaning. A test pins the member order
- Documentation and CI. The README opens with an overview, navigation and benchmark highlights, and its installation section now leads with vcpkg. A new CI job builds and runs the README's vcpkg example in both classic and manifest mode
- New tests cover each way to set a timestamper,
LogConfighandling, the statistics timestamp, and swapping the timestamper while four threads log
Downloads
The library is header-only: take slick-logger-2.3.0.zip
or .tar.gz and add include/ to your include path. The archive is
self-contained - alongside slick/logger.hpp it bundles the
slick/queue.h and slick/shm/ headers it includes, from
slick-queue and
slick-shm, so there is no
separate dependency to install. Their licences are in licenses/.
slick-log-collector-* contains the prebuilt standalone collector for
multi-process logging.
It is optional; you only need it to collect log entries from several
processes into one set of sinks.