Skip to content

Logovod – macro-free allocation-free user-configurable logger front-end for C++

1. Features

logovod features

  1. Three styles of use — with functions, ostream left shifts, format string
  2. Automatic space insertion of functional style
  3. Automatic printing of standard containers, tuples, variants, optional
  4. Compile or run-time priority levels
  5. Compile or run-time sinks
  6. Constrained message length
  7. Support for wide-char streams
  8. Priority levels according to RFC-5424 section-6.2.1

2. Concerns

The following conerns were identified

  1. Easy of use prevails of precise formatting
  2. 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
  3. Allocation in the logger may induce bad alloc errors
  4. Unconstrained log message size accompanied with C++ operators may cause unintentionally huge data dumps
  5. Troubleshooting race conditions requires sync-free logging
  6. Log level limits should be available for build-time and run-time
  7. Sink selection should be available for build-time and run-time
  8. Logger tuning should be flexible enough to focus on a particular problem and void unrelated records
  9. Logger front-end should introduce minimal possible penalties and overhead
  10. Changing log level should not impact any possible side-effects of the user’s logging statements
  11. Logger’s formatter should not interfere with application’s formatters
  12. Access to the logger is needed from different contexts, such as static methods, free functions, lambdas.
  13. A shared instance of a logger front-end would require some synchronization technique
  14. In some use cases the log messages should be attributed with some common information, such as date, tag, source location, thread-id, process id.
  15. Some log sinks automatically attribute the messages, some others don’t
  16. 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
  17. Logger from-end is the only source of source location information
  18. An application should not require any run-time configuration file to use logger
    • run-time configuration file is an option, not a prerequisite
  19. Some libraries needs logging, however, where to log and whether tog should be decided by application
  20. Shared logger configuration is better for consistency, ad-hoc overrides – for flexibility
  21. Some standard to string conversions are available only for operator<<(std::ostream,...) .
  22. 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

  1. Logger configuration responsibilities are assigned to concept of log Category.
  2. Log Category defines logger properties and controls it behavior
  3. Logger is a template class parametrized by a log category
  4. Log emitters are inner classes of the logger template, additionally parametrized by a log priority level
  5. 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
  6. A category may redefine sink concepts as a functor object, if needed
  7. An emitter:
    • buffers data writes, issued by the user,
    • collects message attributes,
    • calls prologer, epiloger and
    • flushes the message to the writer
  8. 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.
  9. Emitter supports three style of use: invoke , left shift and format string
  10. Emitter deploys std::ostream for converting value to text
  11. 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

Your email is never published nor shared. Required fields are marked *
*
*

*