{"id":13424554,"url":"https://github.com/odygrd/quill","last_synced_at":"2025-05-15T04:04:51.159Z","repository":{"id":37740460,"uuid":"234192998","full_name":"odygrd/quill","owner":"odygrd","description":"Asynchronous Low Latency C++ Logging Library","archived":false,"fork":false,"pushed_at":"2025-05-07T16:01:56.000Z","size":8079,"stargazers_count":2182,"open_issues_count":12,"forks_count":207,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-05-07T16:35:53.675Z","etag":null,"topics":["async","asynchronous","cpp","cpp14","cpp17","cpp20","cross-platform","fmtlib","high-performance","log-library","logger","logging","logging-library","low-latency"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/odygrd.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-01-15T23:22:33.000Z","updated_at":"2025-05-07T16:02:00.000Z","dependencies_parsed_at":"2023-12-18T11:48:48.853Z","dependency_job_id":"8635d410-2423-4737-b264-852ba303dcd3","html_url":"https://github.com/odygrd/quill","commit_stats":{"total_commits":1372,"total_committers":36,"mean_commits":"38.111111111111114","dds":0.05393586005830908,"last_synced_commit":"1759eac3833a8a52705d7440812ea41d3cf53df2"},"previous_names":[],"tags_count":89,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/odygrd%2Fquill","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/odygrd%2Fquill/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/odygrd%2Fquill/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/odygrd%2Fquill/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/odygrd","download_url":"https://codeload.github.com/odygrd/quill/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270641,"owners_count":22042858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","asynchronous","cpp","cpp14","cpp17","cpp20","cross-platform","fmtlib","high-performance","log-library","logger","logging","logging-library","low-latency"],"created_at":"2024-07-31T00:00:56.159Z","updated_at":"2025-05-15T04:04:51.139Z","avatar_url":"https://github.com/odygrd.png","language":"C++","readme":"\u003cdiv align=\"center\"\u003e\n  \u003c!--\n  \u003cmeta name=\"description\" content=\"C++ logging library. High-performance, asynchronous logging for low-latency real-time applications.\"\u003e\n  \u003cmeta name=\"keywords\" content=\"C++, logging library, asynchronous logging, high performance, low latency\"\u003e\n  --\u003e\n\n  \u003cbr\u003e\n  \u003cimg src=\"docs/logo.png\" alt=\"Quill C++ Logging Library\" width=\"200\" height=\"auto\" /\u003e\n  \u003ch1\u003eQuill\u003c/h1\u003e\n  \u003cp\u003e\u003cb\u003eAsynchronous Low Latency C++ Logging Library\u003c/b\u003e\u003c/p\u003e\n\n  \u003cdiv\u003e\n    \u003ca href=\"https://github.com/odygrd/quill/actions?query=workflow%3Afedora\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/odygrd/quill/fedora.yml?branch=master\u0026label=Fedora\u0026style=flat-square\u0026logo=fedora\" alt=\"fedora-ci\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/odygrd/quill/actions?query=workflow%3Aubuntu\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/odygrd/quill/ubuntu.yml?branch=master\u0026label=Ubuntu\u0026style=flat-square\u0026logo=ubuntu\" alt=\"ubuntu-ci\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/odygrd/quill/actions?query=workflow%3Absd\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/odygrd/quill/bsd.yml?branch=master\u0026label=BSD\u0026style=flat-square\u0026logo=openbsd\" alt=\"bsd-ci\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/odygrd/quill/actions?query=workflow%3Amacos\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/odygrd/quill/macos.yml?branch=master\u0026label=macOS\u0026logoColor=white\u0026style=flat-square\u0026logo=apple\" alt=\"macos-ci\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/odygrd/quill/actions?query=workflow%3Awindows\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/odygrd/quill/windows.yml?branch=master\u0026label=Windows\u0026logoColor=blue\u0026style=flat-square\u0026logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iODgiIHdpZHRoPSI4OCIgeG1sbnM6dj0iaHR0cHM6Ly92ZWN0YS5pby9uYW5vIj48cGF0aCBkPSJNMCAxMi40MDJsMzUuNjg3LTQuODYuMDE2IDM0LjQyMy0zNS42Ny4yMDN6bTM1LjY3IDMzLjUyOWwuMDI4IDM0LjQ1M0wuMDI4IDc1LjQ4LjAyNiA0NS43em00LjMyNi0zOS4wMjVMODcuMzE0IDB2NDEuNTI3bC00Ny4zMTguMzc2em00Ny4zMjkgMzkuMzQ5bC0uMDExIDQxLjM0LTQ3LjMxOC02LjY3OC0uMDY2LTM0LjczOXoiIGZpbGw9IiMwMGFkZWYiLz48L3N2Zz4=\" alt=\"windows-ci\" /\u003e\n    \u003c/a\u003e\n  \u003c/div\u003e\n\n  \u003cdiv\u003e\n    \u003ca href=\"https://codecov.io/gh/odygrd/quill\"\u003e\n      \u003cimg src=\"https://img.shields.io/codecov/c/gh/odygrd/quill/master.svg?logo=codecov\u0026style=flat-square\" alt=\"Codecov\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://app.codacy.com/gh/odygrd/quill/dashboard?utm_source=gh\u0026utm_medium=referral\u0026utm_content=\u0026utm_campaign=Badge_grade\"\u003e\n      \u003cimg src=\"https://img.shields.io/codacy/grade/cd387bc34658475d98bff84db3ad5287?logo=codacy\u0026style=flat-square\" alt=\"Codacy\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.codefactor.io/repository/github/odygrd/quill\"\u003e\n      \u003cimg src=\"https://img.shields.io/codefactor/grade/github/odygrd/quill?logo=codefactor\u0026style=flat-square\" alt=\"CodeFactor\" /\u003e\n    \u003c/a\u003e\n  \u003c/div\u003e\n\n  \u003cdiv\u003e\n    \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square\" alt=\"license\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://en.wikipedia.org/wiki/C%2B%2B17\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/language-C%2B%2B17-red.svg?style=flat-square\" alt=\"language\" /\u003e\n    \u003c/a\u003e\n  \u003c/div\u003e\n\n  \u003ch4\u003e\n    \u003ca href=\"https://quillcpp.readthedocs.io\" title=\"Explore the full documentation\"\u003e📚 Documentation\u003c/a\u003e\n    \u003cspan\u003e · \u003c/span\u003e\n    \u003ca href=\"https://quillcpp.readthedocs.io/en/latest/cheat_sheet.html\" title=\"Quick reference for common tasks\"\u003e⚡ Cheat Sheet\u003c/a\u003e\n    \u003cspan\u003e · \u003c/span\u003e\n    \u003ca href=\"https://github.com/odygrd/quill/issues/new?assignees=\u0026labels=\u0026projects=\u0026template=bug-report.md\u0026title=\" title=\"Report a bug or issue\"\u003e🐛 Report Bug\u003c/a\u003e\n    \u003cspan\u003e · \u003c/span\u003e\n    \u003ca href=\"https://github.com/odygrd/quill/issues/new?assignees=\u0026labels=\u0026projects=\u0026template=feature_request.md\u0026title=\"\u003e💡 Request Feature\u003c/a\u003e\n  \u003c/h4\u003e\n\n  \u003cdiv align=\"center\"\u003e\u003cimg src=\"docs/quill_demo.gif\" alt=\"Logging Demo\" width=\"75%\" /\u003e\u003c/div\u003e\n\u003c/div\u003e\n\n---\n\n## 🧭 Table of Contents\n\n- [Introduction](#-introduction)\n- [Quick Start](#-quick-start)\n- [Features](#-features)\n- [Performance](#-performance)\n- [Usage](#-usage)\n- [Design](#-design)\n- [Caveats](#-caveats)\n- [License](#-license)\n\n---\n\n## ✨ Introduction\n\n**Quill** is a **high-performance asynchronous logging library** written in **C++**. It is designed for low-latency, performance-critical applications where every microsecond counts.\n\n- **Performance-Focused**: Quill consistently outperforms many popular logging libraries.\n- **Feature-Rich**: Packed with advanced features to meet diverse logging needs.\n- **Battle-Tested**: Proven in demanding production environments.\n- **Extensive Documentation**: Comprehensive guides and examples available.\n- **Community-Driven**: Open to contributions, feedback, and feature requests.\n\nTry it on [Compiler Explorer](https://godbolt.org/z/szncr8c8d)\n\n---\n\n## ⏩ Quick Start\n\nGetting started is easy and straightforward. Follow these steps to integrate the library into your project:\n\n### Installation\n\nYou can install Quill using the package manager of your choice:\n\n| Package Manager |              Installation Command              |\n|:---------------:|:----------------------------------------------:|\n|      vcpkg      |             `vcpkg install quill`              |\n|      Conan      |             `conan install quill`              |\n|    Homebrew     |              `brew install quill`              |\n|  Meson WrapDB   |           `meson wrap install quill`           |\n|      Conda      |      `conda install -c conda-forge quill`      |\n|     Bzlmod      | `bazel_dep(name = \"quill\", version = \"x.y.z\")` |\n|      xmake      |             `xrepo install quill`              |\n|       nix       |            `nix-shell -p quill-log`            |\n\n### Setup\n\nOnce installed, you can start using Quill with the following code:\n\n```c++\n#include \"quill/Backend.h\"\n#include \"quill/Frontend.h\"\n#include \"quill/LogMacros.h\"\n#include \"quill/Logger.h\"\n#include \"quill/sinks/ConsoleSink.h\"\n#include \u003cstring_view\u003e\n\nint main()\n{\n  quill::Backend::start();\n\n  quill::Logger* logger = quill::Frontend::create_or_get_logger(\n    \"root\", quill::Frontend::create_or_get_sink\u003cquill::ConsoleSink\u003e(\"sink_id_1\"));\n\n  LOG_INFO(logger, \"Hello from {}!\", std::string_view{\"Quill\"});\n}\n```\n\n---\n\n## 🎯 Features\n\n- **High-Performance**: Ultra-low latency performance. View [Benchmarks](http://github.com/odygrd/quill#performance)\n- **Asynchronous Processing**: Background thread handles formatting and I/O, keeping your main thread responsive.\n- **Minimal Header Includes**:\n    - **Frontend**: Only `Logger.h` and `LogMacros.h` needed for logging. Lightweight with minimal dependencies.\n    - **Backend**: Single `.cpp` file inclusion. No backend code injection into other translation units.\n- **Compile-Time Optimization**: Eliminate specific log levels at compile time.\n- **Custom Formatters**: Define your own log output patterns.\n  See [Formatters](https://quillcpp.readthedocs.io/en/latest/formatters.html).\n- **Timestamp-Ordered Logs**: Simplify debugging of multithreaded applications with chronologically ordered logs.\n- **Flexible Timestamps**: Support for `rdtsc`, `chrono`, or `custom clocks` - ideal for simulations and more.\n- **Backtrace Logging**: Store messages in a ring buffer for on-demand display.\n  See [Backtrace Logging](https://quillcpp.readthedocs.io/en/latest/backtrace_logging.html)\n- **Multiple Output Sinks**: Console (with color), files (with rotation), JSON, ability to create custom sinks and more.\n- **Log Filtering**: Process only relevant messages.\n  See [Filters](https://quillcpp.readthedocs.io/en/latest/filters.html).\n- **JSON Logging**: Structured log output.\n  See [JSON Logging](https://quillcpp.readthedocs.io/en/latest/json_logging.html)\n- **Configurable Queue Modes**: `bounded/unbounded` and `blocking/dropping` options with monitoring on dropped messages,\n  queue reallocations, and blocked hot threads.\n- **Crash Handling**: Built-in signal handler for log preservation during crashes.\n- **Huge Pages Support (Linux)**: Leverage huge pages on the hot path for optimized performance.\n- **Wide Character Support (Windows)**: Compatible with ASCII-encoded wide strings and STL containers consisting of wide\n  strings.\n- **Exception-Free Option**: Configurable builds with or without exception handling.\n- **Clean Codebase**: Maintained to high standards, warning-free even at strict levels.\n- **Type-Safe API**: Built on [{fmt}](http://github.com/fmtlib/fmt) library.\n\n---\n\n## 🚀 Performance\n\n### System Configuration\n\n- **OS:** Linux RHEL 9.4\n- **CPU:** Intel Core i5-12600 (12th Gen) @ 4.8 GHz\n- **Compiler:** GCC 13.1\n- **Benchmark-Tuned System:** The system is specifically tuned for benchmarking.\n\n- **Command Line Parameters:**\n  ```shell\n  $ cat /proc/cmdline\n  BOOT_IMAGE=(hd0,gpt2)/vmlinuz-5.14.0-427.13.1.el9_4.x86_64 root=/dev/mapper/rhel-root ro crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet nohz=on nohz_full=1-5 rcu_nocbs=1-5 isolcpus=1-5 mitigations=off transparent_hugepage=never intel_pstate=disable nosoftlockup irqaffinity=0 processor.max_cstate=1 nosoftirqd sched_tick_offload=0 spec_store_bypass_disable=off spectre_v2=off iommu=pt\n  ```\n\nYou can find the benchmark code on the [logger_benchmarks](http://github.com/odygrd/logger_benchmarks) repository.\n\n### Latency\n\nThe results presented in the tables below are measured in `nanoseconds (ns)`.\n\nThe tables are sorted by the 95th percentile\n\n#### Logging Numbers\n\n`LOG_INFO(logger, \"Logging int: {}, int: {}, double: {}\", i, j, d)`.\n\n##### 1 Thread Logging\n\n| Library                                                        | 50th | 75th | 90th | 95th | 99th | 99.9th |\n|----------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:|\n| [Quill Bounded Dropping Queue](http://github.com/odygrd/quill) |  7   |  8   |  8   |  9   |  9   |   11   |\n| [fmtlog](http://github.com/MengRao/fmtlog)                     |  9   |  9   |  10  |  10  |  12  |   13   |\n| [Quill Unbounded Queue](http://github.com/odygrd/quill)        |  10  |  10  |  10  |  10  |  12  |   14   |\n| [PlatformLab NanoLog](http://github.com/PlatformLab/NanoLog)   |  13  |  14  |  16  |  17  |  19  |   25   |\n| [MS BinLog](http://github.com/Morgan-Stanley/binlog)           |  21  |  21  |  22  |  22  |  56  |   93   |\n| [XTR](https://github.com/choll/xtr)                            |  7   |  7   |  29  |  30  |  33  |   53   |\n| [Reckless](http://github.com/mattiasflodin/reckless)           |  26  |  28  |  31  |  32  |  35  |   49   |\n| [BqLog](https://github.com/Tencent/BqLog)                      |  29  |  29  |  30  |  49  |  56  |   71   |\n| [Iyengar NanoLog](http://github.com/Iyengar111/NanoLog)        |  83  |  96  | 117  | 125  | 152  |  197   |\n| [spdlog](http://github.com/gabime/spdlog)                      | 143  | 147  | 152  | 158  | 165  |  177   |\n| [g3log](http://github.com/KjellKod/g3log)                      | 1161 | 1259 | 1329 | 1419 | 1602 |  1827  |\n\n![numbers_1_thread_logging.webp](docs%2Fcharts%2Fnumbers_1_thread_logging.webp)\n\n##### 4 Threads Logging Simultaneously\n\n| Library                                                        | 50th | 75th | 90th | 95th | 99th | 99.9th |\n|----------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:|\n| [fmtlog](http://github.com/MengRao/fmtlog)                     |  8   |  9   |  9   |  10  |  11  |   13   |\n| [Quill Bounded Dropping Queue](http://github.com/odygrd/quill) |  8   |  9   |  10  |  10  |  12  |   14   |\n| [XTR](https://github.com/choll/xtr)                            |  7   |  8   |  9   |  11  |  31  |   38   | \n| [Quill Unbounded Queue](http://github.com/odygrd/quill)        |  10  |  11  |  11  |  12  |  13  |   15   |\n| [PlatformLab NanoLog](http://github.com/PlatformLab/NanoLog)   |  15  |  17  |  20  |  23  |  27  |   32   |\n| [MS BinLog](http://github.com/Morgan-Stanley/binlog)           |  21  |  22  |  22  |  23  |  62  |  100   |\n| [Reckless](http://github.com/mattiasflodin/reckless)           |  19  |  23  |  26  |  28  |  34  |   55   |\n| [BqLog](https://github.com/Tencent/BqLog)                      |  31  |  33  |  34  |  55  |  61  |   73   |\n| [Iyengar NanoLog](http://github.com/Iyengar111/NanoLog)        |  58  |  90  | 123  | 131  | 168  |  242   |\n| [spdlog](http://github.com/gabime/spdlog)                      | 210  | 243  | 288  | 313  | 382  |  694   |\n| [g3log](http://github.com/KjellKod/g3log)                      | 1271 | 1337 | 1396 | 1437 | 1614 |  1899  |\n\n![numbers_4_thread_logging.webp](docs%2Fcharts%2Fnumbers_4_thread_logging.webp)\n\n#### Logging Large Strings\n\nLogging `std::string` over 35 characters to prevent the short string optimization.\n\n`LOG_INFO(logger, \"Logging int: {}, int: {}, string: {}\", i, j, large_string)`.\n\n##### 1 Thread Logging\n\n| Library                                                        | 50th | 75th | 90th | 95th | 99th | 99.9th |\n|----------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:|\n| [Quill Bounded Dropping Queue](http://github.com/odygrd/quill) |  11  |  13  |  13  |  14  |  15  |   16   |\n| [fmtlog](http://github.com/MengRao/fmtlog)                     |  11  |  12  |  13  |  14  |  15  |   17   |\n| [Quill Unbounded Queue](http://github.com/odygrd/quill)        |  14  |  15  |  16  |  17  |  18  |   19   |\n| [MS BinLog](http://github.com/Morgan-Stanley/binlog)           |  22  |  23  |  24  |  25  |  61  |  100   |\n| [PlatformLab NanoLog](http://github.com/PlatformLab/NanoLog)   |  15  |  17  |  21  |  27  |  33  |   39   |\n| [XTR](https://github.com/choll/xtr)                            |  8   |  9   |  29  |  31  |  35  |   54   |\n| [BqLog](https://github.com/Tencent/BqLog)                      |  29  |  30  |  31  |  51  |  60  |   71   |\n| [Reckless](http://github.com/mattiasflodin/reckless)           |  91  | 107  | 115  | 118  | 124  |  135   |\n| [Iyengar NanoLog](http://github.com/Iyengar111/NanoLog)        |  86  |  97  | 119  | 128  | 159  |  268   |\n| [spdlog](http://github.com/gabime/spdlog)                      | 120  | 124  | 128  | 132  | 141  |  151   |\n| [g3log](http://github.com/KjellKod/g3log)                      | 881  | 956  | 1018 | 1089 | 1264 |  1494  |\n\n![large_strings_1_thread_logging.webp](docs%2Fcharts%2Flarge_strings_1_thread_logging.webp)\n\n##### 4 Threads Logging Simultaneously\n\n| Library                                                        | 50th | 75th | 90th | 95th | 99th | 99.9th |\n|----------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:|\n| [XTR](https://github.com/choll/xtr)                            |  9   |  11  |  13  |  14  |  32  |   40   |\n| [fmtlog](http://github.com/MengRao/fmtlog)                     |  11  |  12  |  13  |  14  |  16  |   19   |\n| [Quill Bounded Dropping Queue](http://github.com/odygrd/quill) |  13  |  14  |  15  |  16  |  17  |   19   |\n| [Quill Unbounded Queue](http://github.com/odygrd/quill)        |  15  |  16  |  17  |  18  |  19  |   21   |\n| [MS BinLog](http://github.com/Morgan-Stanley/binlog)           |  23  |  25  |  27  |  28  |  65  |  105   |\n| [PlatformLab NanoLog](http://github.com/PlatformLab/NanoLog)   |  16  |  20  |  32  |  38  |  44  |   51   |\n| [BqLog](https://github.com/Tencent/BqLog)                      |  32  |  33  |  35  |  56  |  64  |   76   |\n| [Reckless](http://github.com/mattiasflodin/reckless)           |  79  |  94  | 104  | 107  | 114  |  132   |\n| [Iyengar NanoLog](http://github.com/Iyengar111/NanoLog)        |  85  |  93  | 125  | 133  | 168  |  237   |\n| [spdlog](http://github.com/gabime/spdlog)                      | 178  | 218  | 261  | 281  | 381  |  651   |\n| [g3log](http://github.com/KjellKod/g3log)                      | 992  | 1055 | 1121 | 1178 | 1360 |  1600  |\n\n![large_strings_4_thread_logging.webp](docs%2Fcharts%2Flarge_strings_4_thread_logging.webp)\n\n#### Logging Complex Types\n\nLogging `std::vector\u003cstd::string\u003e` containing 16 large strings, each ranging from 50 to 60 characters.\n\nNote: some of the previous loggers do not support passing a `std::vector` as an argument.\n\n`LOG_INFO(logger, \"Logging int: {}, int: {}, vector: {}\", i, j, v)`.\n\n##### 1 Thread Logging\n\n| Library                                                        | 50th | 75th | 90th | 95th | 99th | 99.9th |\n|----------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:|\n| [Quill Bounded Dropping Queue](http://github.com/odygrd/quill) |  48  |  50  |  53  |  55  |  58  |   62   |\n| [Quill Unbounded Queue](http://github.com/odygrd/quill)        |  54  |  56  |  57  |  58  |  61  |   66   |\n| [MS BinLog](http://github.com/Morgan-Stanley/binlog)           |  68  |  69  |  72  |  74  |  79  |  281   |\n| [XTR](https://github.com/choll/xtr)                            | 284  | 294  | 340  | 346  | 356  |  575   |\n| [fmtlog](http://github.com/MengRao/fmtlog)                     | 711  | 730  | 754  | 770  | 804  |  834   |\n| [spdlog](http://github.com/gabime/spdlog)                      | 6191 | 6261 | 6330 | 6386 | 6633 |  7320  |\n\n![vector_1_thread_logging.webp](docs%2Fcharts%2Fvector_1_thread_logging.webp)\n\n##### 4 Threads Logging Simultaneously\n\n| Library                                                        | 50th | 75th | 90th | 95th | 99th | 99.9th |\n|----------------------------------------------------------------|:----:|:----:|:----:|:----:|:----:|:------:|\n| [Quill Bounded Dropping Queue](http://github.com/odygrd/quill) |  50  |  52  |  54  |  56  |  60  |   82   |\n| [MS BinLog](http://github.com/Morgan-Stanley/binlog)           |  70  |  72  |  75  |  79  |  88  |  286   |\n| [Quill Unbounded Queue](http://github.com/odygrd/quill)        |  97  | 107  | 116  | 122  | 135  |  148   |\n| [XTR](https://github.com/choll/xtr)                            | 512  | 711  | 761  | 791  | 865  |  945   |\n| [fmtlog](http://github.com/MengRao/fmtlog)                     | 780  | 804  | 823  | 835  | 860  |  896   |\n| [spdlog](http://github.com/gabime/spdlog)                      | 6469 | 6549 | 6641 | 6735 | 7631 |  9430  |\n\n![vector_4_thread_logging.webp](docs%2Fcharts%2Fvector_4_thread_logging.webp)\n\nThe benchmark methodology involves logging 20 messages in a loop, calculating and storing the average latency for those\n20 messages, then waiting around ~2 milliseconds, and repeating this process for a specified number of iterations.\n\n_In the `Quill Bounded Dropping` benchmarks, the dropping queue size is set to `262,144` bytes, which is double the\ndefault size of `131,072` bytes._\n\n### Throughput\n\nThroughput is measured by calculating the maximum number of log messages the backend logging thread can write to a log\nfile per second.\n\nThe tests were run on the same system used for the latency benchmarks.\n\nAlthough Quill’s primary focus is not on maximizing throughput, it efficiently manages log messages across multiple\nthreads. Benchmarking throughput of asynchronous logging libraries presents certain challenges. Some libraries may drop\nlog messages, leading to smaller-than-expected log files, while others only provide asynchronous flushing, making it\ndifficult to verify when the backend thread has fully processed all messages.\n\nFor comparison, we benchmark against other asynchronous logging libraries that offer guaranteed logging with a\nflush-and-wait mechanism.\n\nNote that `MS BinLog` writes log data to a binary file, which requires offline formatting with an additional\nprogram—this makes it an unfair comparison, but it is included for reference.\n\nSimilarly, `BqLog (binary log)` uses the compressed binary log appender, and its log files are not human-readable unless\nprocessed offline. However, it is included for reference. The other version of `BqLog` is using a text appender and\nproduces human-readable log files.\n\nIn the same way, `Platformlab Nanolog` also outputs binary logs and is expected to deliver high throughput. However, for\nreasons unexplained, the benchmark runs significantly slower (10x longer) than the other libraries, so it is excluded\nfrom the table.\n\nLogging 4 million times the message `\"Iteration: {} int: {} double: {}\"`\n\n| Library                                                           | million msg/second | elapsed time |\n|-------------------------------------------------------------------|:------------------:|:------------:|\n| [MS BinLog (binary log)](http://github.com/Morgan-Stanley/binlog) |       63.80        |    62 ms     |\n| [BqLog (binary log)](https://github.com/Tencent/BqLog)            |       15.92        |    251 ms    |\n| [Quill](http://github.com/odygrd/quill)                           |        5.70        |    701 ms    |\n| [BqLog](https://github.com/Tencent/BqLog)                         |        4.93        |    811 ms    |\n| [spdlog](http://github.com/gabime/spdlog)                         |        3.54        |   1128 ms    |\n| [fmtlog](http://github.com/MengRao/fmtlog)                        |        2.90        |   1378 ms    |\n| [Reckless](http://github.com/mattiasflodin/reckless)              |        2.72        |   1471 ms    |\n| [XTR](https://github.com/choll/xtr)                               |        2.61        |   1534 ms    |\n\n![throughput_chart.webp](docs%2Fcharts%2Fthroughput_chart.webp)\n\n### Compilation Time\n\nCompile times are measured using `clang 15` and for `Release` build.\n\nBelow, you can find the additional headers that the library will include when you need to log, following\nthe [recommended_usage](https://github.com/odygrd/quill/blob/master/examples/recommended_usage/recommended_usage.cpp)\nexample\n\n![quill_v5_1_compiler_profile.speedscope.png](docs%2Fquill_v5_1_compiler_profile.speedscope.png)\n\nThere is also a compile-time benchmark measuring the compilation time of 2000 auto-generated log statements with\nvarious arguments. You can find\nit [here](https://github.com/odygrd/quill/blob/master/benchmarks/compile_time/compile_time_bench.cpp). It takes\napproximately 30 seconds to compile.\n\n![quill_v5_1_compiler_bench.speedscope.png](docs%2Fquill_v5_1_compiler_bench.speedscope.png)\n\n### Verdict\n\nQuill excels in hot path latency benchmarks and supports high throughput, offering a rich set of features that outshines\nother logging libraries.\n\nThe human-readable log files facilitate easier debugging and analysis. While initially larger, they compress\nefficiently, with the size difference between human-readable and binary logs becoming minimal once zipped.\n\nFor example, for the same amount of messages:\n\n```\nms_binlog_backend_total_time.blog (binary log): 177 MB\nms_binlog_backend_total_time.zip (zipped binary log): 35 MB\n```\n\n```\nquill_backend_total_time.log (human-readable log): 448 MB\nquill_backend_total_time.zip (zipped human-readable log): 47 MB\n```\n\nIf Quill were not available, MS BinLog would be a strong alternative. It delivers great latency on the hot path and\ngenerates smaller binary log files. However, the binary logs necessitate offline processing with additional tools, which\ncan be less convenient.\n\n---\n\n## 🧩 Usage\n\nAlso, see the [Quick Start Guide](https://quillcpp.readthedocs.io/en/latest/quick_start.html) for a brief introduction.\n\n```c++\n#include \"quill/Backend.h\"\n#include \"quill/Frontend.h\"\n#include \"quill/LogMacros.h\"\n#include \"quill/Logger.h\"\n#include \"quill/sinks/ConsoleSink.h\"\n#include \"quill/std/Array.h\"\n\n#include \u003cstring\u003e\n#include \u003cutility\u003e\n\nint main()\n{\n  // Backend  \n  quill::BackendOptions backend_options;\n  quill::Backend::start(backend_options);\n\n  // Frontend\n  auto console_sink = quill::Frontend::create_or_get_sink\u003cquill::ConsoleSink\u003e(\"sink_id_1\");\n  quill::Logger* logger = quill::Frontend::create_or_get_logger(\"root\", std::move(console_sink));\n\n  // Change the LogLevel to print everything\n  logger-\u003eset_log_level(quill::LogLevel::TraceL3);\n\n  // A log message with number 123\n  int a = 123;\n  std::string l = \"log\";\n  LOG_INFO(logger, \"A {} message with number {}\", l, a);\n\n  // libfmt formatting language is supported 3.14e+00\n  double pi = 3.141592653589793;\n  LOG_INFO(logger, \"libfmt formatting language is supported {:.2e}\", pi);\n\n  // Logging STD types is supported [1, 2, 3]\n  std::array\u003cint, 3\u003e arr = {1, 2, 3};\n  LOG_INFO(logger, \"Logging STD types is supported {}\", arr);\n\n  // Logging STD types is supported [arr: [1, 2, 3]]\n  LOGV_INFO(logger, \"Logging STD types is supported\", arr);\n\n  // A message with two variables [a: 123, b: 3.17]\n  double b = 3.17;\n  LOGV_INFO(logger, \"A message with two variables\", a, b);\n\n  for (uint32_t i = 0; i \u003c 10; ++i)\n  {\n    // Will only log the message once per second\n    LOG_INFO_LIMIT(std::chrono::seconds{1}, logger, \"A {} message with number {}\", l, a);\n    LOGV_INFO_LIMIT(std::chrono::seconds{1}, logger, \"A message with two variables\", a, b);\n  }\n\n  LOG_TRACE_L3(logger, \"Support for floats {:03.2f}\", 1.23456);\n  LOG_TRACE_L2(logger, \"Positional arguments are {1} {0} \", \"too\", \"supported\");\n  LOG_TRACE_L1(logger, \"{:\u003e30}\", std::string_view {\"right aligned\"});\n  LOG_DEBUG(logger, \"Debugging foo {}\", 1234);\n  LOG_INFO(logger, \"Welcome to Quill!\");\n  LOG_WARNING(logger, \"A warning message.\");\n  LOG_ERROR(logger, \"An error message. error code {}\", 123);\n  LOG_CRITICAL(logger, \"A critical error.\");\n}\n```\n\n### Output\n\n![example_output.png](docs%2Fexample_output.png)\n\n### External CMake\n\n#### Building and Installing Quill\n\nTo get started with Quill, clone the repository and install it using CMake:\n\n```bash\ngit clone http://github.com/odygrd/quill.git\ncd quill\nmkdir cmake_build\ncd cmake_build\ncmake ..\nmake install\n```\n\n- **Custom Installation**: Specify a custom directory with `-DCMAKE_INSTALL_PREFIX=/path/to/install/dir`.\n- **Build Examples**: Include examples with `-DQUILL_BUILD_EXAMPLES=ON`.\n\nNext, add Quill to your project using `find_package()`:\n\n```cmake\nfind_package(quill REQUIRED)\ntarget_link_libraries(your_target PUBLIC quill::quill)\n```\n\n#### Sample Directory Structure\n\nOrganize your project directory like this:\n\n```\nmy_project/\n├── CMakeLists.txt\n├── main.cpp\n```\n\n#### Sample CMakeLists.txt\n\nHere’s a sample `CMakeLists.txt` to get you started:\n\n```cmake\n# If Quill is in a non-standard directory, specify its path.\nset(CMAKE_PREFIX_PATH /path/to/quill)\n\n# Find and link the Quill library.\nfind_package(quill REQUIRED)\nadd_executable(example main.cpp)\ntarget_link_libraries(example PUBLIC quill::quill)\n```\n\n### Embedded CMake\n\nFor a more integrated approach, embed Quill directly into your project:\n\n#### Sample Directory Structure\n\n```\nmy_project/\n├── quill/            # Quill repo folder\n├── CMakeLists.txt\n├── main.cpp\n```\n\n#### Sample CMakeLists.txt\n\nUse this `CMakeLists.txt` to include Quill directly:\n\n```cmake\ncmake_minimum_required(VERSION 3.1.0)\nproject(my_project)\n\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\n\nadd_subdirectory(quill)\nadd_executable(my_project main.cpp)\ntarget_link_libraries(my_project PUBLIC quill::quill)\n```\n\n### Android NDK\n\nWhen building Quill for Android, you might need to add this flag during configuration, but in most cases, it works without it:\n\n```bash\n-DQUILL_NO_THREAD_NAME_SUPPORT:BOOL=ON\n```\n\nFor timestamps, use `quill::ClockSourceType::System`. Quill also includes an `AndroidSink`, which integrates with Android's logging system.\n\n#### Minimal Example to Start Logging on Android\n\n```c++\nquill::Backend::start();\n\nauto sink = quill::Frontend::create_or_get_sink\u003cquill::AndroidSink\u003e(\"app\", [](){\n    quill::AndroidSinkConfig asc;\n    asc.set_tag(\"app\");\n    asc.set_format_message(true);\n    return asc;\n}());\n\nauto logger = quill::Frontend::create_or_get_logger(\"root\", std::move(sink),\n                                                    quill::PatternFormatterOptions {}, \n                                                    quill::ClockSourceType::System);\n\nLOG_INFO(logger, \"Test {}\", 123);\n```\n\n### Meson\n\n#### Using WrapDB\n\nEasily integrate Quill with Meson’s `wrapdb`:\n\n```bash\nmeson wrap install quill\n```\n\n#### Manual Integration\n\nCopy the repository contents to your `subprojects` directory and add the following to your `meson.build`:\n\n```meson\nquill = subproject('quill')\nquill_dep = quill.get_variable('quill_dep')\nmy_build_target = executable('name', 'main.cpp', dependencies : [quill_dep], install : true)\n```\n\n### Bazel\n\n#### Using Blzmod\n\nQuill is available on `BLZMOD` for easy integration.\n\n#### Manual Integration\n\nFor manual setup, add Quill to your `BUILD.bazel` file like this:\n\n```bazel\ncc_binary(name = \"app\", srcs = [\"main.cpp\"], deps = [\"//quill_path:quill\"])\n```\n\n---\n\n## 📐 Design\n\n### Frontend (caller-thread)\n\nWhen invoking a `LOG_` macro:\n\n1. Creates a static constexpr metadata object to store `Metadata` such as the format string and source location.\n\n2. Pushes the data SPSC lock-free queue. For each log message, the following variables are pushed\n\n| Variable   |                                                  Description                                                   |\n|------------|:--------------------------------------------------------------------------------------------------------------:|\n| timestamp  |                                               Current timestamp                                                |\n| Metadata*  |                                        Pointer to metadata information                                         |\n| Logger*    |                                         Pointer to the logger instance                                         |\n| DecodeFunc | A pointer to a templated function containing all the log message argument types, used for decoding the message |\n| Args...    |           A serialized binary copy of each log message argument that was passed to the `LOG_` macro            |\n\n### Backend\n\nConsumes each message from the SPSC queue, retrieves all the necessary information and then formats the message.\nSubsequently, forwards the log message to all Sinks associated with the Logger.\n\n![design.jpg](docs%2Fdesign.jpg)\n\n---\n\n## 🚨 Caveats\n\nQuill may not work well with `fork()` since it spawns a background thread and `fork()` doesn't work well with\nmultithreading.\n\nIf your application uses `fork()` and you want to log in the child processes as well, you should call `quill::start()`\nafter the `fork()` call. Additionally, you should ensure that you write to different files in the parent and child\nprocesses to avoid conflicts.\n\nFor example :\n\n```c++\n#include \"quill/Backend.h\"\n#include \"quill/Frontend.h\"\n#include \"quill/LogMacros.h\"\n#include \"quill/Logger.h\"\n#include \"quill/sinks/FileSink.h\"\n\nint main()\n{\n  // DO NOT CALL THIS BEFORE FORK\n  // quill::Backend::start();\n\n  if (fork() == 0)\n  {\n    quill::Backend::start();\n        \n    // Get or create a handler to the file - Write to a different file\n    auto file_sink = quill::Frontend::create_or_get_sink\u003cquill::FileSink\u003e(\n      \"child.log\");\n    \n    quill::Logger* logger = quill::Frontend::create_or_get_logger(\"root\", std::move(file_sink));\n\n    QUILL_LOG_INFO(logger, \"Hello from Child {}\", 123);\n  }\n  else\n  {\n    quill::Backend::start();\n          \n    // Get or create a handler to the file - Write to a different file\n    auto file_sink = quill::Frontend::create_or_get_sink\u003cquill::FileSink\u003e(\n      \"parent.log\");\n    \n    quill::Logger* logger = quill::Frontend::create_or_get_logger(\"root\", std::move(file_sink));\n    \n    QUILL_LOG_INFO(logger, \"Hello from Parent {}\", 123);\n  }\n}\n```\n\n---\n\n## 📝 License\n\nQuill is licensed under the [MIT License](http://opensource.org/licenses/MIT)\n\nQuill depends on third party libraries with separate copyright notices and license terms.\nYour use of the source code for these subcomponents is subject to the terms and conditions of the following licenses.\n\n- ([MIT License](http://opensource.org/licenses/MIT)) [{fmt}](http://github.com/fmtlib/fmt/blob/master/LICENSE.rst)\n- ([MIT License](http://opensource.org/licenses/MIT)) [doctest](http://github.com/onqtam/doctest/blob/master/LICENSE.txt)\n","funding_links":[],"categories":["Logging","C++","Footprints , Logging","进程间通信","Libraries \u0026 Frameworks:","C/C++程序设计"],"sub_categories":["UI Test Automation Scripting","日志","Other","资源传输下载"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fodygrd%2Fquill","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fodygrd%2Fquill","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fodygrd%2Fquill/lists"}