MyGit

v4.0.0

odygrd/quill

版本发布时间: 2024-05-22 19:57:09

odygrd/quill最新发布版本:v7.0.0(2024-09-06 06:50:45)

This version represents a major revamp of the library, aiming to simplify and modernize it, resulting in the removal of a few features. Please read through the changes carefully before upgrading, as it is not backwards compatible with previous versions and some effort will be required to migrate.

I understand that these changes may inconvenience some existing users. However, they have been made with good intentions, aiming to improve and refine the logging library. This involved significant effort and dedication.

Bug fixes and releases for v3 will continue to be supported under the v3.x.x branch.

Comparison

The below flamegraph shows the difference in included headers between the two versions

Version Compiler FlameGraph
v4.0.0 quill_v4_compiler_profile.speedscope.png
v3.8.0 quill_v3_compiler_profile.speedscope.png

A new compiler benchmark has been introduced. A Python script generates 2000 distinct log statements with various arguments. You can find the benchmark here. Compilation now takes only about 30 seconds, whereas the previous version required over 4 minutes.

Version Compiler FlameGraph
v4.0.0 quill_v4_compiler_bench.speedscope.png
v3.8.0 quill_v3_compiler_bench.speedscope.png
Version Backend Throughput
v4.0.0 4.56 million msgs/sec average, total time elapsed: 876 ms for 4000000 log messages
v3.8.0 4.39 million msgs/sec average, total time elapsed: 910 ms for 4000000 log messages

Changes

The library has been restructured to minimize the number of required headers. Refactoring efforts have focused on decoupling the frontend from the backend, resulting in reduced dependencies. Accessing the frontend logging functions now does not demand inclusion of any backend logic components.

 "quill/Backend.h" - It can be included once to start the backend logging thread, typically in main.cpp 
                     or in a wrapper library.
 
 "quill/Frontend.h"` - Used to create or obtain a `Logger*` or a `Sink`. It can be included in limited 
                       files, since an obtained `Logger*` has pointer stability and can be passed around.
 
 "quill/Logger.h", "quill/LogMacros.h" - These two files are the only ones needed for logging and will have 
                                         to be included in every file that requires logging functionality.

One of the significant changes lies in the support for formatting both user-defined and standard library types. Previously, the backend thread handled the formatting of these types sent by the frontend. It involved making a copy for any object passed to the LOG_ macros as an argument using the copy constructor of a complex type instead of directly serializing the data to the SPSC queue. While this method facilitated logging copy-constructible user-defined types with ease, it also posed numerous challenges for asynchronous logging:

Additionally, after years of professional use and based on experience, it has been observed that user-defined types are often logged during program initialization, with fewer occurrences on the hot path where mostly built-in types are logged. In such scenarios, the overhead of string formatting on the frontend during initialization is not an issue.

In this new version, the use of the copy constructor for emplacing objects in the queue has been abandoned. Only POD types are copied, ensuring that only raw, tangible data is handled without any underlying pointers pointing to other memory locations. The only exception to this are the pointers to Metadata, LoggerBase and DecodeFunction that are passed internally for each log message. Log arguments sent from the frontend must undergo serialization beforehand. While this approach resolves the above issues, it does introduce more complexity when dealing with user-defined or standard library types.

Built-in types and strings are logged by default, with the formatting being offloaded to the backend. Additionally, there is built-in support for most standard library types, which can also be directly passed to the logger by including the relevant header from quill/std.

The recommendation for user-defined types is to format them into strings before passing them to the LOG_ macros using your preferred method. You can find an example of this here.

It's also possible to extend the library by providing template specializations to serialize the user-defined types and offload their formatting to the backend. However, this approach should only be pursued if you cannot tolerate the formatting overhead in that part of your program. For further guidance, refer to this example.

The library is now header-only. This change simplifies exporting the library as a C++ module in the future. See here on how to build a wrapper static library which includes the backend and will minimise the compile times.

Most preprocessor flags have been moved to template parameters, with only a few remaining as CMake options. This change simplifies exporting the library as a C++ module in the future.

To enhance clarity, handlers have been renamed to sinks.

The PatternFormatter has been relocated from Sink to Logger, enabling a logger object to log in a specific format. This allows for different formats within the same output file, a feature not previously possible.

The configuration settings have been divided into FrontendOptions and BackendOptions.

MacroMetadata and many backend classes have undergone refactoring, resulting in reduced memory requirements.

The library now offers significant performance enhancements for handling wide strings on Windows platforms. It's important to note that only wide strings containing ASCII characters are supported. Previously, wide strings were converted to narrow strings at the frontend, impacting the critical path of the application. With this update, the underlying wide char buffer is copied and the conversion to UTF-8 encoding is deferred to the backend logging thread. Additionally, this update adds support for logging STL containers consisting of wide strings

The default logger, along with the configuration inheritance feature during logger creation, has been removed. Now, when creating a new logger instance, configurations such as the Sink and log pattern format must be explicitly specified each time. This simplifies the codebase.

The static global logger* variable that was initialised during quill::start() used to obtain the default logger has been removed. It is possible to add this on the user side. If you require a global logger you can have a look at this example

The support for printf style formatting has been removed due to its limited usage and the increased complexity. Users requiring this feature should stay on v3.x.x versions to maintain compatibility.

The option to build the library with external libfmt has been removed. It becomes difficult to maintain and backwards support previous versions of libfmt. Instead, libfmt is now an internal component of the library, accessible under the namespace fmtquill. You can use the bundled version of fmtquill by including the necessary headers from quill/bundled/fmt. Alternatively, you have the freedom to integrate your own version. Since libfmt is encapsulated within a distinct namespace, there are no conflicts even if you link your own libfmt alongside the logging library.

Migration Guidance

相关地址:原始地址 下载(tar) 下载(zip)

查看:2024-05-22发行的版本