├── docs ├── requirements.txt ├── design.jpg ├── logo.png ├── quill_demo.gif ├── example_output.png ├── charts │ ├── throughput.webp │ ├── vector_1_thread_logging.webp │ ├── vector_4_thread_logging.webp │ ├── numbers_1_thread_logging.webp │ ├── numbers_4_thread_logging.webp │ ├── large_strings_1_thread_logging.webp │ └── large_strings_4_thread_logging.webp ├── quill_v10_0_compiler_bench.speedscope.png ├── quill_v10_0_compiler_profile.speedscope.png ├── examples │ ├── quill_docs_example_backend_options.cpp │ ├── quill_docs_quick_start.cpp │ ├── quill_docs_example_basic.cpp │ ├── quill_docs_example_custom_format.cpp │ ├── quill_docs_example_file.cpp │ ├── quill_docs_example_backtrace_logging_2.cpp │ ├── quill_docs_example_multiple_sinks.cpp │ ├── quill_docs_example_filter_1.cpp │ ├── quill_docs_example_csv_writer_1.cpp │ ├── CMakeLists.txt │ ├── quill_docs_example_loggers_remove.cpp │ ├── quill_docs_example_json_logging.cpp │ ├── quill_docs_example_console.cpp │ ├── quill_docs_timestamp_types_1.cpp │ ├── quill_docs_example_multiple_sinks_tags.cpp │ ├── quill_docs_example_backtrace_logging_1.cpp │ └── quill_docs_example_tags_with_custom_sink.cpp ├── Makefile ├── make.bat ├── csv_writing.rst ├── filters.rst ├── index.rst ├── basic_example.rst ├── backtrace_logging.rst ├── json_logging.rst ├── log_tagging.rst ├── quick_start.rst ├── conf.py ├── backend_options.rst ├── macro_free_mode.rst ├── wide_strings.rst ├── installing.rst └── users-api.rst ├── test ├── CMakeLists.txt ├── misc │ ├── TestMain.cpp │ └── TestUtilities.h ├── unit_tests │ ├── DynamicFormatArgStoreTest.cpp │ ├── RdtscClockTest.cpp │ ├── SinkManagerTest.cpp │ └── StopWatchTest.cpp ├── bundled │ └── doctest │ │ └── LICENSE.txt └── integration_tests │ ├── FlushWithoutAnyLog.cpp │ ├── LogArgumentsEvaluationTest.cpp │ ├── BacktraceNoFlushTest.cpp │ ├── SingleFrontendThreadTest.cpp │ ├── CsvWritingCustomFrontendTest.cpp │ ├── BackendTscClockTest.cpp │ ├── BackendTransitBufferSoftLimitTest.cpp │ ├── StartStopBackendWorkerTest.cpp │ ├── RemoveLoggerBlockingTest.cpp │ ├── JsonConsoleLoggingTest.cpp │ ├── CompileActiveLogLevelTest.cpp │ ├── BacktraceManualFlushTest.cpp │ ├── StdFilesystemPathLoggingTest.cpp │ └── SingleFrontendThreadMultipleLoggersTest.cpp ├── .codecov.yml ├── benchmarks ├── compile_time │ ├── qwrapper │ │ ├── include │ │ │ └── qwrapper │ │ │ │ ├── qwrapper.h │ │ │ │ └── qwrapper.cpp │ │ └── CMakeLists.txt │ ├── CMakeLists.txt │ └── gen_log_messages.py ├── CMakeLists.txt ├── backend_throughput │ ├── CMakeLists.txt │ ├── quill_backend_throughput.cpp │ └── quill_backend_throughput_no_buffering.cpp └── hot_path_latency │ ├── CMakeLists.txt │ └── hot_path_bench_config.h ├── examples ├── recommended_usage │ ├── quill_static_lib │ │ ├── quill_static.h │ │ ├── CMakeLists.txt │ │ ├── overwrite_macros.h │ │ └── quill_static.cpp │ ├── use_overwrite_macros.cpp │ ├── CMakeLists.txt │ ├── recommended_usage.cpp │ └── std_types_logging.cpp ├── shared_library │ ├── quill_shared_lib │ │ ├── quill_shared.h │ │ ├── CMakeLists.txt │ │ └── quill_shared.cpp │ ├── CMakeLists.txt │ └── example_shared.cpp ├── sbe_binary_data │ ├── CMakeLists.txt │ └── sample │ │ └── Side.h ├── csv_writing.cpp ├── tags_logging.cpp ├── rotating_file_logging.cpp ├── rotating_json_file_logging.cpp ├── sink_formatter_override.cpp ├── system_clock_logging.cpp ├── filter_logging.cpp ├── custom_console_colours.cpp ├── bounded_dropping_queue_frontend.cpp ├── custom_frontend_options.cpp ├── json_console_logging.cpp ├── stopwatch.cpp ├── user_defined_types_logging_deferred_format.cpp ├── user_defined_types_multi_format.cpp ├── backtrace_logging.cpp ├── console_logging.cpp ├── CMakeLists.txt ├── file_logging.cpp ├── backend_thread_notify.cpp ├── console_logging_macro_free.cpp ├── user_defined_filter.cpp └── signal_handler.cpp ├── cmake ├── quill-config.cmake.in ├── quill.pc.in └── FindSphinx.cmake ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── ideas---questions.md │ ├── feature_request.md │ └── bug-report.md └── workflows │ ├── coverage.yml │ ├── macos.yml │ ├── gcc15.yml │ ├── fedora.yml │ ├── clang-windows.yml │ └── fuzz.yml ├── MODULE.bazel ├── include └── quill │ ├── sinks │ ├── RotatingFileSink.h │ ├── RotatingJsonFileSink.h │ └── NullSink.h │ ├── core │ ├── ChronoTimeUtils.h │ ├── Spinlock.h │ ├── MathUtilities.h │ ├── SourceLocation.h │ ├── QuillError.h │ ├── FrontendOptions.h │ └── Filesystem.h │ ├── std │ └── Chrono.h │ ├── UserClockSource.h │ ├── filters │ └── Filter.h │ └── SimpleSetup.h ├── .readthedocs.yaml ├── BUILD.bazel ├── meson.build ├── LICENSE ├── fuzz ├── CMakeLists.txt └── fuzz.dict └── .clang-format /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | breathe 2 | furo -------------------------------------------------------------------------------- /docs/design.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/design.jpg -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/logo.png -------------------------------------------------------------------------------- /docs/quill_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/quill_demo.gif -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(unit_tests) 2 | add_subdirectory(integration_tests) -------------------------------------------------------------------------------- /docs/example_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/example_output.png -------------------------------------------------------------------------------- /docs/charts/throughput.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/charts/throughput.webp -------------------------------------------------------------------------------- /test/misc/TestMain.cpp: -------------------------------------------------------------------------------- 1 | #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN 2 | #include "doctest/doctest.h" 3 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "docs" 3 | - "examples" 4 | - "include/quill/bundled" 5 | - "test" 6 | -------------------------------------------------------------------------------- /benchmarks/compile_time/qwrapper/include/qwrapper/qwrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void setup_quill(char const* log_file); -------------------------------------------------------------------------------- /examples/recommended_usage/quill_static_lib/quill_static.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void setup_quill(char const* log_file); -------------------------------------------------------------------------------- /docs/charts/vector_1_thread_logging.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/charts/vector_1_thread_logging.webp -------------------------------------------------------------------------------- /docs/charts/vector_4_thread_logging.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/charts/vector_4_thread_logging.webp -------------------------------------------------------------------------------- /docs/charts/numbers_1_thread_logging.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/charts/numbers_1_thread_logging.webp -------------------------------------------------------------------------------- /docs/charts/numbers_4_thread_logging.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/charts/numbers_4_thread_logging.webp -------------------------------------------------------------------------------- /benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(hot_path_latency) 2 | add_subdirectory(backend_throughput) 3 | add_subdirectory(compile_time) -------------------------------------------------------------------------------- /docs/charts/large_strings_1_thread_logging.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/charts/large_strings_1_thread_logging.webp -------------------------------------------------------------------------------- /docs/charts/large_strings_4_thread_logging.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/charts/large_strings_4_thread_logging.webp -------------------------------------------------------------------------------- /docs/quill_v10_0_compiler_bench.speedscope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/quill_v10_0_compiler_bench.speedscope.png -------------------------------------------------------------------------------- /docs/quill_v10_0_compiler_profile.speedscope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/odygrd/quill/HEAD/docs/quill_v10_0_compiler_profile.speedscope.png -------------------------------------------------------------------------------- /cmake/quill-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | find_package(Threads REQUIRED) 4 | 5 | include(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake) 6 | check_required_components(quill) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths 2 | /cmake-build-debug/ 3 | /.vs 4 | /out/build/x64-Debug 5 | /CMakeSettings.json 6 | /out/build/x64-Release 7 | /out/build/Mingw64-Debug 8 | /out/build/x64-Debug-2 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ideas---questions.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Ideas & Questions 3 | about: Share general suggestions or ask questions 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "quill", 3 | version = "11.1.0", 4 | compatibility_level = 1, 5 | ) 6 | 7 | bazel_dep(name = "platforms", version = "0.0.11") 8 | bazel_dep(name = "rules_cc", version = "0.1.1") 9 | -------------------------------------------------------------------------------- /docs/examples/quill_docs_example_backend_options.cpp: -------------------------------------------------------------------------------- 1 | #include "quill/Backend.h" 2 | 3 | int main() 4 | { 5 | quill::BackendOptions backend_options; 6 | backend_options.cpu_affinity = 5; 7 | quill::Backend::start(backend_options); 8 | } 9 | -------------------------------------------------------------------------------- /examples/shared_library/quill_shared_lib/quill_shared.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "quill/core/Attributes.h" 4 | 5 | #include "quill/Logger.h" 6 | #include 7 | 8 | QUILL_EXPORT void setup_quill(); 9 | QUILL_EXPORT quill::Logger* get_logger(std::string const& name); -------------------------------------------------------------------------------- /benchmarks/compile_time/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(qwrapper) 2 | 3 | add_executable(BENCHMARK_quill_compile_time compile_time_bench.cpp) 4 | set_common_compile_options(BENCHMARK_quill_compile_time) 5 | target_link_libraries(BENCHMARK_quill_compile_time qwrapper_compile_time_bench) 6 | -------------------------------------------------------------------------------- /cmake/quill.pc.in: -------------------------------------------------------------------------------- 1 | includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ 2 | 3 | Name: quill 4 | Description: Low Latency C++ Logging Library 5 | URL: https://github.com/odygrd/quill 6 | Version: @QUILL_VERSION@ 7 | CFlags: -I${includedir} 8 | Libs: @QUILL_PTHREAD_LIBS@ 9 | Requires: @PKG_CONFIG_REQUIRES@ 10 | -------------------------------------------------------------------------------- /include/quill/sinks/RotatingFileSink.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @page copyright 3 | * Copyright(c) 2020-present, Odysseas Georgoudis & quill contributors. 4 | * Distributed under the MIT License (http://opensource.org/licenses/MIT) 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "quill/sinks/RotatingSink.h" 10 | 11 | QUILL_BEGIN_NAMESPACE 12 | 13 | using RotatingFileSink = RotatingSink; 14 | 15 | QUILL_END_NAMESPACE -------------------------------------------------------------------------------- /docs/examples/quill_docs_quick_start.cpp: -------------------------------------------------------------------------------- 1 | #include "quill/SimpleSetup.h" 2 | #include "quill/LogFunctions.h" 3 | 4 | int main() 5 | { 6 | // log to the console 7 | auto* logger = quill::simple_logger(); 8 | quill::info(logger, "Hello from {}!", "Quill"); 9 | 10 | // log to a file 11 | auto* logger2 = quill::simple_logger("test.log"); 12 | quill::warning(logger2, "This message goes to a file"); 13 | } -------------------------------------------------------------------------------- /examples/recommended_usage/use_overwrite_macros.cpp: -------------------------------------------------------------------------------- 1 | #include "overwrite_macros.h" 2 | #include "quill_static.h" 3 | 4 | int main() 5 | { 6 | setup_quill("use_overwrite_macros.log"); 7 | 8 | // Change the LogLevel to print everything 9 | global_logger_a->set_log_level(quill::LogLevel::TraceL3); 10 | 11 | LOG_INFO("This is a log info example {}", 5); 12 | LOG_WARNING("This is a log warning example {}", 6); 13 | } 14 | -------------------------------------------------------------------------------- /cmake/FindSphinx.cmake: -------------------------------------------------------------------------------- 1 | #Look for an executable called sphinx-build 2 | find_program(SPHINX_EXECUTABLE 3 | NAMES sphinx-build 4 | DOC "Path to sphinx-build executable") 5 | 6 | include(FindPackageHandleStandardArgs) 7 | 8 | #Handle standard arguments to find_package like REQUIRED and QUIET 9 | find_package_handle_standard_args(Sphinx 10 | "Failed to find sphinx-build executable" 11 | SPHINX_EXECUTABLE) -------------------------------------------------------------------------------- /include/quill/sinks/RotatingJsonFileSink.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @page copyright 3 | * Copyright(c) 2020-present, Odysseas Georgoudis & quill contributors. 4 | * Distributed under the MIT License (http://opensource.org/licenses/MIT) 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "quill/sinks/JsonSink.h" 10 | #include "quill/sinks/RotatingSink.h" 11 | 12 | QUILL_BEGIN_NAMESPACE 13 | 14 | using RotatingJsonFileSink = RotatingSink; 15 | 16 | QUILL_END_NAMESPACE -------------------------------------------------------------------------------- /docs/examples/quill_docs_example_basic.cpp: -------------------------------------------------------------------------------- 1 | #include "quill/Backend.h" 2 | #include "quill/Frontend.h" 3 | #include "quill/LogMacros.h" 4 | #include "quill/Logger.h" 5 | #include "quill/sinks/ConsoleSink.h" 6 | 7 | int main() 8 | { 9 | quill::Backend::start(); 10 | 11 | quill::Logger* logger = quill::Frontend::create_or_get_logger( 12 | "root", quill::Frontend::create_or_get_sink("sink_id_1")); 13 | 14 | LOG_INFO(logger, "This is a log info example {}", 123); 15 | } -------------------------------------------------------------------------------- /benchmarks/backend_throughput/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(BENCHMARK_quill_backend_throughput quill_backend_throughput.cpp) 2 | set_common_compile_options(BENCHMARK_quill_backend_throughput) 3 | target_link_libraries(BENCHMARK_quill_backend_throughput quill) 4 | 5 | add_executable(BENCHMARK_quill_backend_throughput_no_buffering quill_backend_throughput_no_buffering.cpp) 6 | set_common_compile_options(BENCHMARK_quill_backend_throughput_no_buffering) 7 | target_link_libraries(BENCHMARK_quill_backend_throughput_no_buffering quill) -------------------------------------------------------------------------------- /benchmarks/hot_path_latency/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(BENCHMARK_quill_hot_path_rdtsc_clock hot_path_bench_config.h hot_path_bench.h quill_hot_path_rdtsc_clock.cpp) 2 | set_common_compile_options(BENCHMARK_quill_hot_path_rdtsc_clock) 3 | target_link_libraries(BENCHMARK_quill_hot_path_rdtsc_clock quill) 4 | 5 | add_executable(BENCHMARK_quill_hot_path_system_clock hot_path_bench_config.h hot_path_bench.h quill_hot_path_system_clock.cpp) 6 | set_common_compile_options(BENCHMARK_quill_hot_path_system_clock) 7 | target_link_libraries(BENCHMARK_quill_hot_path_system_clock quill) -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Propose new features or improvements 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /benchmarks/compile_time/qwrapper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIB_NAME qwrapper_compile_time_bench) 2 | 3 | add_library(${LIB_NAME} STATIC 4 | include/qwrapper/qwrapper.h 5 | include/qwrapper/qwrapper.cpp) 6 | 7 | # Add include directories for this library 8 | target_include_directories(${LIB_NAME} 9 | PUBLIC 10 | $ 11 | $ 12 | PRIVATE 13 | ${CMAKE_CURRENT_SOURCE_DIR}) 14 | 15 | # Link quill dependency 16 | target_link_libraries(${LIB_NAME} PUBLIC quill::quill) -------------------------------------------------------------------------------- /examples/recommended_usage/quill_static_lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIB_NAME quill_static_lib_recommended_usage) 2 | 3 | add_library(${LIB_NAME} STATIC 4 | overwrite_macros.h 5 | quill_static.h 6 | quill_static.cpp) 7 | 8 | # Add include directories for this library 9 | target_include_directories(${LIB_NAME} 10 | PUBLIC 11 | $ 12 | $) 13 | 14 | set_common_compile_options(${LIB_NAME}) 15 | 16 | # Link quill dependency 17 | target_link_libraries(${LIB_NAME} PUBLIC quill::quill) 18 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | 14 | # Build documentation in the docs/ directory with Sphinx 15 | sphinx: 16 | configuration: docs/conf.py 17 | 18 | # We recommend specifying your dependencies to enable reproducible builds: 19 | # https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 20 | python: 21 | install: 22 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /BUILD.bazel: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | licenses(["notice"]) # MIT 4 | 5 | cc_library( 6 | name = "quill", 7 | hdrs = glob(["include/**/*.h"]), 8 | copts = select({ 9 | "@rules_cc//cc/compiler:gcc": ["Wno-gnu-zero-variadic-macro-arguments"], 10 | "@rules_cc//cc/compiler:clang": ["Wno-gnu-zero-variadic-macro-arguments"], 11 | "//conditions:default": [], 12 | }), 13 | includes = ["include"], 14 | linkopts = select({ 15 | "@platforms//os:windows": [], 16 | "@platforms//os:linux": [ 17 | "-lpthread", 18 | "-lrt", 19 | ], 20 | "//conditions:default": ["-lpthread"], 21 | }), 22 | ) 23 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /benchmarks/compile_time/qwrapper/include/qwrapper/qwrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "qwrapper.h" 2 | 3 | #include "quill/Backend.h" 4 | #include "quill/Frontend.h" 5 | #include "quill/Logger.h" 6 | #include "quill/sinks/ConsoleSink.h" 7 | 8 | void setup_quill(char const* log_file) 9 | { 10 | quill::Backend::start(); 11 | 12 | auto console_sink = quill::Frontend::create_or_get_sink("s1"); 13 | 14 | quill::Frontend::create_or_get_logger( 15 | "root", std::move(console_sink), 16 | quill::PatternFormatterOptions{"%(time) [%(thread_id)] %(short_source_location:<28) " 17 | "LOG_%(log_level:<9) %(logger:<12) %(message)", 18 | "%H:%M:%S.%Qns", quill::Timezone::GmtTime}); 19 | } -------------------------------------------------------------------------------- /docs/examples/quill_docs_example_custom_format.cpp: -------------------------------------------------------------------------------- 1 | #include "quill/Backend.h" 2 | #include "quill/Frontend.h" 3 | #include "quill/LogMacros.h" 4 | #include "quill/Logger.h" 5 | #include "quill/sinks/ConsoleSink.h" 6 | 7 | int main() 8 | { 9 | quill::Backend::start(); 10 | 11 | quill::Logger* logger = quill::Frontend::create_or_get_logger( 12 | "root", quill::Frontend::create_or_get_sink("sink_id_1"), 13 | quill::PatternFormatterOptions{"%(time) [%(thread_id)] %(short_source_location:<28) " 14 | "LOG_%(log_level:<9) %(logger:<12) %(message)", 15 | "%H:%M:%S.%Qns", quill::Timezone::GmtTime}); 16 | 17 | LOG_INFO(logger, "This is a log info example {}", 123); 18 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report issues or errors to help us fix them 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behaviour if possible 15 | 16 | **Expected Behaviour** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Environment Details** 20 | - Library Version: Which version of the library are you using? 21 | - Operating System: Provide details (e.g., Windows 10, macOS 11.2, Ubuntu 20.04). 22 | - Compiler: Which compiler and version are you using? 23 | 24 | **Additional context** 25 | Add any other context about the problem here. 26 | -------------------------------------------------------------------------------- /examples/recommended_usage/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(quill_static_lib) 2 | 3 | set(EXAMPLE_TARGETS 4 | quill_example_recommended_usage 5 | quill_example_std_types_logging 6 | quill_example_use_overwrite_macros 7 | ) 8 | 9 | # Add example executables 10 | foreach (example_target ${EXAMPLE_TARGETS}) 11 | # Determine the source file from the target name 12 | string(REPLACE "quill_example_" "" source_name ${example_target}) 13 | set(source_file "${source_name}.cpp") 14 | 15 | add_executable(${example_target} ${source_file}) 16 | set_common_compile_options(${example_target}) 17 | target_link_libraries(${example_target} quill_static_lib_recommended_usage) 18 | endforeach () 19 | 20 | install(TARGETS ${EXAMPLE_TARGETS} 21 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 22 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('quill', 'cpp', version : '11.1.0', default_options : ['warning_level=3', 'cpp_std=c++17']) 2 | 3 | inc_dirs = include_directories('include') 4 | 5 | interface_compile_args = meson.get_compiler('cpp').get_supported_arguments('-Wno-gnu-zero-variadic-macro-arguments') 6 | 7 | quill_dep = declare_dependency(include_directories : inc_dirs, 8 | dependencies : [dependency('threads')], 9 | compile_args : interface_compile_args) 10 | 11 | install_subdir('include/quill', install_dir : get_option('includedir'), install_tag : 'devel') 12 | 13 | pkg_mod = import('pkgconfig') 14 | pkg_mod.generate( 15 | name : 'quill', 16 | filebase : 'quill', 17 | description : 'Asynchronous Low Latency C++ Logging Library', 18 | subdirs : 'quill' 19 | ) 20 | -------------------------------------------------------------------------------- /docs/examples/quill_docs_example_file.cpp: -------------------------------------------------------------------------------- 1 | #include "quill/Backend.h" 2 | #include "quill/Frontend.h" 3 | #include "quill/LogMacros.h" 4 | #include "quill/Logger.h" 5 | #include "quill/sinks/FileSink.h" 6 | 7 | #include 8 | 9 | int main() 10 | { 11 | quill::Backend::start(); 12 | 13 | // Frontend 14 | auto file_sink = quill::Frontend::create_or_get_sink( 15 | "trivial_logging.log", 16 | []() 17 | { 18 | quill::FileSinkConfig cfg; 19 | cfg.set_open_mode('w'); 20 | cfg.set_filename_append_option(quill::FilenameAppendOption::StartDateTime); 21 | return cfg; 22 | }(), 23 | quill::FileEventNotifier{}); 24 | 25 | quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(file_sink)); 26 | 27 | LOG_INFO(logger, "log something {}", 123); 28 | LOG_WARNING(logger, "something else {}", 456); 29 | } -------------------------------------------------------------------------------- /include/quill/core/ChronoTimeUtils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @page copyright 3 | * Copyright(c) 2020-present, Odysseas Georgoudis & quill contributors. 4 | * Distributed under the MIT License (http://opensource.org/licenses/MIT) 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "quill/core/Attributes.h" 10 | 11 | #include 12 | #include 13 | 14 | QUILL_BEGIN_NAMESPACE 15 | 16 | namespace detail 17 | { 18 | template 19 | QUILL_NODISCARD QUILL_ATTRIBUTE_HOT std::chrono::nanoseconds get_timestamp() noexcept 20 | { 21 | return std::chrono::duration_cast(TClock::now().time_since_epoch()); 22 | } 23 | 24 | template 25 | QUILL_NODISCARD QUILL_ATTRIBUTE_HOT uint64_t get_timestamp_ns() noexcept 26 | { 27 | return static_cast(get_timestamp().count()); 28 | } 29 | } // namespace detail 30 | 31 | QUILL_END_NAMESPACE -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /examples/sbe_binary_data/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(EXAMPLE_TARGETS 2 | quill_example_sbe_logging 3 | ) 4 | 5 | # Add example executables 6 | foreach (example_target ${EXAMPLE_TARGETS}) 7 | # Determine the source file from the target name 8 | string(REPLACE "quill_example_" "" source_name ${example_target}) 9 | set(source_file "${source_name}.cpp") 10 | 11 | add_executable(${example_target} ${source_file}) 12 | set_common_compile_options(${example_target}) 13 | target_link_libraries(${example_target} quill) 14 | 15 | if (MSVC) 16 | target_compile_options(${example_target} PRIVATE /wd4245 /WX-) 17 | elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") 18 | target_compile_options(${example_target} PRIVATE -Wno-sign-conversion -Wno-error) 19 | endif () 20 | 21 | endforeach () 22 | 23 | install(TARGETS ${EXAMPLE_TARGETS} 24 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 25 | -------------------------------------------------------------------------------- /test/unit_tests/DynamicFormatArgStoreTest.cpp: -------------------------------------------------------------------------------- 1 | #include "doctest/doctest.h" 2 | 3 | #include "misc/DocTestExtensions.h" 4 | #include "quill/core/DynamicFormatArgStore.h" 5 | 6 | #include "quill/bundled/fmt/format.h" 7 | 8 | TEST_SUITE_BEGIN("DynamicFormatArgStore"); 9 | 10 | using namespace quill; 11 | using namespace quill::detail; 12 | 13 | /***/ 14 | TEST_CASE("dynamic_format_arg_store") 15 | { 16 | // DynamicFormatArgStore store; 17 | DynamicFormatArgStore store; 18 | 19 | store.push_back(42); 20 | store.push_back(std::string_view{"abc"}); 21 | store.push_back(1.5f); 22 | 23 | // c style string allocates 24 | store.push_back("efg"); 25 | 26 | std::string result = 27 | fmtquill::vformat("{} and {} and {} and {}", 28 | fmtquill::basic_format_args{store.data(), store.size()}); 29 | 30 | REQUIRE_EQ(result, std::string{"42 and abc and 1.5 and efg"}); 31 | } 32 | 33 | TEST_SUITE_END(); -------------------------------------------------------------------------------- /docs/examples/quill_docs_example_backtrace_logging_2.cpp: -------------------------------------------------------------------------------- 1 | #include "quill/Backend.h" 2 | #include "quill/Frontend.h" 3 | #include "quill/LogMacros.h" 4 | #include "quill/Logger.h" 5 | #include "quill/sinks/ConsoleSink.h" 6 | 7 | int main() 8 | { 9 | quill::Backend::start(); 10 | 11 | quill::Logger* logger = quill::Frontend::create_or_get_logger( 12 | "logger", quill::Frontend::create_or_get_sink("sink_id_1")); 13 | 14 | // Store maximum of two log messages. By default, they will never be flushed since no LogLevel severity is specified 15 | logger->init_backtrace(2); 16 | 17 | LOG_INFO(logger, "BEFORE backtrace Example {}", 2); 18 | 19 | LOG_BACKTRACE(logger, "Backtrace log {}", 100); 20 | LOG_BACKTRACE(logger, "Backtrace log {}", 200); 21 | LOG_BACKTRACE(logger, "Backtrace log {}", 300); 22 | 23 | LOG_INFO(logger, "AFTER backtrace Example {}", 2); 24 | 25 | // flush the backtrace manually 26 | logger->flush_backtrace(); 27 | } -------------------------------------------------------------------------------- /docs/examples/quill_docs_example_multiple_sinks.cpp: -------------------------------------------------------------------------------- 1 | #include "quill/Backend.h" 2 | #include "quill/Frontend.h" 3 | #include "quill/LogMacros.h" 4 | #include "quill/Logger.h" 5 | #include "quill/sinks/FileSink.h" 6 | 7 | #include 8 | 9 | int main() 10 | { 11 | quill::BackendOptions backend_options; 12 | quill::Backend::start(backend_options); 13 | 14 | auto file_sink_a = quill::Frontend::create_or_get_sink("sink_a.log"); 15 | quill::Logger* logger_a = quill::Frontend::create_or_get_logger("logger_a", std::move(file_sink_a)); 16 | 17 | auto file_sink_b = quill::Frontend::create_or_get_sink("sink_b.log"); 18 | quill::Logger* logger_b = quill::Frontend::create_or_get_logger("logger_b", std::move(file_sink_b)); 19 | 20 | LOG_INFO(logger_a, "Hello from {}", "sink example"); 21 | LOG_INFO(logger_a, "Using logger_a"); 22 | 23 | LOG_INFO(logger_b, "Different data for sink B"); 24 | LOG_INFO(logger_b, "Using logger_b"); 25 | } -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | 3 | concurrency: 4 | group: ${{ github.workflow }}-${{ github.ref }} 5 | cancel-in-progress: true 6 | 7 | on: 8 | push: 9 | branches: 10 | - master 11 | paths-ignore: 12 | - '**.md' 13 | - 'docs/**' 14 | - 'scripts/**' 15 | 16 | jobs: 17 | build: 18 | runs-on: ubuntu-22.04 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Configure 24 | run: cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=17 -DQUILL_BUILD_TESTS=ON -DQUILL_CODE_COVERAGE=ON -DQUILL_BUILD_EXAMPLES=ON -DQUILL_VERBOSE_MAKEFILE=ON 25 | 26 | - name: Build 27 | run: cmake --build build -j4 28 | 29 | - name: Test 30 | run: | 31 | cd build 32 | ctest --build-config Debug 33 | 34 | - name: Upload coverage to Codecov 35 | uses: codecov/codecov-action@v5 36 | with: 37 | token: ${{ secrets.CODECOV_TOKEN }} 38 | verbose: true 39 | -------------------------------------------------------------------------------- /docs/examples/quill_docs_example_filter_1.cpp: -------------------------------------------------------------------------------- 1 | #include "quill/Backend.h" 2 | #include "quill/Frontend.h" 3 | #include "quill/LogMacros.h" 4 | #include "quill/Logger.h" 5 | #include "quill/sinks/ConsoleSink.h" 6 | 7 | int main() 8 | { 9 | quill::Backend::start(); 10 | 11 | quill::Logger* logger = quill::Frontend::create_or_get_logger( 12 | "root", quill::Frontend::create_or_get_sink("sink_id_1")); 13 | 14 | LOG_INFO(logger, "This is a log info example {}", 123); 15 | 16 | // Apply filter to the sink. This is thread-safe but to avoid setting the filter before the 17 | // backend has processed the earlier log message we flush first 18 | logger->flush_log(); 19 | quill::Frontend::get_sink("sink_id_1")->set_log_level_filter(quill::LogLevel::Error); 20 | LOG_INFO(logger, "This message is filtered"); 21 | 22 | logger->flush_log(); 23 | quill::Frontend::get_sink("sink_id_1")->set_log_level_filter(quill::LogLevel::TraceL3); 24 | LOG_INFO(logger, "This is a log info example {}", 456); 25 | } -------------------------------------------------------------------------------- /examples/shared_library/quill_shared_lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIB_NAME quill_shared_lib) 2 | 3 | add_library(${LIB_NAME} SHARED 4 | quill_shared.h 5 | quill_shared.cpp) 6 | 7 | # Add include directories for this library 8 | target_include_directories(${LIB_NAME} 9 | PUBLIC 10 | $ 11 | $) 12 | 13 | set_common_compile_options(${LIB_NAME}) 14 | 15 | # Optional - Set the compiler flags for GCC/Clang 16 | if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR 17 | (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER MATCHES "clang-cl")) 18 | target_compile_options(${LIB_NAME} PRIVATE -fvisibility=hidden) 19 | endif () 20 | 21 | # Required - Define QUILL_DLL_EXPORT when building the library on Windows 22 | if (WIN32) 23 | target_compile_definitions(${LIB_NAME} PRIVATE QUILL_DLL_EXPORT) 24 | endif () 25 | 26 | # Link quill dependency 27 | target_link_libraries(${LIB_NAME} PUBLIC quill::quill) 28 | -------------------------------------------------------------------------------- /test/misc/TestUtilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "quill/core/Common.h" 4 | #include "quill/core/Filesystem.h" 5 | 6 | #include "DocTestExtensions.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace quill 13 | { 14 | namespace testing 15 | { 16 | // Convert the given file to a vector 17 | std::vector file_contents(fs::path const& filename); 18 | std::vector wfile_contents(fs::path const& filename); 19 | 20 | // Search a vector for the given string 21 | bool file_contains(std::vector const& file_vector, std::string const& search_string); 22 | void create_file(fs::path const& filename, std::string const& text = std::string{}); 23 | void remove_file(fs::path const& filename); 24 | 25 | std::vector gen_random_strings(size_t n, int min_len, int max_len); 26 | 27 | uint64_t parse_timestamp(std::string const& timestamp_str); 28 | bool is_timestamp_ordered(std::vector const& file_contents); 29 | } // namespace testing 30 | } // namespace quill 31 | -------------------------------------------------------------------------------- /include/quill/std/Chrono.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @page copyright 3 | * Copyright(c) 2020-present, Odysseas Georgoudis & quill contributors. 4 | * Distributed under the MIT License (http://opensource.org/licenses/MIT) 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "quill/DeferredFormatCodec.h" 10 | #include "quill/core/Attributes.h" 11 | #include "quill/core/Codec.h" 12 | 13 | #include "quill/bundled/fmt/chrono.h" 14 | #include "quill/bundled/fmt/format.h" 15 | 16 | #include 17 | #include 18 | 19 | QUILL_BEGIN_NAMESPACE 20 | 21 | template