1. Features
logovod features
- Three styles of use — with functions, ostream left shifts, format string
- Automatic space insertion of functional style
- Automatic printing of standard containers, tuples, variants, optional
- Compile or run-time priority levels
- Compile or run-time sinks
- Constrained message length
- Support for wide-char streams
- Priority levels according to RFC-5424 section-6.2.1
2. Concerns
The following conerns were identified
- Easy of use prevails of precise formatting
- A macro-free logger front-end is desirable, as macros:
- may trigger/expose unintended side-effects
- may hide build errors until a particular log-level is enabled
- discouraged by ISOCPP
- Allocation in the logger may induce bad alloc errors
- Unconstrained log message size accompanied with C++ operators may cause unintentionally huge data dumps
- Troubleshooting race conditions requires sync-free logging
- Log level limits should be available for build-time and run-time
- Sink selection should be available for build-time and run-time
- Logger tuning should be flexible enough to focus on a particular problem and void unrelated records
- Logger front-end should introduce minimal possible penalties and overhead
- Changing log level should not impact any possible side-effects of the user’s logging statements
- Logger’s formatter should not interfere with application’s formatters
- Access to the logger is needed from different contexts, such as static methods, free functions, lambdas.
- A shared instance of a logger front-end would require some synchronization technique
- In some use cases the log messages should be attributed with some common information, such as date, tag, source location, thread-id, process id.
- Some log sinks automatically attribute the messages, some others don’t
- In some cases log messages should be routed to more than one sink.
- This multi-sink routing may need some logic based on the message attributes
- Such sinks may have different approach or capabilities on message attributing
- Logger from-end is the only source of source location information
- An application should not require any run-time configuration file to use logger
- run-time configuration file is an option, not a prerequisite
- Some libraries needs logging, however, where to log and whether tog should be decided by application
- Shared logger configuration is better for consistency, ad-hoc overrides – for flexibility
- Some standard to string conversions are available only for operator<<(std::ostream,...) .
- Different teams prefer different syntax of the log statements – function calls, stream left shift operators, format string
3. Design
3.1. Design Philosophy
Focus on a simple ready-to-use solution and provide easy-to-use means for making custom solutions as complex as needed
3.2. Design Decisions
- Logger configuration responsibilities are assigned to concept of log Category.
- Log Category defines logger properties and controls it behavior
- Logger is a template class parametrized by a log category
- Log emitters are inner classes of the logger template, additionally parametrized by a log priority level
- Log sink is a set of weakly related concepts – prologer, writer, epiloger.
- prologer, writer, epiloger are free functions.
- Any state needed for their operations maintained externally, for example in variables with static storage class
- A category may redefine sink concepts as a functor object, if needed
- An emitter:
- buffers data writes, issued by the user,
- collects message attributes,
- calls prologer, epiloger and
- flushes the message to the writer
- An emitter is considered to be a disposable, one-time use object.
- Design, however, should not disallow other use cases, such as emitter reuse, or deferred use.
- Emitter supports three style of use: invoke , left shift and format string
- Emitter deploys std::ostream for converting value to text
- Emitter uses internally allocated stream buffer of capacity, defined in the category
- If category defines unlimited capacity, basic_stringbuf is used
4. Quick Start Guide
// Instantiate a logger type using Log = logovod::logger<logovod::category>; // Emit log messages with a function-call style Log::debug("Hello Logovod"); // or with I/O stream shifts Log::info{} << "Hello Logovod I/O stream style"; // or with std::format Log::notice{}.format("Hello {} format style", "Logovod");
5. User Guide
Please visit this github page User Guide
6. Sources
Logovod sources are shared via github https://github.com/hutorny/logovod
7. License
Logovod is licensed under MIT
Post a Comment